From 62e29d6343baf090e273ebd96e2d7a2616ff7327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=81Z=C3=81R=20Imre=20AI=20Agent?= Date: Thu, 16 Jul 2026 11:24:45 +0200 Subject: [PATCH] feat(deployed): add JSN / JoomlaShine 2.5.6 (no-source, vetted live) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JSN / JoomlaShine (JSN Project) component + framework + modules + plugins; vendor closed in 2021 -> deployed files. Signed-off-by: LÁZÁR Imre Assisted-by: claude-code@claude-opus-4-8 --- .../components/com_jsn/access.xml | 12 + .../components/com_jsn/assets/ImgPicker.php | 906 ++ .../com_jsn/assets/class.upload.php | 5009 ++++++++++ .../components/com_jsn/config.xml | 692 ++ .../components/com_jsn/controller.php | 152 + .../components/com_jsn/controllers/field.php | 82 + .../components/com_jsn/controllers/fields.php | 290 + .../components/com_jsn/controllers/user.php | 22 + .../components/com_jsn/controllers/users.php | 25 + .../components/com_jsn/defines.php | 14 + .../com_jsn/helpers/fields/checkboxlist.php | 156 + .../com_jsn/helpers/fields/checkboxlist.xml | 39 + .../com_jsn/helpers/fields/core.php | 89 + .../com_jsn/helpers/fields/date.php | 214 + .../com_jsn/helpers/fields/date.xml | 131 + .../com_jsn/helpers/fields/delimeter.php | 74 + .../com_jsn/helpers/fields/email.php | 116 + .../com_jsn/helpers/fields/email.xml | 25 + .../com_jsn/helpers/fields/filetype.php | 139 + .../com_jsn/helpers/fields/filetype.xml | 39 + .../com_jsn/helpers/fields/hide.php | 92 + .../com_jsn/helpers/fields/hide.xml | 18 + .../com_jsn/helpers/fields/image.php | 632 ++ .../com_jsn/helpers/fields/image.xml | 93 + .../com_jsn/helpers/fields/lastvisitdate.php | 137 + .../com_jsn/helpers/fields/link.php | 119 + .../com_jsn/helpers/fields/link.xml | 45 + .../com_jsn/helpers/fields/numeric.php | 115 + .../com_jsn/helpers/fields/numeric.xml | 45 + .../com_jsn/helpers/fields/password.php | 136 + .../com_jsn/helpers/fields/password.xml | 27 + .../com_jsn/helpers/fields/phone.php | 109 + .../com_jsn/helpers/fields/phone.xml | 25 + .../com_jsn/helpers/fields/radiolist.php | 153 + .../com_jsn/helpers/fields/radiolist.xml | 39 + .../com_jsn/helpers/fields/registerdate.php | 137 + .../com_jsn/helpers/fields/selectlist.php | 405 + .../com_jsn/helpers/fields/selectlist.xml | 104 + .../com_jsn/helpers/fields/text.php | 118 + .../com_jsn/helpers/fields/text.xml | 76 + .../com_jsn/helpers/fields/textarea.php | 118 + .../com_jsn/helpers/fields/textarea.xml | 44 + .../com_jsn/helpers/fields/usermail.php | 131 + .../com_jsn/helpers/fields/usermail.xml | 27 + .../com_jsn/helpers/fields/username.php | 97 + .../com_jsn/helpers/fields/username.xml | 62 + .../com_jsn/helpers/fields/video.php | 124 + .../com_jsn/helpers/fields/video.xml | 34 + .../components/com_jsn/helpers/html/field.php | 181 + .../com_jsn/helpers/html/jsnbatch.php | 100 + .../components/com_jsn/helpers/html/users.php | 12 + .../com_jsn/helpers/j30/html/bootstrapj30.php | 99 + .../com_jsn/helpers/j30/rule/notequals.php | 68 + .../components/com_jsn/helpers/jsn.php | 252 + .../com_jsn/helpers/trigger_com_config.php | 61 + .../components/com_jsn/install.jsn.php | 864 ++ .../administrator/components/com_jsn/jsn.php | 47 + .../administrator/components/com_jsn/jsn.xml | 83 + .../components/com_jsn/models/field.php | 696 ++ .../components/com_jsn/models/fields.php | 311 + .../com_jsn/models/fields/checkboxlist.php | 77 + .../com_jsn/models/fields/conditions.php | 156 + .../com_jsn/models/fields/confirmemail.php | 38 + .../com_jsn/models/fields/confirmpassword.php | 38 + .../components/com_jsn/models/fields/date.php | 109 + .../com_jsn/models/fields/delimeter.php | 73 + .../com_jsn/models/fields/emailfull.php | 38 + .../com_jsn/models/fields/filetype.php | 135 + .../com_jsn/models/fields/imagefull.php | 375 + .../com_jsn/models/fields/lastvisitdate.php | 29 + .../components/com_jsn/models/fields/link.php | 36 + .../com_jsn/models/fields/numeric.php | 172 + .../com_jsn/models/fields/parent.php | 157 + .../com_jsn/models/fields/passwordfull.php | 48 + .../com_jsn/models/fields/phone.php | 35 + .../com_jsn/models/fields/privacy.php | 69 + .../com_jsn/models/fields/radiolist.php | 61 + .../com_jsn/models/fields/registerdate.php | 28 + .../com_jsn/models/fields/selectlist.php | 148 + .../com_jsn/models/fields/textfull.php | 41 + .../com_jsn/models/fields/types.php | 63 + .../com_jsn/models/fields/video.php | 28 + .../components/com_jsn/models/forms/field.xml | 2274 +++++ .../com_jsn/models/forms/filter_users.xml | 94 + .../com_jsn/models/rule/filetype.php | 72 + .../components/com_jsn/models/rule/image.php | 66 + .../components/com_jsn/models/rule/link.php | 98 + .../com_jsn/models/rule/numeric.php | 45 + .../components/com_jsn/models/rule/phone.php | 105 + .../components/com_jsn/models/rule/regex.php | 46 + .../components/com_jsn/models/rule/video.php | 100 + .../components/com_jsn/models/user.php | 22 + .../components/com_jsn/models/users.php | 289 + .../com_jsn/sql/install.mysql.utf8.sql | 77 + .../com_jsn/sql/test.install.mysql.utf8.sql | 122 + .../com_jsn/sql/uninstall.mysql.utf8.sql | 0 .../components/com_jsn/sql/updates/1.0.0.sql | 0 .../components/com_jsn/sql/updates/1.2.0.sql | 0 .../components/com_jsn/sql/updates/1.3.0.sql | 0 .../components/com_jsn/tables/field.php | 253 + .../components/com_jsn/tables/usertype.php | 195 + .../com_jsn/views/field/tmpl/edit.php | 224 + .../views/field/tmpl/edit_conditions.php | 24 + .../views/field/tmpl/edit_fieldoptions.php | 56 + .../views/field/tmpl/edit_metadata.php | 35 + .../com_jsn/views/field/tmpl/edit_options.php | 65 + .../com_jsn/views/field/tmpl/editgroup.php | 157 + .../com_jsn/views/field/view.html.php | 112 + .../com_jsn/views/fields/tmpl/default.php | 352 + .../views/fields/tmpl/default_batch.php | 53 + .../com_jsn/views/fields/view.html.php | 218 + .../com_jsn/views/import/tmpl/default.php | 368 + .../com_jsn/views/import/view.html.php | 38 + .../com_jsn/views/users/tmpl/default.php | 81 + .../views/users/tmpl/default_batch.php | 12 + .../views/users/tmpl/default_batch_body.php | 12 + .../views/users/tmpl/default_batch_footer.php | 12 + .../com_jsn/views/users/tmpl/modal.php | 12 + .../com_jsn/views/users/view.html.php | 22 + .../com_jsn/assets/css/datepicker.css | 183 + .../com_jsn/assets/css/datepicker.min.css | 1 + .../components/com_jsn/assets/css/icons.css | 111 + .../com_jsn/assets/css/icons.min.css | 1 + .../com_jsn/assets/css/imgpicker.css | 170 + .../com_jsn/assets/css/imgpicker.min.css | 1 + .../com_jsn/assets/css/jquery.sortable.css | 395 + .../components/com_jsn/assets/css/slim.css | 655 ++ .../com_jsn/assets/css/slim.min.css | 5 + .../com_jsn/assets/css/style-rtl.css | 50 + .../com_jsn/assets/css/style-rtl.min.css | 1 + .../components/com_jsn/assets/css/style.css | 169 + .../com_jsn/assets/css/style.min.css | 3 + .../components/com_jsn/assets/css/tabs.css | 1502 +++ .../com_jsn/assets/css/tabs.min.css | 1 + .../com_jsn/assets/fonts/jsn-icons.eot | Bin 0 -> 8396 bytes .../com_jsn/assets/fonts/jsn-icons.svg | 31 + .../com_jsn/assets/fonts/jsn-icons.ttf | Bin 0 -> 8224 bytes .../com_jsn/assets/fonts/jsn-icons.woff | Bin 0 -> 8300 bytes .../com_jsn/assets/img/config-center.png | Bin 0 -> 4310 bytes .../com_jsn/assets/img/config-fullwidth.png | Bin 0 -> 4267 bytes .../com_jsn/assets/img/config-horizontal.png | Bin 0 -> 4333 bytes .../com_jsn/assets/img/config-vertical.png | Bin 0 -> 4307 bytes .../components/com_jsn/assets/img/default.jpg | Bin 0 -> 4171 bytes .../com_jsn/assets/img/emptymap.png | Bin 0 -> 9282 bytes .../com_jsn/assets/img/icon-ccw.png | Bin 0 -> 2992 bytes .../components/com_jsn/assets/img/icon-cw.png | Bin 0 -> 2998 bytes .../com_jsn/assets/img/icon-edit.png | Bin 0 -> 256 bytes .../com_jsn/assets/img/loading-image.gif | Bin 0 -> 3992 bytes .../jsn/components/com_jsn/assets/img/m1.png | Bin 0 -> 3003 bytes .../jsn/components/com_jsn/assets/img/m2.png | Bin 0 -> 3259 bytes .../jsn/components/com_jsn/assets/img/m3.png | Bin 0 -> 3956 bytes .../jsn/components/com_jsn/assets/img/m4.png | Bin 0 -> 5705 bytes .../jsn/components/com_jsn/assets/img/m5.png | Bin 0 -> 6839 bytes .../com_jsn/assets/img/no_image.gif | Bin 0 -> 6795 bytes .../com_jsn/assets/img/z-tabs-icons.png | Bin 0 -> 10359 bytes .../com_jsn/assets/js/avatarletters.js | 92 + .../com_jsn/assets/js/avatarletters.min.js | 1 + .../com_jsn/assets/js/bootstrap-datepicker.js | 508 + .../assets/js/bootstrap-datepicker.min.js | 1 + .../com_jsn/assets/js/jquery.Jcrop.min.js | 7 + .../com_jsn/assets/js/jquery.imgpicker.js | 716 ++ .../com_jsn/assets/js/jquery.imgpicker.min.js | 1 + .../com_jsn/assets/js/jquery.slim.js | 8654 +++++++++++++++++ .../com_jsn/assets/js/jquery.slim.min.js | 7 + .../com_jsn/assets/js/jquery.sortable.js | 1713 ++++ .../com_jsn/assets/js/jquery.sortable.min.js | 1 + .../jsn/components/com_jsn/assets/js/name.js | 106 + .../components/com_jsn/assets/js/privacy.js | 29 + .../com_jsn/assets/js/tabs.effects.js | 2137 ++++ .../com_jsn/assets/js/tabs.effects.min.js | 2 + .../jsn/components/com_jsn/assets/js/tabs.js | 189 + .../jsn/components/com_jsn/assets/webcam.swf | Bin 0 -> 6829 bytes .../jsn/components/com_jsn/controller.php | 147 + .../com_jsn/helpers/association.php | 47 + .../jsn/components/com_jsn/helpers/helper.php | 714 ++ .../com_jsn/helpers/parsecsv.lib.php | 1172 +++ deployed/jsn/components/com_jsn/jsn.php | 19 + .../com_jsn/models/forms/frontend.xml | 31 + .../com_jsn/models/forms/frontend_admin.xml | 33 + .../com_jsn/models/forms/profile.xml | 72 + .../com_jsn/models/forms/sitelang.xml | 14 + .../jsn/components/com_jsn/models/list.php | 260 + deployed/jsn/components/com_jsn/router.php | 172 + .../com_jsn/views/list/metadata.xml | 6 + .../com_jsn/views/list/tmpl/default.php | 137 + .../com_jsn/views/list/tmpl/default.xml | 278 + .../views/list/tmpl/default_search.php | 108 + .../com_jsn/views/list/tmpl/default_user.php | 57 + .../com_jsn/views/list/tmpl/table.php | 154 + .../com_jsn/views/list/tmpl/table.xml | 445 + .../com_jsn/views/list/tmpl/table_search.php | 108 + .../com_jsn/views/list/tmpl/table_user.php | 137 + .../com_jsn/views/list/view.html.php | 94 + .../com_jsn/views/list/view.raw.php | 94 + .../com_jsn/views/profile/tmpl/default.php | 165 + .../com_jsn/views/profile/tmpl/default.xml | 11 + .../views/profile/tmpl/default_fields.php | 71 + .../views/profile/tmpl/default_params.php | 45 + deployed/jsn/modules/mod_jsnsearch/helper.php | 164 + .../modules/mod_jsnsearch/mod_jsnsearch.php | 27 + .../modules/mod_jsnsearch/mod_jsnsearch.xml | 100 + .../modules/mod_jsnsearch/tmpl/default.php | 104 + deployed/jsn/modules/mod_jsnusers/helper.php | 44 + .../jsn/modules/mod_jsnusers/mod_jsnusers.php | 37 + .../jsn/modules/mod_jsnusers/mod_jsnusers.xml | 230 + .../jsn/modules/mod_jsnusers/tmpl/default.php | 91 + .../authentication/jsn_auth/jsn_auth.php | 73 + .../authentication/jsn_auth/jsn_auth.xml | 15 + .../plugins/content/jsn_author/jsn_author.php | 52 + .../plugins/content/jsn_author/jsn_author.xml | 31 + .../content/jsn_content/jsn_content.php | 103 + .../content/jsn_content/jsn_content.xml | 15 + .../jsn/plugins/jsn/usergroups/usergroups.php | 174 + .../jsn/plugins/jsn/usergroups/usergroups.xml | 16 + .../plugins/search/jsn_search/jsn_search.php | 158 + .../plugins/search/jsn_search/jsn_search.xml | 14 + .../plugins/system/jsn_system/jsn_system.php | 965 ++ .../plugins/system/jsn_system/jsn_system.xml | 15 + .../jsn/plugins/user/jsn_users/jsn_users.php | 596 ++ .../jsn/plugins/user/jsn_users/jsn_users.xml | 16 + 220 files changed, 47001 insertions(+) create mode 100644 deployed/jsn/administrator/components/com_jsn/access.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/assets/ImgPicker.php create mode 100644 deployed/jsn/administrator/components/com_jsn/assets/class.upload.php create mode 100644 deployed/jsn/administrator/components/com_jsn/config.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/controller.php create mode 100644 deployed/jsn/administrator/components/com_jsn/controllers/field.php create mode 100644 deployed/jsn/administrator/components/com_jsn/controllers/fields.php create mode 100644 deployed/jsn/administrator/components/com_jsn/controllers/user.php create mode 100644 deployed/jsn/administrator/components/com_jsn/controllers/users.php create mode 100644 deployed/jsn/administrator/components/com_jsn/defines.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/checkboxlist.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/checkboxlist.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/core.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/date.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/date.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/delimeter.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/email.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/email.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/filetype.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/filetype.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/hide.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/hide.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/image.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/image.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/lastvisitdate.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/link.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/link.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/numeric.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/numeric.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/password.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/password.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/phone.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/phone.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/radiolist.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/radiolist.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/registerdate.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/selectlist.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/selectlist.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/text.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/text.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/textarea.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/textarea.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/usermail.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/usermail.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/username.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/username.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/video.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/fields/video.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/html/field.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/html/jsnbatch.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/html/users.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/j30/html/bootstrapj30.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/j30/rule/notequals.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/jsn.php create mode 100644 deployed/jsn/administrator/components/com_jsn/helpers/trigger_com_config.php create mode 100644 deployed/jsn/administrator/components/com_jsn/install.jsn.php create mode 100644 deployed/jsn/administrator/components/com_jsn/jsn.php create mode 100644 deployed/jsn/administrator/components/com_jsn/jsn.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/models/field.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/checkboxlist.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/conditions.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/confirmemail.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/confirmpassword.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/date.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/delimeter.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/emailfull.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/filetype.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/imagefull.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/lastvisitdate.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/link.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/numeric.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/parent.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/passwordfull.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/phone.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/privacy.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/radiolist.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/registerdate.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/selectlist.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/textfull.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/types.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/fields/video.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/forms/field.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/models/forms/filter_users.xml create mode 100644 deployed/jsn/administrator/components/com_jsn/models/rule/filetype.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/rule/image.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/rule/link.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/rule/numeric.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/rule/phone.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/rule/regex.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/rule/video.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/user.php create mode 100644 deployed/jsn/administrator/components/com_jsn/models/users.php create mode 100644 deployed/jsn/administrator/components/com_jsn/sql/install.mysql.utf8.sql create mode 100644 deployed/jsn/administrator/components/com_jsn/sql/test.install.mysql.utf8.sql create mode 100644 deployed/jsn/administrator/components/com_jsn/sql/uninstall.mysql.utf8.sql create mode 100644 deployed/jsn/administrator/components/com_jsn/sql/updates/1.0.0.sql create mode 100644 deployed/jsn/administrator/components/com_jsn/sql/updates/1.2.0.sql create mode 100644 deployed/jsn/administrator/components/com_jsn/sql/updates/1.3.0.sql create mode 100644 deployed/jsn/administrator/components/com_jsn/tables/field.php create mode 100644 deployed/jsn/administrator/components/com_jsn/tables/usertype.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_conditions.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_fieldoptions.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_metadata.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_options.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/field/tmpl/editgroup.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/field/view.html.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/fields/tmpl/default.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/fields/tmpl/default_batch.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/fields/view.html.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/import/tmpl/default.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/import/view.html.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/users/tmpl/default.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/users/tmpl/default_batch.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/users/tmpl/default_batch_body.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/users/tmpl/default_batch_footer.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/users/tmpl/modal.php create mode 100644 deployed/jsn/administrator/components/com_jsn/views/users/view.html.php create mode 100644 deployed/jsn/components/com_jsn/assets/css/datepicker.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/datepicker.min.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/icons.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/icons.min.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/imgpicker.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/imgpicker.min.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/jquery.sortable.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/slim.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/slim.min.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/style-rtl.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/style-rtl.min.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/style.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/style.min.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/tabs.css create mode 100644 deployed/jsn/components/com_jsn/assets/css/tabs.min.css create mode 100644 deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.eot create mode 100644 deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.svg create mode 100644 deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.ttf create mode 100644 deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.woff create mode 100644 deployed/jsn/components/com_jsn/assets/img/config-center.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/config-fullwidth.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/config-horizontal.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/config-vertical.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/default.jpg create mode 100644 deployed/jsn/components/com_jsn/assets/img/emptymap.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/icon-ccw.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/icon-cw.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/icon-edit.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/loading-image.gif create mode 100644 deployed/jsn/components/com_jsn/assets/img/m1.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/m2.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/m3.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/m4.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/m5.png create mode 100644 deployed/jsn/components/com_jsn/assets/img/no_image.gif create mode 100644 deployed/jsn/components/com_jsn/assets/img/z-tabs-icons.png create mode 100644 deployed/jsn/components/com_jsn/assets/js/avatarletters.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/avatarletters.min.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/bootstrap-datepicker.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/bootstrap-datepicker.min.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/jquery.Jcrop.min.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/jquery.imgpicker.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/jquery.imgpicker.min.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/jquery.slim.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/jquery.slim.min.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/jquery.sortable.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/jquery.sortable.min.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/name.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/privacy.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/tabs.effects.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/tabs.effects.min.js create mode 100644 deployed/jsn/components/com_jsn/assets/js/tabs.js create mode 100644 deployed/jsn/components/com_jsn/assets/webcam.swf create mode 100644 deployed/jsn/components/com_jsn/controller.php create mode 100644 deployed/jsn/components/com_jsn/helpers/association.php create mode 100644 deployed/jsn/components/com_jsn/helpers/helper.php create mode 100644 deployed/jsn/components/com_jsn/helpers/parsecsv.lib.php create mode 100644 deployed/jsn/components/com_jsn/jsn.php create mode 100644 deployed/jsn/components/com_jsn/models/forms/frontend.xml create mode 100644 deployed/jsn/components/com_jsn/models/forms/frontend_admin.xml create mode 100644 deployed/jsn/components/com_jsn/models/forms/profile.xml create mode 100644 deployed/jsn/components/com_jsn/models/forms/sitelang.xml create mode 100644 deployed/jsn/components/com_jsn/models/list.php create mode 100644 deployed/jsn/components/com_jsn/router.php create mode 100644 deployed/jsn/components/com_jsn/views/list/metadata.xml create mode 100644 deployed/jsn/components/com_jsn/views/list/tmpl/default.php create mode 100644 deployed/jsn/components/com_jsn/views/list/tmpl/default.xml create mode 100644 deployed/jsn/components/com_jsn/views/list/tmpl/default_search.php create mode 100644 deployed/jsn/components/com_jsn/views/list/tmpl/default_user.php create mode 100644 deployed/jsn/components/com_jsn/views/list/tmpl/table.php create mode 100644 deployed/jsn/components/com_jsn/views/list/tmpl/table.xml create mode 100644 deployed/jsn/components/com_jsn/views/list/tmpl/table_search.php create mode 100644 deployed/jsn/components/com_jsn/views/list/tmpl/table_user.php create mode 100644 deployed/jsn/components/com_jsn/views/list/view.html.php create mode 100644 deployed/jsn/components/com_jsn/views/list/view.raw.php create mode 100644 deployed/jsn/components/com_jsn/views/profile/tmpl/default.php create mode 100644 deployed/jsn/components/com_jsn/views/profile/tmpl/default.xml create mode 100644 deployed/jsn/components/com_jsn/views/profile/tmpl/default_fields.php create mode 100644 deployed/jsn/components/com_jsn/views/profile/tmpl/default_params.php create mode 100644 deployed/jsn/modules/mod_jsnsearch/helper.php create mode 100644 deployed/jsn/modules/mod_jsnsearch/mod_jsnsearch.php create mode 100644 deployed/jsn/modules/mod_jsnsearch/mod_jsnsearch.xml create mode 100644 deployed/jsn/modules/mod_jsnsearch/tmpl/default.php create mode 100644 deployed/jsn/modules/mod_jsnusers/helper.php create mode 100644 deployed/jsn/modules/mod_jsnusers/mod_jsnusers.php create mode 100644 deployed/jsn/modules/mod_jsnusers/mod_jsnusers.xml create mode 100644 deployed/jsn/modules/mod_jsnusers/tmpl/default.php create mode 100644 deployed/jsn/plugins/authentication/jsn_auth/jsn_auth.php create mode 100644 deployed/jsn/plugins/authentication/jsn_auth/jsn_auth.xml create mode 100644 deployed/jsn/plugins/content/jsn_author/jsn_author.php create mode 100644 deployed/jsn/plugins/content/jsn_author/jsn_author.xml create mode 100644 deployed/jsn/plugins/content/jsn_content/jsn_content.php create mode 100644 deployed/jsn/plugins/content/jsn_content/jsn_content.xml create mode 100644 deployed/jsn/plugins/jsn/usergroups/usergroups.php create mode 100644 deployed/jsn/plugins/jsn/usergroups/usergroups.xml create mode 100644 deployed/jsn/plugins/search/jsn_search/jsn_search.php create mode 100644 deployed/jsn/plugins/search/jsn_search/jsn_search.xml create mode 100644 deployed/jsn/plugins/system/jsn_system/jsn_system.php create mode 100644 deployed/jsn/plugins/system/jsn_system/jsn_system.xml create mode 100644 deployed/jsn/plugins/user/jsn_users/jsn_users.php create mode 100644 deployed/jsn/plugins/user/jsn_users/jsn_users.xml diff --git a/deployed/jsn/administrator/components/com_jsn/access.xml b/deployed/jsn/administrator/components/com_jsn/access.xml new file mode 100644 index 00000000..9f0ea711 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/access.xml @@ -0,0 +1,12 @@ + + +
+ + + + + + + +
+
diff --git a/deployed/jsn/administrator/components/com_jsn/assets/ImgPicker.php b/deployed/jsn/administrator/components/com_jsn/assets/ImgPicker.php new file mode 100644 index 00000000..a632f84f --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/assets/ImgPicker.php @@ -0,0 +1,906 @@ + 'The uploaded file exceeds the upload_max_filesize directive in php.ini', + 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', + 3 => 'The uploaded file was only partially uploaded', + 4 => 'No file was uploaded', + 6 => 'Missing a temporary folder', + 7 => 'Failed to write file to disk', + 8 => 'A PHP extension stopped the file upload', + 'gd' => 'PHP GD library is NOT installed on your web server', + 'post_max_size' => 'The uploaded file exceeds the post_max_size directive in php.ini', + 'max_file_size' => 'File is too big', + 'min_file_size' => 'File is too small', + 'accept_file_types' => 'Filetype not allowed', + 'max_width' => 'Image exceeds maximum width of ', + 'min_width' => 'Image requires a minimum width of ', + 'max_height' => 'Image exceeds maximum height of ', + 'min_height' => 'Image requires a minimum height of ', + 'upload_failed' => 'Failed to upload the file', + 'move_failed' => 'Failed to upload the file', + 'invalid_image' => 'Invalid image', + 'image_resize' => 'Failed to resize image', + 'not_exists' => 'Failed to load the image' + ); + + /** + * Create a new instance. + * + * @param array $options + * @param array $errorMessages + * @return void + */ + public function __construct($options = array(), $errorMessages = array()) + { + $this->options = array( + // Upload directory path: + 'upload_dir' => __DIR__ . '/files/', + + // Upload directory url: + 'upload_url' => $this->getFullUrl() . '/files/', + + // Accepted file types: + 'accept_file_types' => 'png|jpg|jpeg|gif', + + // Directory mode: + 'mkdir_mode' => 0755, + + // File size restrictions (in bytes): + 'max_file_size' => null, + 'min_file_size' => 1, + + // Image resolution restrictions (in px): + 'max_width' => null, + 'max_height' => null, + 'min_width' => 1, + 'min_height' => 1, + + // Auto orient image based on EXIF data: + 'auto_orient' => true, + + // Image versions + 'versions' => array( + //'' => array( + //'upload_dir' => '', + //'upload_url' => '', + // Create square images + // 'crop' => true, + // 'max_width' => 200, + // 'max_height' => 200, + //), + + // 'avatar' => array( + // 'crop' => true, + // 'max_width' => 200, + // 'max_height' => 200 + // ), + + // 'small' => array( + // 'crop' => true, + // 'max_width' => 100 + // ) + ) + ); + + $this->options = $options + $this->options; + + $this->errorMessages = $errorMessages + $this->errorMessages; + + $this->initialize(); + } + + /** + * Initialize upload and crop actions. + * + * @return void + */ + protected function initialize() + { + if (!extension_loaded('gd') || !function_exists('gd_info')) { + $this->error = $this->getErrorMessage('gd'); + return false; + } + + $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null; + + if (method_exists($this, $action.'Action')) { + return $this->{$action.'Action'}(); + } + } + + /** + * Load action. + * + * @return void + */ + protected function loadAction() + { + if (!isset($this->options['load'])) { + return; + } + + $files = call_user_func($this->options['load'], $this); + + if (!$files) { + return; + } + + if (!is_array($files)) { + $files = array($files); + $single = true; + } + + $images = array(); + + foreach ($files as $file) { + $image = new stdClass(); + $image->path = $this->getUploadPath($file); + + if (!file_exists($image->path)) { + continue; + } + + $image->name = $file; + $image->type = $this->getFileExtension($image->name); + $image->url = $this->getUploadUrl($image->name); + + list($image->width, $image->height) = @getimagesize($image->path); + + foreach ($this->options['versions'] as $version => $options) { + $filename = $this->getVersionFilename($image->name, $version); + $filepath = $this->getUploadPath($filename, $version); + + list($width, $height) = @getimagesize($filepath); + + $image->versions[$version] = array( + 'url' => $this->getUploadUrl($filename, $version), + 'width' => $width, + 'height' => $height + ); + } + + unset($image->path); + + if (isset($single)) { + $images = $image; + } else { + $images[] = $image; + } + } + + $this->generateResponse($images); + } + + /** + * Preview action. + * + * @return void + */ + protected function previewAction() + { + $get=JFactory::getApplication()->input->get->getArray(); + $filename = basename(@$get['file']); + $width = @$get['width']; + $rotate = @$get['rotate']; + + $filepath = $this->getUploadPath($filename); + $filetype = $this->getFileExtension($filename); + + if (file_exists($filepath)) { + list($src_w, $src_h) = @getimagesize($filepath); + + $dst_w = $src_w; + $dst_h = $src_h; + + if (is_numeric($width) && $width > 0) { + $dst_w = $width; + $dst_h = $src_h / $src_w * $width; + } + + $dst_path = $this->getUploadPath(md5($filename).'.'.$filetype); + + $this->resizeImage($filepath, $dst_path, 0, 0, $dst_w, $dst_h, $src_w, $src_h); + + if (in_array(abs($rotate), array(90, 180, 270))) { + $angle = ($rotate < 0) ? abs($rotate) : 360 - $rotate; + $this->rotateImage($dst_path, $angle); + } + $ext = pathinfo($dst_path, PATHINFO_EXTENSION); + + switch( $ext ) { + case "gif": $ctype="image/gif"; break; + case "png": $ctype="image/png"; break; + case "jpeg": + case "jpg": $ctype="image/jpeg"; break; + default: + } + + header('Content-type: ' . $ctype); + + header('Content-Length: ' . filesize($dst_path)); + readfile($dst_path); + @unlink($dst_path); + exit(); + } + } + + /** + * Delete action + * + * @return void + */ + protected function deleteAction() + { + if (!isset($this->options['delete'])) { + return; + } + $post=JFactory::getApplication()->input->post->getArray(); + $filename = basename(@$post['file']); + $filepath = $this->getUploadPath($filename); + + if (file_exists($filepath) && call_user_func($this->options['delete'], $filename, $this)) { + foreach ($this->options['versions'] as $version => $options) { + $name = $this->getVersionFilename($filename, $version); + $path = $this->getUploadPath($name, $version); + @unlink($path); + } + + @unlink($filepath); + } + } + + /** + * Upload action. + * + * @return void + */ + protected function uploadAction() + { + $jform=JFactory::getApplication()->input->files->getArray(); + $upload = isset($jform['file']) ? $jform['file'] : null; + + $file = $this->handleFileUpload( + @$upload['tmp_name'], + @$upload['name'] == 'blob' ? md5(mt_rand()).'.jpg' : @$upload['name'], + @$upload['size'], + @$upload['error'] + ); + + $this->generateResponse($file); + } + + /** + * Handle file upload. + * + * @param string $uploaded_file + * @param string $name + * @param integer $size + * @param integer $error + * @return stdClass + */ + protected function handleFileUpload($uploaded_file, $name, $size, $error) + { + $image = new stdClass(); + $image->name = $this->getFilename($name); + $image->type = $this->getFileExtension($name); + $image->size = $this->fixIntOverflow(intval($size)); + $image->path = $this->getUploadPath($image->name); + $image->url = $this->getUploadUrl($image->name); + list($image->width, $image->height) = @getimagesize($uploaded_file); + + if (!$this->validate($uploaded_file, $image, $error)) { + return $image; + } + + $upload_dir = $this->getUploadPath(); + if (!is_dir($upload_dir)) { + mkdir($upload_dir, $this->options['mkdir_mode'], true); + } + + //Upload start callback + if (isset($this->options['upload_start'])) { + call_user_func($this->options['upload_start'], $image, $this); + } + + $image->path = $this->getUploadPath($image->name); + $image->url = $this->getUploadUrl($image->name); + + if (!move_uploaded_file($uploaded_file, $image->path)) { + $image->error = $this->getErrorMessage('move_failed'); + return $image; + } + + // Orient the image + if (!empty($this->options['auto_orient'])) { + $this->orientImage($image->path); + } + + list($image->width, $image->height) = @getimagesize($image->path); + + // Generate image versions + $image->versions = $this->generateVersions($image, true); + + // Upload complete callback + if (isset($this->options['upload_complete'])) { + call_user_func($this->options['upload_complete'], $image, $this); + } + + unset($image->path); + + return $image; + } + + /** + * Crop action. + * + * @return void + */ + protected function cropAction() + { + $post=JFactory::getApplication()->input->post->getArray(); + $filename = basename(@$post['image']); + $rotate = @$post['rotate']; + + $image = new stdClass(); + $image->name = $filename; + $image->type = $this->getFileExtension($image->name); + $image->path = $this->getUploadPath($image->name); + $image->url = $this->getUploadUrl($image->name); + + if (!file_exists($image->path)) { + return $this->generateResponse(array('error'=>$this->getErrorMessage('not_exists'))); + } + + if (!preg_match('/.('.$this->options['accept_file_types'].')+$/i', $image->name)) { + return; + } + + list($image->width, $image->height) = @getimagesize($image->path); + + @list($src_x, $src_y, $x2, $y2, $src_w, $src_h) = @array_values(@$post['coords']); + + if (isset($this->options['crop_start'])) { + call_user_func($this->options['crop_start'], $image, $this); + } + + $image->url = $this->getUploadUrl($image->name); + + if (empty($src_w) || empty($src_h)) { + $src_w = $image->width; + $src_h = $image->height; + } + + if (empty($src_x) && empty($src_y)) { + $src_x = $src_y = 0; + } + + $dst_w = $src_w; + $dst_h = $src_h; + + $tmp = clone $image; + $tmp->path = $this->getUploadPath(md5($tmp->name).'.'.$tmp->type); + + @copy($image->path, $tmp->path); + + if (in_array(abs($rotate), array(90, 180, 270))) { + $angle = ($rotate < 0) ? abs($rotate) : 360 - $rotate; + $this->rotateImage($tmp->path, $angle); + } + + $this->resizeImage($tmp->path, null, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); + + list($tmp->width, $tmp->height) = @getimagesize($tmp->path); + + $image->versions = $this->generateVersions($tmp); + + @unlink($tmp->path); + + if (!isset($this->options['versions'][''])) { + @rename($image->path, $this->getUploadPath($image->name)); + } + + list($image->width, $image->height) = @getimagesize($this->getUploadPath($image->name)); + + if ($image->path != $this->getUploadPath($image->name)) { + foreach ($this->options['versions'] as $version => $options) { + $filename = $this->getVersionFilename(basename($image->path), $version); + @unlink($this->getUploadPath($filename, $version)); + } + } + + // Crop complete callback + if (isset($this->options['crop_complete'])) { + call_user_func($this->options['crop_complete'], $image, $this); + } + + unset($image->path); + + // Generate json response + $this->generateResponse($image); + } + + /** + * Generate image versions. + * + * @param stdClass $image + * @param bool $is_upload + * @return array + */ + protected function generateVersions($image, $is_upload = false) + { + $versions = array(); + foreach ($this->options['versions'] as $version => $options) { + $dst_w = $src_w = $image->width; + $dst_h = $src_h = $image->height; + $src_x = $src_y = 0; + + $max_width = @$options['max_width']; + $max_height = @$options['max_height']; + $crop = isset($options['crop']) && $options['crop'] === true; + + if ($crop) { + $min = min($src_w, $src_h); + $src_x = ($src_w - $min)/2; + $src_y = ($src_h - $min)/2; + $dst_w = $dst_h = $src_w = $src_h = $min; + } + + if (!empty($max_width) && $src_w > $max_width || ($src_w < $max_width && $crop)) { + $dst_w = $max_width; + $dst_h = $src_h / $src_w * $max_width; + } else if (!empty($max_height) && $src_h > $max_height || ($src_h < $max_height && $crop)) { + $dst_h = $max_height; + $dst_w = $src_w / $src_h * $max_height; + } + + $filename = $this->getVersionFilename($image->name, $version); + $filepath = $this->getUploadPath($filename, $version); + $upload_dir = $this->getUploadPath('', $version); + + if (!is_dir($upload_dir)) { + mkdir($upload_dir, $this->options['mkdir_mode'], true); + } + + if (!$is_upload || ($is_upload && $version != '')) { + $success = $this->resizeImage($image->path, $filepath, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); + } + + if (!empty($success)) { + $versions[$version] = array( + 'url' => $this->getUploadUrl($filename, $version), + 'width' => $dst_w, + 'height' => $dst_h + ); + } + } + + return $versions; + } + + /** + * Validate uploaded file. + * + * @param string $uploaded_file + * @param stdClass $name + * @param string $error + * @return boolean + */ + protected function validate($uploaded_file, $file, $error) + { + if (!$uploaded_file) { + $file->error = $this->getErrorMessage(4); + return false; + } + + if ($error) { + $file->error = $this->getErrorMessage($error); + return false; + } + + $content_length = $this->fixIntOverflow(intval($_SERVER['CONTENT_LENGTH'])); + $post_max_size = $this->getConfigBytes(ini_get('post_max_size')); + + if ($post_max_size && $content_length > $post_max_size) { + $file->error = $this->getErrorMessage('post_max_size'); + return false; + } + + if ($this->options['max_file_size'] && $file->size > $this->options['max_file_size']) { + $file->error = $this->getErrorMessage('max_file_size'); + return false; + } + + if ($this->options['min_file_size'] && $file->size < $this->options['min_file_size']) { + $file->error = $this->getErrorMessage('min_file_size'); + return false; + } + + if (!preg_match('/.('.$this->options['accept_file_types'].')+$/i', $file->name)) { + $file->error = $this->getErrorMessage('accept_file_types'); + return false; + } + + if (empty($file->width) || empty($file->height)) { + $file->error = $this->getErrorMessage('invalid_image'); + return false; + } + + $max_width = @$this->options['max_width']; + $max_height = @$this->options['max_height']; + $min_width = @$this->options['min_width']; + $min_height = @$this->options['min_height']; + + if ($max_width || $max_height || $min_width || $min_height) { + if ($max_width && $file->width > $max_width) { + $file->error = $this->getErrorMessage('max_width').$max_width.'px'; + return false; + } + + if ($max_height && $file->height > $max_height) { + $file->error = $this->getErrorMessage('max_height').$max_height.'px'; + return false; + } + + if ($min_width && $file->width < $min_width) { + $file->error = $this->getErrorMessage('min_width').$min_width.'px'; + return false; + } + + if ($min_height && $file->height < $min_height) { + $file->error = $this->getErrorMessage('min_height').$min_height.'px'; + return false; + } + } + + return true; + } + + /** + * Get upload directory path. + * + * @param string $filename + * @param string $version + * @return string + */ + public function getUploadPath($filename = '', $version = '') + { + $upload_dir = $this->options['upload_dir']; + + if ($version != '') { + $dir = @$this->options['versions'][$version]['upload_dir']; + + if (!empty($dir)) { + $upload_dir = $dir; + } + } + + return $upload_dir . $filename; + } + + /** + * Get upload directory url. + * + * @param string $filename + * @param string $version + * @return string + */ + public function getUploadUrl($filename = '', $version = '') + { + $upload_url = $this->options['upload_url']; + + if ($version != '') { + $url = @$this->options['versions'][$version]['upload_url']; + + if (!empty($url)) { + $upload_url = $url; + } + } + + return $upload_url . $filename; + } + + /** + * Get full url. + * + * @return string + */ + protected function getFullUrl() { + $https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0; + + return + ($https ? 'https://' : 'http://'). + (!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : ''). + (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME']. + ($https && $_SERVER['SERVER_PORT'] === 443 || + $_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))). + substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], '/')); + } + + /** + * Get file name. + * + * @param string + * @return string + */ + public function getFilename($name) + { + return $this->getUniqueFilename($name); + } + + /** + * Get version name. + * + * @param string + * @return string + */ + public function getVersionFilename($filename, $version) + { + $ext = $this->getFileExtension($filename); + + if ($version == '') { + return $filename; + } + + return str_replace('.'.$ext, "-$version.$ext", $filename); + } + + /** + * Get unique file name. + * + * @param string + * @return string + */ + public function getUniqueFilename($name) + { + while (is_dir($this->getUploadPath($name))) { + $name = $this->upcountName($name); + } + + while (is_file($this->getUploadPath($name))) { + $name = $this->upcountName($name); + } + + return $name; + } + + /** + * Get file extension. + * + * @param string $filename + * @return string + */ + public function getFileExtension($filename) + { + return pathinfo(strtolower($filename), PATHINFO_EXTENSION); + } + + /** + * Generate json response. + * + * @param mixed $response + * @return string + */ + public function generateResponse($response) + { + echo json_encode($response); + } + + /** + * Get error message. + * + * @param string $error + * @return string + */ + public function getErrorMessage($error) + { + return isset($this->errorMessages[$error]) ? $this->errorMessages[$error] : $error; + } + + /** + * Resize image. + * + * @param string $src_path Source image path + * @param string|null $dst_path Destination image path + * @param integer $src_x x-coordinate of source point + * @param integer $src_y y-coordinate of source point + * @param integer $dst_w Destination width + * @param integer $dst_h Destination height + * @param integer $src_w Source width + * @param integer $src_h Source height + * @return bool + */ + public function resizeImage($src_path, $dst_path = null, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) + { + $src_x = ceil($src_x); + $src_y = ceil($src_y); + $dst_w = ceil($dst_w); + $dst_h = ceil($dst_h); + $src_w = ceil($src_w); + $src_h = ceil($src_h); + + $dst_path = ($dst_path) ? $dst_path : $src_path; + $dst_image = imagecreatetruecolor($dst_w, $dst_h); + $extension = $this->getFileExtension($src_path); + + if (!$dst_image) { + return false; + } + + switch ($extension) { + case 'gif': + $src_image = imagecreatefromgif($src_path); + break; + case 'jpeg': + case 'jpg': + $src_image = imagecreatefromjpeg($src_path); + break; + case 'png': + imagealphablending($dst_image, false); + imagesavealpha($dst_image, true); + $src_image = imagecreatefrompng($src_path); + @imagealphablending($src_image, true); + break; + } + + if (isset($src_image) && !$src_image) { + return false; + } + + if (!imagecopyresampled($dst_image, $src_image, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)) { + return false; + } + + switch ($extension) { + case 'gif': + return imagegif($dst_image, $dst_path); + break; + case 'jpeg': + case 'jpg': + return imagejpeg($dst_image, $dst_path); + break; + case 'png': + return imagepng($dst_image, $dst_path); + break; + } + } + + /** + * Rotate image. + * + * @param string $src_path + * @param integer $angle + * @return void + */ + public function rotateImage($src_path, $angle) + { + $type = $this->getFileExtension($src_path); + + switch ($type) { + case 'gif': + $source = imagecreatefromgif($src_path); + break; + case 'jpeg': + case 'jpg': + $source = imagecreatefromjpeg($src_path); + break; + case 'png': + $source = imagecreatefrompng($src_path); + break; + } + + $image = imagerotate($source, $angle, 0); + + switch ($type) { + case 'gif': + imagegif($image, $src_path); + break; + case 'jpeg': + case 'jpg': + imagejpeg($image, $src_path); + break; + case 'png': + imagepng($image, $src_path); + break; + } + + imagedestroy($source); + imagedestroy($image); + } + + /** + * Orient image based on EXIF orientation data. + * + * @param string $filepath + * @return void + */ + protected function orientImage($filepath) + { + if (!preg_match('/\.(jpe?g)$/i', $filepath)) { + return; + } + + if (!function_exists('exif_read_data')) { + return; + } + + $exif = @exif_read_data($filepath); + + if (!empty($exif['Orientation'])) { + switch($exif['Orientation']) { + case 3: $angle = 180; break; + case 6: $angle = -90; break; + case 8: $angle = 90; break; + } + + if (isset($angle)) { + $this->rotateImage($filepath, $angle); + } + } + } + + protected function upcountName($name) + { + return preg_replace_callback( + '/(?:(?: \(([\d]+)\))?(\.[^.]+))?$/', + array($this, 'upcountNameCallback'), + $name, + 1 + ); + } + + protected function upcountNameCallback($matches) + { + $index = isset($matches[1]) ? intval($matches[1]) + 1 : 1; + $ext = isset($matches[2]) ? $matches[2] : ''; + + return ' ('.$index.')'.$ext; + } + + protected function getConfigBytes($val) + { + $val = trim($val); + $last = strtolower($val[strlen($val)-1]); + + switch ($last) { + case 'g': + $val *= 1024; + case 'm': + $val *= 1024; + case 'k': + $val *= 1024; + } + + return $this->fixIntOverflow($val); + } + + protected function fixIntOverflow($size) + { + if ($size < 0) { + $size += 2.0 * (PHP_INT_MAX + 1); + } + + return $size; + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/assets/class.upload.php b/deployed/jsn/administrator/components/com_jsn/assets/class.upload.php new file mode 100644 index 00000000..efd0bf41 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/assets/class.upload.php @@ -0,0 +1,5009 @@ + + * @license http://opensource.org/licenses/gpl-license.php GNU Public License + * @copyright Colin Verot + */ +class upload { + + + /** + * Class version + * + * @access public + * @var string + */ + var $version; + + /** + * Uploaded file name + * + * @access public + * @var string + */ + var $file_src_name; + + /** + * Uploaded file name body (i.e. without extension) + * + * @access public + * @var string + */ + var $file_src_name_body; + + /** + * Uploaded file name extension + * + * @access public + * @var string + */ + var $file_src_name_ext; + + /** + * Uploaded file MIME type + * + * @access public + * @var string + */ + var $file_src_mime; + + /** + * Uploaded file size, in bytes + * + * @access public + * @var double + */ + var $file_src_size; + + /** + * Holds eventual PHP error code from FILES + * + * @access public + * @var string + */ + var $file_src_error; + + /** + * Uloaded file name, including server path + * + * @access public + * @var string + */ + var $file_src_pathname; + + /** + * Uloaded file name temporary copy + * + * @access private + * @var string + */ + var $file_src_temp; + + /** + * Destination file name + * + * @access public + * @var string + */ + var $file_dst_path; + + /** + * Destination file name + * + * @access public + * @var string + */ + var $file_dst_name; + + /** + * Destination file name body (i.e. without extension) + * + * @access public + * @var string + */ + var $file_dst_name_body; + + /** + * Destination file extension + * + * @access public + * @var string + */ + var $file_dst_name_ext; + + /** + * Destination file name, including path + * + * @access public + * @var string + */ + var $file_dst_pathname; + + /** + * Source image width + * + * @access public + * @var integer + */ + var $image_src_x; + + /** + * Source image height + * + * @access public + * @var integer + */ + var $image_src_y; + + /** + * Source image color depth + * + * @access public + * @var integer + */ + var $image_src_bits; + + /** + * Number of pixels + * + * @access public + * @var long + */ + var $image_src_pixels; + + /** + * Type of image (png, gif, jpg or bmp) + * + * @access public + * @var string + */ + var $image_src_type; + + /** + * Destination image width + * + * @access public + * @var integer + */ + var $image_dst_x; + + /** + * Destination image height + * + * @access public + * @var integer + */ + var $image_dst_y; + + /** + * Destination image type (png, gif, jpg or bmp) + * + * @access public + * @var integer + */ + var $image_dst_type; + + /** + * Supported image formats + * + * @access private + * @var array + */ + var $image_supported; + + /** + * Flag to determine if the source file is an image + * + * @access public + * @var boolean + */ + var $file_is_image; + + /** + * Flag set after instanciating the class + * + * Indicates if the file has been uploaded properly + * + * @access public + * @var bool + */ + var $uploaded; + + /** + * Flag stopping PHP upload checks + * + * Indicates whether we instanciated the class with a filename, in which case + * we will not check on the validity of the PHP *upload* + * + * This flag is automatically set to true when working on a local file + * + * Warning: for uploads, this flag MUST be set to false for security reason + * + * @access public + * @var bool + */ + var $no_upload_check; + + /** + * Flag set after calling a process + * + * Indicates if the processing, and copy of the resulting file went OK + * + * @access public + * @var bool + */ + var $processed; + + /** + * Holds eventual error message in plain english + * + * @access public + * @var string + */ + var $error; + + /** + * Holds an HTML formatted log + * + * @access public + * @var string + */ + var $log; + + + // overiddable processing variables + + + /** + * Set this variable to replace the name body (i.e. without extension) + * + * @access public + * @var string + */ + var $file_new_name_body; + + /** + * Set this variable to append a string to the file name body + * + * @access public + * @var string + */ + var $file_name_body_add; + + /** + * Set this variable to prepend a string to the file name body + * + * @access public + * @var string + */ + var $file_name_body_pre; + + /** + * Set this variable to change the file extension + * + * @access public + * @var string + */ + var $file_new_name_ext; + + /** + * Set this variable to format the filename (spaces changed to _) + * + * @access public + * @var boolean + */ + var $file_safe_name; + + /** + * Forces an extension if the source file doesn't have one + * + * If the file is an image, then the correct extension will be added + * Otherwise, a .txt extension will be chosen + * + * @access public + * @var boolean + */ + var $file_force_extension; + + /** + * Set this variable to false if you don't want to check the MIME against the allowed list + * + * This variable is set to true by default for security reason + * + * @access public + * @var boolean + */ + var $mime_check; + + /** + * Set this variable to false in the init() function if you don't want to check the MIME + * with Fileinfo PECL extension. On some systems, Fileinfo is known to be buggy, and you + * may want to deactivate it in the class code directly. + * + * You can also set it with the path of the magic database file. + * If set to true, the class will try to read the MAGIC environment variable + * and if it is empty, will default to the system's default + * If set to an empty string, it will call finfo_open without the path argument + * + * This variable is set to true by default for security reason + * + * @access public + * @var boolean + */ + var $mime_fileinfo; + + /** + * Set this variable to false in the init() function if you don't want to check the MIME + * with UNIX file() command + * + * This variable is set to true by default for security reason + * + * @access public + * @var boolean + */ + var $mime_file; + + /** + * Set this variable to false in the init() function if you don't want to check the MIME + * with the magic.mime file + * + * The function mime_content_type() will be deprecated, + * and this variable will be set to false in a future release + * + * This variable is set to true by default for security reason + * + * @access public + * @var boolean + */ + var $mime_magic; + + /** + * Set this variable to false in the init() function if you don't want to check the MIME + * with getimagesize() + * + * The class tries to get a MIME type from getimagesize() + * If no MIME is returned, it tries to guess the MIME type from the file type + * + * This variable is set to true by default for security reason + * + * @access public + * @var boolean + */ + var $mime_getimagesize; + + /** + * Set this variable to false if you don't want to turn dangerous scripts into simple text files + * + * @access public + * @var boolean + */ + var $no_script; + + /** + * Set this variable to true to allow automatic renaming of the file + * if the file already exists + * + * Default value is true + * + * For instance, on uploading foo.ext,
+ * if foo.ext already exists, upload will be renamed foo_1.ext
+ * and if foo_1.ext already exists, upload will be renamed foo_2.ext
+ * + * Note that this option doesn't have any effect if {@link file_overwrite} is true + * + * @access public + * @var bool + */ + var $file_auto_rename; + + /** + * Set this variable to true to allow automatic creation of the destination + * directory if it is missing (works recursively) + * + * Default value is true + * + * @access public + * @var bool + */ + var $dir_auto_create; + + /** + * Set this variable to true to allow automatic chmod of the destination + * directory if it is not writeable + * + * Default value is true + * + * @access public + * @var bool + */ + var $dir_auto_chmod; + + /** + * Set this variable to the default chmod you want the class to use + * when creating directories, or attempting to write in a directory + * + * Default value is 0777 (without quotes) + * + * @access public + * @var bool + */ + var $dir_chmod; + + /** + * Set this variable tu true to allow overwriting of an existing file + * + * Default value is false, so no files will be overwritten + * + * @access public + * @var bool + */ + var $file_overwrite; + + /** + * Set this variable to change the maximum size in bytes for an uploaded file + * + * Default value is the value upload_max_filesize from php.ini + * + * Value in bytes (integer) or shorthand byte values (string) is allowed. + * The available options are K (for Kilobytes), M (for Megabytes) and G (for Gigabytes) + * + * @access public + * @var double + */ + var $file_max_size; + + /** + * Set this variable to true to resize the file if it is an image + * + * You will probably want to set {@link image_x} and {@link image_y}, and maybe one of the ratio variables + * + * Default value is false (no resizing) + * + * @access public + * @var bool + */ + var $image_resize; + + /** + * Set this variable to convert the file if it is an image + * + * Possibles values are : ''; 'png'; 'jpeg'; 'gif'; 'bmp' + * + * Default value is '' (no conversion)
+ * If {@link resize} is true, {@link convert} will be set to the source file extension + * + * @access public + * @var string + */ + var $image_convert; + + /** + * Set this variable to the wanted (or maximum/minimum) width for the processed image, in pixels + * + * Default value is 150 + * + * @access public + * @var integer + */ + var $image_x; + + /** + * Set this variable to the wanted (or maximum/minimum) height for the processed image, in pixels + * + * Default value is 150 + * + * @access public + * @var integer + */ + var $image_y; + + /** + * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y} + * + * Default value is false + * + * @access public + * @var bool + */ + var $image_ratio; + + /** + * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y} + * + * The image will be resized as to fill the whole space, and excedent will be cropped + * + * Value can also be a string, one or more character from 'TBLR' (top, bottom, left and right) + * If set as a string, it determines which side of the image is kept while cropping. + * By default, the part of the image kept is in the center, i.e. it crops equally on both sides + * + * Default value is false + * + * @access public + * @var mixed + */ + var $image_ratio_crop; + + /** + * Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y} + * + * The image will be resized to fit entirely in the space, and the rest will be colored. + * The default color is white, but can be set with {@link image_default_color} + * + * Value can also be a string, one or more character from 'TBLR' (top, bottom, left and right) + * If set as a string, it determines in which side of the space the image is displayed. + * By default, the image is displayed in the center, i.e. it fills the remaining space equally on both sides + * + * Default value is false + * + * @access public + * @var mixed + */ + var $image_ratio_fill; + + /** + * Set this variable to a number of pixels so that {@link image_x} and {@link image_y} are the best match possible + * + * The image will be resized to have approximatively the number of pixels + * The aspect ratio wil be conserved + * + * Default value is false + * + * @access public + * @var mixed + */ + var $image_ratio_pixels; + + /** + * Set this variable to calculate {@link image_x} automatically , using {@link image_y} and conserving ratio + * + * Default value is false + * + * @access public + * @var bool + */ + var $image_ratio_x; + + /** + * Set this variable to calculate {@link image_y} automatically , using {@link image_x} and conserving ratio + * + * Default value is false + * + * @access public + * @var bool + */ + var $image_ratio_y; + + /** + * (deprecated) Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y}, + * but only if original image is bigger + * + * This setting is soon to be deprecated. Instead, use {@link image_ratio} and {@link image_no_enlarging} + * + * Default value is false + * + * @access public + * @var bool + */ + var $image_ratio_no_zoom_in; + + /** + * (deprecated) Set this variable to keep the original size ratio to fit within {@link image_x} x {@link image_y}, + * but only if original image is smaller + * + * Default value is false + * + * This setting is soon to be deprecated. Instead, use {@link image_ratio} and {@link image_no_shrinking} + * + * @access public + * @var bool + */ + var $image_ratio_no_zoom_out; + + /** + * Cancel resizing if the resized image is bigger than the original image, to prevent enlarging + * + * Default value is false + * + * @access public + * @var bool + */ + var $image_no_enlarging; + + /** + * Cancel resizing if the resized image is smaller than the original image, to prevent shrinking + * + * Default value is false + * + * @access public + * @var bool + */ + var $image_no_shrinking; + + /** + * Set this variable to set a maximum image width, above which the upload will be invalid + * + * Default value is null + * + * @access public + * @var integer + */ + var $image_max_width; + + /** + * Set this variable to set a maximum image height, above which the upload will be invalid + * + * Default value is null + * + * @access public + * @var integer + */ + var $image_max_height; + + /** + * Set this variable to set a maximum number of pixels for an image, above which the upload will be invalid + * + * Default value is null + * + * @access public + * @var long + */ + var $image_max_pixels; + + /** + * Set this variable to set a maximum image aspect ratio, above which the upload will be invalid + * + * Note that ratio = width / height + * + * Default value is null + * + * @access public + * @var float + */ + var $image_max_ratio; + + /** + * Set this variable to set a minimum image width, below which the upload will be invalid + * + * Default value is null + * + * @access public + * @var integer + */ + var $image_min_width; + + /** + * Set this variable to set a minimum image height, below which the upload will be invalid + * + * Default value is null + * + * @access public + * @var integer + */ + var $image_min_height; + + /** + * Set this variable to set a minimum number of pixels for an image, below which the upload will be invalid + * + * Default value is null + * + * @access public + * @var long + */ + var $image_min_pixels; + + /** + * Set this variable to set a minimum image aspect ratio, below which the upload will be invalid + * + * Note that ratio = width / height + * + * Default value is null + * + * @access public + * @var float + */ + var $image_min_ratio; + + /** + * Compression level for PNG images + * + * Between 1 (fast but large files) and 9 (slow but smaller files) + * + * Default value is null (Zlib default) + * + * @access public + * @var integer + */ + var $png_compression; + + /** + * Quality of JPEG created/converted destination image + * + * Default value is 85 + * + * @access public + * @var integer + */ + var $jpeg_quality; + + /** + * Determines the quality of the JPG image to fit a desired file size + * + * The JPG quality will be set between 1 and 100% + * The calculations are approximations. + * + * Value in bytes (integer) or shorthand byte values (string) is allowed. + * The available options are K (for Kilobytes), M (for Megabytes) and G (for Gigabytes) + * + * Default value is null (no calculations) + * + * @access public + * @var integer + */ + var $jpeg_size; + + /** + * Turns the interlace bit on + * + * This is actually used only for JPEG images, and defaults to false + * + * @access public + * @var boolean + */ + var $image_interlace; + + /** + * Flag set to true when the image is transparent + * + * This is actually used only for transparent GIFs + * + * @access public + * @var boolean + */ + var $image_is_transparent; + + /** + * Transparent color in a palette + * + * This is actually used only for transparent GIFs + * + * @access public + * @var boolean + */ + var $image_transparent_color; + + /** + * Background color, used to paint transparent areas with + * + * If set, it will forcibly remove transparency by painting transparent areas with the color + * This setting will fill in all transparent areas in PNG and GIF, as opposed to {@link image_default_color} + * which will do so only in BMP, JPEG, and alpha transparent areas in transparent GIFs + * This setting overrides {@link image_default_color} + * + * Default value is null + * + * @access public + * @var string + */ + var $image_background_color; + + /** + * Default color for non alpha-transparent images + * + * This setting is to be used to define a background color for semi transparent areas + * of an alpha transparent when the output format doesn't support alpha transparency + * This is useful when, from an alpha transparent PNG image, or an image with alpha transparent features + * if you want to output it as a transparent GIFs for instance, you can set a blending color for transparent areas + * If you output in JPEG or BMP, this color will be used to fill in the previously transparent areas + * + * The default color white + * + * @access public + * @var boolean + */ + var $image_default_color; + + /** + * Flag set to true when the image is not true color + * + * @access public + * @var boolean + */ + var $image_is_palette; + + /** + * Corrects the image brightness + * + * Value can range between -127 and 127 + * + * Default value is null + * + * @access public + * @var integer + */ + var $image_brightness; + + /** + * Corrects the image contrast + * + * Value can range between -127 and 127 + * + * Default value is null + * + * @access public + * @var integer + */ + var $image_contrast; + + /** + * Changes the image opacity + * + * Value can range between 0 and 100 + * + * Default value is null + * + * @access public + * @var integer + */ + var $image_opacity; + + /** + * Applies threshold filter + * + * Value can range between -127 and 127 + * + * Default value is null + * + * @access public + * @var integer + */ + var $image_threshold; + + /** + * Applies a tint on the image + * + * Value is an hexadecimal color, such as #FFFFFF + * + * Default value is null + * + * @access public + * @var string; + */ + var $image_tint_color; + + /** + * Applies a colored overlay on the image + * + * Value is an hexadecimal color, such as #FFFFFF + * + * To use with {@link image_overlay_opacity} + * + * Default value is null + * + * @access public + * @var string; + */ + var $image_overlay_color; + + /** + * Sets the opacity for the colored overlay + * + * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque) + * + * Unless used with {@link image_overlay_color}, this setting has no effect + * + * Default value is 50 + * + * @access public + * @var integer + */ + var $image_overlay_opacity; + + /** + * Inverts the color of an image + * + * Default value is FALSE + * + * @access public + * @var boolean; + */ + var $image_negative; + + /** + * Turns the image into greyscale + * + * Default value is FALSE + * + * @access public + * @var boolean; + */ + var $image_greyscale; + + /** + * Pixelate an image + * + * Value is integer, represents the block size + * + * Default value is null + * + * @access public + * @var integer; + */ + var $image_pixelate; + + /** + * Applies an unsharp mask, with alpha transparency support + * + * Beware that this unsharp mask is quite resource-intensive + * + * Default value is FALSE + * + * @access public + * @var boolean; + */ + var $image_unsharp; + + /** + * Sets the unsharp mask amount + * + * Value is an integer between 0 and 500, typically between 50 and 200 + * + * Unless used with {@link image_unsharp}, this setting has no effect + * + * Default value is 80 + * + * @access public + * @var integer + */ + var $image_unsharp_amount; + + /** + * Sets the unsharp mask radius + * + * Value is an integer between 0 and 50, typically between 0.5 and 1 + * It is not recommended to change it, the default works best + * + * Unless used with {@link image_unsharp}, this setting has no effect + * + * From PHP 5.1, imageconvolution is used, and this setting has no effect + * + * Default value is 0.5 + * + * @access public + * @var integer + */ + var $image_unsharp_radius; + + /** + * Sets the unsharp mask threshold + * + * Value is an integer between 0 and 255, typically between 0 and 5 + * + * Unless used with {@link image_unsharp}, this setting has no effect + * + * Default value is 1 + * + * @access public + * @var integer + */ + var $image_unsharp_threshold; + + /** + * Adds a text label on the image + * + * Value is a string, any text. Text will not word-wrap, although you can use breaklines in your text "\n" + * + * If set, this setting allow the use of all other settings starting with image_text_ + * + * Replacement tokens can be used in the string: + *
+     * gd_version    src_name       src_name_body src_name_ext
+     * src_pathname  src_mime       src_x         src_y
+     * src_type      src_bits       src_pixels
+     * src_size      src_size_kb    src_size_mb   src_size_human
+     * dst_path      dst_name_body  dst_pathname
+     * dst_name      dst_name_ext   dst_x         dst_y
+     * date          time           host          server        ip
+     * 
+ * The tokens must be enclosed in square brackets: [dst_x] will be replaced by the width of the picture + * + * Default value is null + * + * @access public + * @var string; + */ + var $image_text; + + /** + * Sets the text direction for the text label + * + * Value is either 'h' or 'v', as in horizontal and vertical + * + * Note that if you use a TrueType font, you can use {@link image_text_angle} instead + * + * Default value is h (horizontal) + * + * @access public + * @var string; + */ + var $image_text_direction; + + /** + * Sets the text color for the text label + * + * Value is an hexadecimal color, such as #FFFFFF + * + * Default value is #FFFFFF (white) + * + * @access public + * @var string; + */ + var $image_text_color; + + /** + * Sets the text opacity in the text label + * + * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque) + * + * Default value is 100 + * + * @access public + * @var integer + */ + var $image_text_opacity; + + /** + * Sets the text background color for the text label + * + * Value is an hexadecimal color, such as #FFFFFF + * + * Default value is null (no background) + * + * @access public + * @var string; + */ + var $image_text_background; + + /** + * Sets the text background opacity in the text label + * + * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque) + * + * Default value is 100 + * + * @access public + * @var integer + */ + var $image_text_background_opacity; + + /** + * Sets the text font in the text label + * + * Value is a an integer between 1 and 5 for GD built-in fonts. 1 is the smallest font, 5 the biggest + * Value can also be a string, which represents the path to a GDF or TTF font (TrueType). + * + * Default value is 5 + * + * @access public + * @var mixed; + */ + var $image_text_font; + + /** + * Sets the text font size for TrueType fonts + * + * Value is a an integer, and represents the font size in pixels (GD1) or points (GD1) + * + * Note that this setting is only applicable to TrueType fonts, and has no effects with GD fonts + * + * Default value is 16 + * + * @access public + * @var integer; + */ + var $image_text_size; + + /** + * Sets the text angle for TrueType fonts + * + * Value is a an integer between 0 and 360, in degrees, with 0 degrees being left-to-right reading text. + * + * Note that this setting is only applicable to TrueType fonts, and has no effects with GD fonts + * For GD fonts, you can use {@link image_text_direction} instead + * + * Default value is null (so it is determined by the value of {@link image_text_direction}) + * + * @access public + * @var integer; + */ + var $image_text_angle; + + /** + * Sets the text label position within the image + * + * Value is one or two out of 'TBLR' (top, bottom, left, right) + * + * The positions are as following: + *
+     *                        TL  T  TR
+     *                        L       R
+     *                        BL  B  BR
+     * 
+ * + * Default value is null (centered, horizontal and vertical) + * + * Note that is {@link image_text_x} and {@link image_text_y} are used, this setting has no effect + * + * @access public + * @var string; + */ + var $image_text_position; + + /** + * Sets the text label absolute X position within the image + * + * Value is in pixels, representing the distance between the left of the image and the label + * If a negative value is used, it will represent the distance between the right of the image and the label + * + * Default value is null (so {@link image_text_position} is used) + * + * @access public + * @var integer + */ + var $image_text_x; + + /** + * Sets the text label absolute Y position within the image + * + * Value is in pixels, representing the distance between the top of the image and the label + * If a negative value is used, it will represent the distance between the bottom of the image and the label + * + * Default value is null (so {@link image_text_position} is used) + * + * @access public + * @var integer + */ + var $image_text_y; + + /** + * Sets the text label padding + * + * Value is in pixels, representing the distance between the text and the label background border + * + * Default value is 0 + * + * This setting can be overriden by {@link image_text_padding_x} and {@link image_text_padding_y} + * + * @access public + * @var integer + */ + var $image_text_padding; + + /** + * Sets the text label horizontal padding + * + * Value is in pixels, representing the distance between the text and the left and right label background borders + * + * Default value is null + * + * If set, this setting overrides the horizontal part of {@link image_text_padding} + * + * @access public + * @var integer + */ + var $image_text_padding_x; + + /** + * Sets the text label vertical padding + * + * Value is in pixels, representing the distance between the text and the top and bottom label background borders + * + * Default value is null + * + * If set, his setting overrides the vertical part of {@link image_text_padding} + * + * @access public + * @var integer + */ + var $image_text_padding_y; + + /** + * Sets the text alignment + * + * Value is a string, which can be either 'L', 'C' or 'R' + * + * Default value is 'C' + * + * This setting is relevant only if the text has several lines. + * + * Note that this setting is only applicable to GD fonts, and has no effects with TrueType fonts + * + * @access public + * @var string; + */ + var $image_text_alignment; + + /** + * Sets the text line spacing + * + * Value is an integer, in pixels + * + * Default value is 0 + * + * This setting is relevant only if the text has several lines. + * + * Note that this setting is only applicable to GD fonts, and has no effects with TrueType fonts + * + * @access public + * @var integer + */ + var $image_text_line_spacing; + + /** + * Sets the height of the reflection + * + * Value is an integer in pixels, or a string which format can be in pixels or percentage. + * For instance, values can be : 40, '40', '40px' or '40%' + * + * Default value is null, no reflection + * + * @access public + * @var mixed; + */ + var $image_reflection_height; + + /** + * Sets the space between the source image and its relection + * + * Value is an integer in pixels, which can be negative + * + * Default value is 2 + * + * This setting is relevant only if {@link image_reflection_height} is set + * + * @access public + * @var integer + */ + var $image_reflection_space; + + /** + * Sets the initial opacity of the reflection + * + * Value is an integer between 0 (no opacity) and 100 (full opacity). + * The reflection will start from {@link image_reflection_opacity} and end up at 0 + * + * Default value is 60 + * + * This setting is relevant only if {@link image_reflection_height} is set + * + * @access public + * @var integer + */ + var $image_reflection_opacity; + + /** + * Automatically rotates the image according to EXIF data (JPEG only) + * + * Default value is true + * + * @access public + * @var boolean; + */ + var $image_auto_rotate; + + /** + * Flips the image vertically or horizontally + * + * Value is either 'h' or 'v', as in horizontal and vertical + * + * Default value is null (no flip) + * + * @access public + * @var string; + */ + var $image_flip; + + /** + * Rotates the image by increments of 45 degrees + * + * Value is either 90, 180 or 270 + * + * Default value is null (no rotation) + * + * @access public + * @var string; + */ + var $image_rotate; + + /** + * Crops an image + * + * Values are four dimensions, or two, or one (CSS style) + * They represent the amount cropped top, right, bottom and left. + * These values can either be in an array, or a space separated string. + * Each value can be in pixels (with or without 'px'), or percentage (of the source image) + * + * For instance, are valid: + *
+     * $foo->image_crop = 20                  OR array(20);
+     * $foo->image_crop = '20px'              OR array('20px');
+     * $foo->image_crop = '20 40'             OR array('20', 40);
+     * $foo->image_crop = '-20 25%'           OR array(-20, '25%');
+     * $foo->image_crop = '20px 25%'          OR array('20px', '25%');
+     * $foo->image_crop = '20% 25%'           OR array('20%', '25%');
+     * $foo->image_crop = '20% 25% 10% 30%'   OR array('20%', '25%', '10%', '30%');
+     * $foo->image_crop = '20px 25px 2px 2px' OR array('20px', '25%px', '2px', '2px');
+     * $foo->image_crop = '20 25% 40px 10%'   OR array(20, '25%', '40px', '10%');
+     * 
+ * + * If a value is negative, the image will be expanded, and the extra parts will be filled with black + * + * Default value is null (no cropping) + * + * @access public + * @var string OR array; + */ + var $image_crop; + + /** + * Crops an image, before an eventual resizing + * + * See {@link image_crop} for valid formats + * + * Default value is null (no cropping) + * + * @access public + * @var string OR array; + */ + var $image_precrop; + + /** + * Adds a bevel border on the image + * + * Value is a positive integer, representing the thickness of the bevel + * + * If the bevel colors are the same as the background, it makes a fade out effect + * + * Default value is null (no bevel) + * + * @access public + * @var integer + */ + var $image_bevel; + + /** + * Top and left bevel color + * + * Value is a color, in hexadecimal format + * This setting is used only if {@link image_bevel} is set + * + * Default value is #FFFFFF + * + * @access public + * @var string; + */ + var $image_bevel_color1; + + /** + * Right and bottom bevel color + * + * Value is a color, in hexadecimal format + * This setting is used only if {@link image_bevel} is set + * + * Default value is #000000 + * + * @access public + * @var string; + */ + var $image_bevel_color2; + + /** + * Adds a single-color border on the outer of the image + * + * Values are four dimensions, or two, or one (CSS style) + * They represent the border thickness top, right, bottom and left. + * These values can either be in an array, or a space separated string. + * Each value can be in pixels (with or without 'px'), or percentage (of the source image) + * + * See {@link image_crop} for valid formats + * + * If a value is negative, the image will be cropped. + * Note that the dimensions of the picture will be increased by the borders' thickness + * + * Default value is null (no border) + * + * @access public + * @var integer + */ + var $image_border; + + /** + * Border color + * + * Value is a color, in hexadecimal format. + * This setting is used only if {@link image_border} is set + * + * Default value is #FFFFFF + * + * @access public + * @var string; + */ + var $image_border_color; + + /** + * Sets the opacity for the borders + * + * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque) + * + * Unless used with {@link image_border}, this setting has no effect + * + * Default value is 100 + * + * @access public + * @var integer + */ + var $image_border_opacity; + + /** + * Adds a fading-to-transparent border on the image + * + * Values are four dimensions, or two, or one (CSS style) + * They represent the border thickness top, right, bottom and left. + * These values can either be in an array, or a space separated string. + * Each value can be in pixels (with or without 'px'), or percentage (of the source image) + * + * See {@link image_crop} for valid formats + * + * Note that the dimensions of the picture will not be increased by the borders' thickness + * + * Default value is null (no border) + * + * @access public + * @var integer + */ + var $image_border_transparent; + + /** + * Adds a multi-color frame on the outer of the image + * + * Value is an integer. Two values are possible for now: + * 1 for flat border, meaning that the frame is mirrored horizontally and vertically + * 2 for crossed border, meaning that the frame will be inversed, as in a bevel effect + * + * The frame will be composed of colored lines set in {@link image_frame_colors} + * + * Note that the dimensions of the picture will be increased by the borders' thickness + * + * Default value is null (no frame) + * + * @access public + * @var integer + */ + var $image_frame; + + /** + * Sets the colors used to draw a frame + * + * Values is a list of n colors in hexadecimal format. + * These values can either be in an array, or a space separated string. + * + * The colors are listed in the following order: from the outset of the image to its center + * + * For instance, are valid: + *
+     * $foo->image_frame_colors = '#FFFFFF #999999 #666666 #000000';
+     * $foo->image_frame_colors = array('#FFFFFF', '#999999', '#666666', '#000000');
+     * 
+ * + * This setting is used only if {@link image_frame} is set + * + * Default value is '#FFFFFF #999999 #666666 #000000' + * + * @access public + * @var string OR array; + */ + var $image_frame_colors; + + /** + * Sets the opacity for the frame + * + * Value is a percentage, as an integer between 0 (transparent) and 100 (opaque) + * + * Unless used with {@link image_frame}, this setting has no effect + * + * Default value is 100 + * + * @access public + * @var integer + */ + var $image_frame_opacity; + + /** + * Adds a watermark on the image + * + * Value is a local image filename, relative or absolute. GIF, JPG, BMP and PNG are supported, as well as PNG alpha. + * + * If set, this setting allow the use of all other settings starting with image_watermark_ + * + * Default value is null + * + * @access public + * @var string; + */ + var $image_watermark; + + /** + * Sets the watermarkposition within the image + * + * Value is one or two out of 'TBLR' (top, bottom, left, right) + * + * The positions are as following: TL T TR + * L R + * BL B BR + * + * Default value is null (centered, horizontal and vertical) + * + * Note that is {@link image_watermark_x} and {@link image_watermark_y} are used, this setting has no effect + * + * @access public + * @var string; + */ + var $image_watermark_position; + + /** + * Sets the watermark absolute X position within the image + * + * Value is in pixels, representing the distance between the top of the image and the watermark + * If a negative value is used, it will represent the distance between the bottom of the image and the watermark + * + * Default value is null (so {@link image_watermark_position} is used) + * + * @access public + * @var integer + */ + var $image_watermark_x; + + /** + * Sets the twatermark absolute Y position within the image + * + * Value is in pixels, representing the distance between the left of the image and the watermark + * If a negative value is used, it will represent the distance between the right of the image and the watermark + * + * Default value is null (so {@link image_watermark_position} is used) + * + * @access public + * @var integer + */ + var $image_watermark_y; + + /** + * Prevents the watermark to be resized up if it is smaller than the image + * + * If the watermark if smaller than the destination image, taking in account the desired watermark position + * then it will be resized up to fill in the image (minus the {@link image_watermark_x} or {@link image_watermark_y} values) + * + * If you don't want your watermark to be resized in any way, then + * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to true + * If you want your watermark to be resized up or doan to fill in the image better, then + * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to false + * + * Default value is true (so the watermark will not be resized up, which is the behaviour most people expect) + * + * @access public + * @var integer + */ + var $image_watermark_no_zoom_in; + + /** + * Prevents the watermark to be resized down if it is bigger than the image + * + * If the watermark if bigger than the destination image, taking in account the desired watermark position + * then it will be resized down to fit in the image (minus the {@link image_watermark_x} or {@link image_watermark_y} values) + * + * If you don't want your watermark to be resized in any way, then + * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to true + * If you want your watermark to be resized up or doan to fill in the image better, then + * set {@link image_watermark_no_zoom_in} and {@link image_watermark_no_zoom_out} to false + * + * Default value is false (so the watermark may be shrinked to fit in the image) + * + * @access public + * @var integer + */ + var $image_watermark_no_zoom_out; + + /** + * List of MIME types per extension + * + * @access private + * @var array + */ + var $mime_types; + + /** + * Allowed MIME types + * + * Default is a selection of safe mime-types, but you might want to change it + * + * Simple wildcards are allowed, such as image/* or application/* + * If there is only one MIME type allowed, then it can be a string instead of an array + * + * @access public + * @var array OR string + */ + var $allowed; + + /** + * Forbidden MIME types + * + * Default is a selection of safe mime-types, but you might want to change it + * To only check for forbidden MIME types, and allow everything else, set {@link allowed} to array('* / *') without the spaces + * + * Simple wildcards are allowed, such as image/* or application/* + * If there is only one MIME type forbidden, then it can be a string instead of an array + * + * @access public + * @var array OR string + */ + var $forbidden; + + /** + * Array of translated error messages + * + * By default, the language is english (en_GB) + * Translations can be in separate files, in a lang/ subdirectory + * + * @access public + * @var array + */ + var $translation; + + /** + * Language selected for the translations + * + * By default, the language is english ("en_GB") + * + * @access public + * @var array + */ + var $lang; + + /** + * Init or re-init all the processing variables to their default values + * + * This function is called in the constructor, and after each call of {@link process} + * + * @access private + */ + function init() { + + // overiddable variables + $this->file_new_name_body = null; // replace the name body + $this->file_name_body_add = null; // append to the name body + $this->file_name_body_pre = null; // prepend to the name body + $this->file_new_name_ext = null; // replace the file extension + $this->file_safe_name = true; // format safely the filename + $this->file_force_extension = true; // forces extension if there isn't one + $this->file_overwrite = false; // allows overwritting if the file already exists + $this->file_auto_rename = true; // auto-rename if the file already exists + $this->dir_auto_create = true; // auto-creates directory if missing + $this->dir_auto_chmod = true; // auto-chmod directory if not writeable + $this->dir_chmod = 0777; // default chmod to use + + $this->no_script = true; // turns scripts into test files + $this->mime_check = true; // checks the mime type against the allowed list + + // these are the different MIME detection methods. if one of these method doesn't work on your + // system, you can deactivate it here; just set it to false + $this->mime_fileinfo = true; // MIME detection with Fileinfo PECL extension + $this->mime_file = true; // MIME detection with UNIX file() command + $this->mime_magic = true; // MIME detection with mime_magic (mime_content_type()) + $this->mime_getimagesize = true; // MIME detection with getimagesize() + + // get the default max size from php.ini + $this->file_max_size_raw = trim(ini_get('upload_max_filesize')); + $this->file_max_size = $this->getsize($this->file_max_size_raw); + + $this->image_resize = false; // resize the image + $this->image_convert = ''; // convert. values :''; 'png'; 'jpeg'; 'gif'; 'bmp' + + $this->image_x = 150; + $this->image_y = 150; + $this->image_ratio = false; // keeps aspect ratio with x and y dimensions + $this->image_ratio_crop = false; // keeps aspect ratio with x and y dimensions, filling the space + $this->image_ratio_fill = false; // keeps aspect ratio with x and y dimensions, fitting the image in the space, and coloring the rest + $this->image_ratio_pixels = false; // keeps aspect ratio, calculating x and y so that the image is approx the set number of pixels + $this->image_ratio_x = false; // calculate the $image_x if true + $this->image_ratio_y = false; // calculate the $image_y if true + $this->image_ratio_no_zoom_in = false; + $this->image_ratio_no_zoom_out = false; + $this->image_no_enlarging = false; + $this->image_no_shrinking = false; + + $this->png_compression = null; + $this->jpeg_quality = 85; + $this->jpeg_size = null; + $this->image_interlace = false; + $this->image_is_transparent = false; + $this->image_transparent_color = null; + $this->image_background_color = null; + $this->image_default_color = '#ffffff'; + $this->image_is_palette = false; + + $this->image_max_width = null; + $this->image_max_height = null; + $this->image_max_pixels = null; + $this->image_max_ratio = null; + $this->image_min_width = null; + $this->image_min_height = null; + $this->image_min_pixels = null; + $this->image_min_ratio = null; + + $this->image_brightness = null; + $this->image_contrast = null; + $this->image_opacity = null; + $this->image_threshold = null; + $this->image_tint_color = null; + $this->image_overlay_color = null; + $this->image_overlay_opacity = null; + $this->image_negative = false; + $this->image_greyscale = false; + $this->image_pixelate = null; + $this->image_unsharp = false; + $this->image_unsharp_amount = 80; + $this->image_unsharp_radius = 0.5; + $this->image_unsharp_threshold = 1; + + $this->image_text = null; + $this->image_text_direction = null; + $this->image_text_color = '#FFFFFF'; + $this->image_text_opacity = 100; + $this->image_text_background = null; + $this->image_text_background_opacity = 100; + $this->image_text_font = 5; + $this->image_text_size = 16; + $this->image_text_angle = null; + $this->image_text_x = null; + $this->image_text_y = null; + $this->image_text_position = null; + $this->image_text_padding = 0; + $this->image_text_padding_x = null; + $this->image_text_padding_y = null; + $this->image_text_alignment = 'C'; + $this->image_text_line_spacing = 0; + + $this->image_reflection_height = null; + $this->image_reflection_space = 2; + $this->image_reflection_opacity = 60; + + $this->image_watermark = null; + $this->image_watermark_x = null; + $this->image_watermark_y = null; + $this->image_watermark_position = null; + $this->image_watermark_no_zoom_in = true; + $this->image_watermark_no_zoom_out = false; + + $this->image_flip = null; + $this->image_auto_rotate = true; + $this->image_rotate = null; + $this->image_crop = null; + $this->image_precrop = null; + + $this->image_bevel = null; + $this->image_bevel_color1 = '#FFFFFF'; + $this->image_bevel_color2 = '#000000'; + $this->image_border = null; + $this->image_border_color = '#FFFFFF'; + $this->image_border_opacity = 100; + $this->image_border_transparent = null; + $this->image_frame = null; + $this->image_frame_colors = '#FFFFFF #999999 #666666 #000000'; + $this->image_frame_opacity = 100; + + $this->forbidden = array(); + $this->allowed = array( + 'application/arj', + 'application/excel', + 'application/gnutar', + 'application/mspowerpoint', + 'application/msword', + 'application/octet-stream', + 'application/onenote', + 'application/pdf', + 'application/plain', + 'application/postscript', + 'application/powerpoint', + 'application/rar', + 'application/rtf', + 'application/vnd.ms-excel', + 'application/vnd.ms-excel.addin.macroEnabled.12', + 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'application/vnd.ms-excel.template.macroEnabled.12', + 'application/vnd.ms-office', + 'application/vnd.ms-officetheme', + 'application/vnd.ms-powerpoint', + 'application/vnd.ms-powerpoint.addin.macroEnabled.12', + 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'application/vnd.ms-powerpoint.slide.macroEnabled.12', + 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', + 'application/vnd.ms-powerpoint.template.macroEnabled.12', + 'application/vnd.ms-word', + 'application/vnd.ms-word.document.macroEnabled.12', + 'application/vnd.ms-word.template.macroEnabled.12', + 'application/vnd.oasis.opendocument.chart', + 'application/vnd.oasis.opendocument.database', + 'application/vnd.oasis.opendocument.formula', + 'application/vnd.oasis.opendocument.graphics', + 'application/vnd.oasis.opendocument.graphics-template', + 'application/vnd.oasis.opendocument.image', + 'application/vnd.oasis.opendocument.presentation', + 'application/vnd.oasis.opendocument.presentation-template', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/vnd.oasis.opendocument.spreadsheet-template', + 'application/vnd.oasis.opendocument.text', + 'application/vnd.oasis.opendocument.text-master', + 'application/vnd.oasis.opendocument.text-template', + 'application/vnd.oasis.opendocument.text-web', + 'application/vnd.openofficeorg.extension', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'application/vocaltec-media-file', + 'application/wordperfect', + 'application/x-bittorrent', + 'application/x-bzip', + 'application/x-bzip2', + 'application/x-compressed', + 'application/x-excel', + 'application/x-gzip', + 'application/x-latex', + 'application/x-midi', + 'application/xml', + 'application/x-msexcel', + 'application/x-rar', + 'application/x-rar-compressed', + 'application/x-rtf', + 'application/x-shockwave-flash', + 'application/x-sit', + 'application/x-stuffit', + 'application/x-troff-msvideo', + 'application/x-zip', + 'application/x-zip-compressed', + 'application/zip', + 'audio/*', + 'image/*', + 'multipart/x-gzip', + 'multipart/x-zip', + 'text/plain', + 'text/rtf', + 'text/richtext', + 'text/xml', + 'video/*', + 'text/csv' + ); + + $this->mime_types = array( + 'jpg' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'gif' => 'image/gif', + 'png' => 'image/png', + 'bmp' => 'image/bmp', + 'flif' => 'image/flif', + 'flv' => 'video/x-flv', + 'js' => 'application/x-javascript', + 'json' => 'application/json', + 'tiff' => 'image/tiff', + 'css' => 'text/css', + 'xml' => 'application/xml', + 'doc' => 'application/msword', + 'xls' => 'application/vnd.ms-excel', + 'xlt' => 'application/vnd.ms-excel', + 'xlm' => 'application/vnd.ms-excel', + 'xld' => 'application/vnd.ms-excel', + 'xla' => 'application/vnd.ms-excel', + 'xlc' => 'application/vnd.ms-excel', + 'xlw' => 'application/vnd.ms-excel', + 'xll' => 'application/vnd.ms-excel', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pps' => 'application/vnd.ms-powerpoint', + 'rtf' => 'application/rtf', + 'pdf' => 'application/pdf', + 'html' => 'text/html', + 'htm' => 'text/html', + 'php' => 'text/html', + 'txt' => 'text/plain', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'mp3' => 'audio/mpeg3', + 'wav' => 'audio/wav', + 'aiff' => 'audio/aiff', + 'aif' => 'audio/aiff', + 'avi' => 'video/msvideo', + 'wmv' => 'video/x-ms-wmv', + 'mov' => 'video/quicktime', + 'zip' => 'application/zip', + 'tar' => 'application/x-tar', + 'swf' => 'application/x-shockwave-flash', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'ott' => 'application/vnd.oasis.opendocument.text-template', + 'oth' => 'application/vnd.oasis.opendocument.text-web', + 'odm' => 'application/vnd.oasis.opendocument.text-master', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'otg' => 'application/vnd.oasis.opendocument.graphics-template', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'otp' => 'application/vnd.oasis.opendocument.presentation-template', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'odf' => 'application/vnd.oasis.opendocument.formula', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'odi' => 'application/vnd.oasis.opendocument.image', + 'oxt' => 'application/vnd.openofficeorg.extension', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'docm' => 'application/vnd.ms-word.document.macroEnabled.12', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12', + 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', + 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12', + 'thmx' => 'application/vnd.ms-officetheme', + 'onetoc' => 'application/onenote', + 'onetoc2' => 'application/onenote', + 'onetmp' => 'application/onenote', + 'onepkg' => 'application/onenote', + 'csv' => 'text/csv', + ); + + } + + /** + * Constructor, for PHP5+ + */ + function __construct($file, $lang = 'en_GB') { + $this->upload($file, $lang); + } + + /** + * Constructor, for PHP4. Checks if the file has been uploaded + * + * The constructor takes FILES['form_field'] array as argument + * where form_field is the form field name + * + * The constructor will check if the file has been uploaded in its temporary location, and + * accordingly will set {@link uploaded} (and {@link error} is an error occurred) + * + * If the file has been uploaded, the constructor will populate all the variables holding the upload + * information (none of the processing class variables are used here). + * You can have access to information about the file (name, size, MIME type...). + * + * + * Alternatively, you can set the first argument to be a local filename (string) + * This allows processing of a local file, as if the file was uploaded + * + * The optional second argument allows you to set the language for the error messages + * + * @access private + * @param array $file FILES['form_field'] + * or string $file Local filename + * @param string $lang Optional language code + */ + function upload($file, $lang = 'en_GB') { + + $this->version = '0.34dev'; + + $this->file_src_name = ''; + $this->file_src_name_body = ''; + $this->file_src_name_ext = ''; + $this->file_src_mime = ''; + $this->file_src_size = ''; + $this->file_src_error = ''; + $this->file_src_pathname = ''; + $this->file_src_temp = ''; + + $this->file_dst_path = ''; + $this->file_dst_name = ''; + $this->file_dst_name_body = ''; + $this->file_dst_name_ext = ''; + $this->file_dst_pathname = ''; + + $this->image_src_x = null; + $this->image_src_y = null; + $this->image_src_bits = null; + $this->image_src_type = null; + $this->image_src_pixels = null; + $this->image_dst_x = 0; + $this->image_dst_y = 0; + $this->image_dst_type = ''; + + $this->uploaded = true; + $this->no_upload_check = false; + $this->processed = true; + $this->error = ''; + $this->log = ''; + $this->allowed = array(); + $this->forbidden = array(); + $this->file_is_image = false; + $this->init(); + $info = null; + $mime_from_browser = null; + + // sets default language + $this->translation = array(); + $this->translation['file_error'] = 'File error. Please try again.'; + $this->translation['local_file_missing'] = 'Local file doesn\'t exist.'; + $this->translation['local_file_not_readable'] = 'Local file is not readable.'; + $this->translation['uploaded_too_big_ini'] = 'File upload error (the uploaded file exceeds the upload_max_filesize directive in php.ini).'; + $this->translation['uploaded_too_big_html'] = 'File upload error (the uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form).'; + $this->translation['uploaded_partial'] = 'File upload error (the uploaded file was only partially uploaded).'; + $this->translation['uploaded_missing'] = 'File upload error (no file was uploaded).'; + $this->translation['uploaded_no_tmp_dir'] = 'File upload error (missing a temporary folder).'; + $this->translation['uploaded_cant_write'] = 'File upload error (failed to write file to disk).'; + $this->translation['uploaded_err_extension'] = 'File upload error (file upload stopped by extension).'; + $this->translation['uploaded_unknown'] = 'File upload error (unknown error code).'; + $this->translation['try_again'] = 'File upload error. Please try again.'; + $this->translation['file_too_big'] = 'File too big.'; + $this->translation['no_mime'] = 'MIME type can\'t be detected.'; + $this->translation['incorrect_file'] = 'Incorrect type of file.'; + $this->translation['image_too_wide'] = 'Image too wide.'; + $this->translation['image_too_narrow'] = 'Image too narrow.'; + $this->translation['image_too_high'] = 'Image too tall.'; + $this->translation['image_too_short'] = 'Image too short.'; + $this->translation['ratio_too_high'] = 'Image ratio too high (image too wide).'; + $this->translation['ratio_too_low'] = 'Image ratio too low (image too high).'; + $this->translation['too_many_pixels'] = 'Image has too many pixels.'; + $this->translation['not_enough_pixels'] = 'Image has not enough pixels.'; + $this->translation['file_not_uploaded'] = 'File not uploaded. Can\'t carry on a process.'; + $this->translation['already_exists'] = '%s already exists. Please change the file name.'; + $this->translation['temp_file_missing'] = 'No correct temp source file. Can\'t carry on a process.'; + $this->translation['source_missing'] = 'No correct uploaded source file. Can\'t carry on a process.'; + $this->translation['destination_dir'] = 'Destination directory can\'t be created. Can\'t carry on a process.'; + $this->translation['destination_dir_missing'] = 'Destination directory doesn\'t exist. Can\'t carry on a process.'; + $this->translation['destination_path_not_dir'] = 'Destination path is not a directory. Can\'t carry on a process.'; + $this->translation['destination_dir_write'] = 'Destination directory can\'t be made writeable. Can\'t carry on a process.'; + $this->translation['destination_path_write'] = 'Destination path is not a writeable. Can\'t carry on a process.'; + $this->translation['temp_file'] = 'Can\'t create the temporary file. Can\'t carry on a process.'; + $this->translation['source_not_readable'] = 'Source file is not readable. Can\'t carry on a process.'; + $this->translation['no_create_support'] = 'No create from %s support.'; + $this->translation['create_error'] = 'Error in creating %s image from source.'; + $this->translation['source_invalid'] = 'Can\'t read image source. Not an image?.'; + $this->translation['gd_missing'] = 'GD doesn\'t seem to be present.'; + $this->translation['watermark_no_create_support'] = 'No create from %s support, can\'t read watermark.'; + $this->translation['watermark_create_error'] = 'No %s read support, can\'t create watermark.'; + $this->translation['watermark_invalid'] = 'Unknown image format, can\'t read watermark.'; + $this->translation['file_create'] = 'No %s create support.'; + $this->translation['no_conversion_type'] = 'No conversion type defined.'; + $this->translation['copy_failed'] = 'Error copying file on the server. copy() failed.'; + $this->translation['reading_failed'] = 'Error reading the file.'; + + // determines the language + $this->lang = $lang; + if ($this->lang != 'en_GB' && file_exists(dirname(__FILE__).'/lang') && file_exists(dirname(__FILE__).'/lang/class.upload.' . $lang . '.php')) { + $translation = null; + include(dirname(__FILE__).'/lang/class.upload.' . $lang . '.php'); + if (is_array($translation)) { + $this->translation = array_merge($this->translation, $translation); + } else { + $this->lang = 'en_GB'; + } + } + + + // determines the supported MIME types, and matching image format + $this->image_supported = array(); + if ($this->gdversion()) { + if (imagetypes() & IMG_GIF) { + $this->image_supported['image/gif'] = 'gif'; + } + if (imagetypes() & IMG_JPG) { + $this->image_supported['image/jpg'] = 'jpg'; + $this->image_supported['image/jpeg'] = 'jpg'; + $this->image_supported['image/pjpeg'] = 'jpg'; + } + if (imagetypes() & IMG_PNG) { + $this->image_supported['image/png'] = 'png'; + $this->image_supported['image/x-png'] = 'png'; + } + if (imagetypes() & IMG_WBMP) { + $this->image_supported['image/bmp'] = 'bmp'; + $this->image_supported['image/x-ms-bmp'] = 'bmp'; + $this->image_supported['image/x-windows-bmp'] = 'bmp'; + } + } + + // display some system information + if (empty($this->log)) { + $this->log .= 'system information
'; + if ($this->function_enabled('ini_get_all')) { + $inis = ini_get_all(); + $open_basedir = (array_key_exists('open_basedir', $inis) && array_key_exists('local_value', $inis['open_basedir']) && !empty($inis['open_basedir']['local_value'])) ? $inis['open_basedir']['local_value'] : false; + } else { + $open_basedir = false; + } + $gd = $this->gdversion() ? $this->gdversion(true) : 'GD not present'; + $supported = trim((in_array('png', $this->image_supported) ? 'png' : '') . ' ' . (in_array('jpg', $this->image_supported) ? 'jpg' : '') . ' ' . (in_array('gif', $this->image_supported) ? 'gif' : '') . ' ' . (in_array('bmp', $this->image_supported) ? 'bmp' : '')); + $this->log .= '- class version : ' . $this->version . '
'; + $this->log .= '- operating system : ' . PHP_OS . '
'; + $this->log .= '- PHP version : ' . PHP_VERSION . '
'; + $this->log .= '- GD version : ' . $gd . '
'; + $this->log .= '- supported image types : ' . (!empty($supported) ? $supported : 'none') . '
'; + $this->log .= '- open_basedir : ' . (!empty($open_basedir) ? $open_basedir : 'no restriction') . '
'; + $this->log .= '- upload_max_filesize : ' . $this->file_max_size_raw . ' (' . $this->file_max_size . ' bytes)
'; + $this->log .= '- language : ' . $this->lang . '
'; + } + + if (!$file) { + $this->uploaded = false; + $this->error = $this->translate('file_error'); + } + + // check if we sent a local filename or a PHP stream rather than a $_FILE element + if (!is_array($file)) { + if (empty($file)) { + $this->uploaded = false; + $this->error = $this->translate('file_error'); + } else { + if (substr($file, 0, 4) == 'php:' || substr($file, 0, 5) == 'data:' || substr($file, 0, 7) == 'base64:') { + $data = null; + + // this is a PHP stream, i.e.not uploaded + if (substr($file, 0, 4) == 'php:') { + $file = preg_replace('/^php:(.*)/i', '$1', $file); + if (!$file) $file = $_SERVER['HTTP_X_FILE_NAME']; + if (!$file) $file = 'unknown'; + $data = file_get_contents('php://input'); + $this->log .= 'source is a PHP stream ' . $file . ' of length ' . strlen($data) . '
'; + + // this is the raw file data, i.e.not uploaded + } else if (substr($file, 0, 5) == 'data:') { + $data = preg_replace('/^data:(.*)/i', '$1', $file); + $file = 'data'; + $this->log .= 'source is a data string of length ' . strlen($data) . '
'; + + // this is the raw file data, base64-encoded, i.e.not uploaded + } else if (substr($file, 0, 7) == 'base64:') { + $data = base64_decode(preg_replace('/^base64:(.*)/i', '$1', $file)); + $file = 'base64'; + $this->log .= 'source is a base64 data string of length ' . strlen($data) . '
'; + } + + $this->no_upload_check = TRUE; + $this->log .= '- requires a temp file ... '; + $hash = $this->temp_dir() . md5($file . rand(1, 1000)); + if ($data && file_put_contents($hash, $data)) { + $this->file_src_pathname = $hash; + $this->log .= ' file created
'; + $this->log .= '    temp file is: ' . $this->file_src_pathname . '
'; + } else { + $this->log .= ' failed
'; + $this->uploaded = false; + $this->error = $this->translate('temp_file'); + } + + if ($this->uploaded) { + $this->file_src_name = $file; + $this->log .= '- local file OK
'; + preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension); + if (is_array($extension) && sizeof($extension) > 0) { + $this->file_src_name_ext = strtolower($extension[1]); + $this->file_src_name_body = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1); + } else { + $this->file_src_name_ext = ''; + $this->file_src_name_body = $this->file_src_name; + } + $this->file_src_size = (file_exists($this->file_src_pathname) ? filesize($this->file_src_pathname) : 0); + } + $this->file_src_error = 0; + + } else { + // this is a local filename, i.e.not uploaded + $this->log .= 'source is a local file ' . $file . '
'; + $this->no_upload_check = TRUE; + + if ($this->uploaded && !file_exists($file)) { + $this->uploaded = false; + $this->error = $this->translate('local_file_missing'); + } + + if ($this->uploaded && !is_readable($file)) { + $this->uploaded = false; + $this->error = $this->translate('local_file_not_readable'); + } + + if ($this->uploaded) { + $this->file_src_pathname = $file; + $this->file_src_name = basename($file); + $this->log .= '- local file OK
'; + preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension); + if (is_array($extension) && sizeof($extension) > 0) { + $this->file_src_name_ext = strtolower($extension[1]); + $this->file_src_name_body = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1); + } else { + $this->file_src_name_ext = ''; + $this->file_src_name_body = $this->file_src_name; + } + $this->file_src_size = (file_exists($this->file_src_pathname) ? filesize($this->file_src_pathname) : 0); + } + $this->file_src_error = 0; + } + } + } else { + // this is an element from $_FILE, i.e. an uploaded file + $this->log .= 'source is an uploaded file
'; + if ($this->uploaded) { + $this->file_src_error = trim($file['error']); + switch($this->file_src_error) { + case UPLOAD_ERR_OK: + // all is OK + $this->log .= '- upload OK
'; + break; + case UPLOAD_ERR_INI_SIZE: + $this->uploaded = false; + $this->error = $this->translate('uploaded_too_big_ini'); + break; + case UPLOAD_ERR_FORM_SIZE: + $this->uploaded = false; + $this->error = $this->translate('uploaded_too_big_html'); + break; + case UPLOAD_ERR_PARTIAL: + $this->uploaded = false; + $this->error = $this->translate('uploaded_partial'); + break; + case UPLOAD_ERR_NO_FILE: + $this->uploaded = false; + $this->error = $this->translate('uploaded_missing'); + break; + case @UPLOAD_ERR_NO_TMP_DIR: + $this->uploaded = false; + $this->error = $this->translate('uploaded_no_tmp_dir'); + break; + case @UPLOAD_ERR_CANT_WRITE: + $this->uploaded = false; + $this->error = $this->translate('uploaded_cant_write'); + break; + case @UPLOAD_ERR_EXTENSION: + $this->uploaded = false; + $this->error = $this->translate('uploaded_err_extension'); + break; + default: + $this->uploaded = false; + $this->error = $this->translate('uploaded_unknown') . ' ('.$this->file_src_error.')'; + } + } + + if ($this->uploaded) { + $this->file_src_pathname = $file['tmp_name']; + $this->file_src_name = $file['name']; + if ($this->file_src_name == '') { + $this->uploaded = false; + $this->error = $this->translate('try_again'); + } + } + + if ($this->uploaded) { + $this->log .= '- file name OK
'; + preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension); + if (is_array($extension) && sizeof($extension) > 0) { + $this->file_src_name_ext = strtolower($extension[1]); + $this->file_src_name_body = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1); + } else { + $this->file_src_name_ext = ''; + $this->file_src_name_body = $this->file_src_name; + } + $this->file_src_size = $file['size']; + $mime_from_browser = $file['type']; + } + } + + if ($this->uploaded) { + $this->log .= 'determining MIME type
'; + $this->file_src_mime = null; + + // checks MIME type with Fileinfo PECL extension + if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) { + if ($this->mime_fileinfo) { + $this->log .= '- Checking MIME type with Fileinfo PECL extension
'; + if ($this->function_enabled('finfo_open')) { + $path = null; + if ($this->mime_fileinfo !== '') { + if ($this->mime_fileinfo === true) { + if (getenv('MAGIC') === FALSE) { + if (substr(PHP_OS, 0, 3) == 'WIN') { + $path = realpath(ini_get('extension_dir') . '/../') . '/extras/magic'; + $this->log .= '    MAGIC path defaults to ' . $path . '
'; + } + } else { + $path = getenv('MAGIC'); + $this->log .= '    MAGIC path is set to ' . $path . ' from MAGIC variable
'; + } + } else { + $path = $this->mime_fileinfo; + $this->log .= '    MAGIC path is set to ' . $path . '
'; + } + } + if ($path) { + $f = @finfo_open(FILEINFO_MIME, $path); + } else { + $this->log .= '    MAGIC path will not be used
'; + $f = @finfo_open(FILEINFO_MIME); + } + if (is_resource($f)) { + $mime = finfo_file($f, realpath($this->file_src_pathname)); + finfo_close($f); + $this->file_src_mime = $mime; + $this->log .= '    MIME type detected as ' . $this->file_src_mime . ' by Fileinfo PECL extension
'; + if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) { + $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime); + $this->log .= '- MIME validated as ' . $this->file_src_mime . '
'; + } else { + $this->file_src_mime = null; + } + } else { + $this->log .= '    Fileinfo PECL extension failed (finfo_open)
'; + } + } elseif (@class_exists('finfo')) { + $f = new finfo( FILEINFO_MIME ); + if ($f) { + $this->file_src_mime = $f->file(realpath($this->file_src_pathname)); + $this->log .= '- MIME type detected as ' . $this->file_src_mime . ' by Fileinfo PECL extension
'; + if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) { + $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime); + $this->log .= '- MIME validated as ' . $this->file_src_mime . '
'; + } else { + $this->file_src_mime = null; + } + } else { + $this->log .= '    Fileinfo PECL extension failed (finfo)
'; + } + } else { + $this->log .= '    Fileinfo PECL extension not available
'; + } + } else { + $this->log .= '- Fileinfo PECL extension deactivated
'; + } + } + + // checks MIME type with shell if unix access is authorized + if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) { + if ($this->mime_file) { + $this->log .= '- Checking MIME type with UNIX file() command
'; + if (substr(PHP_OS, 0, 3) != 'WIN') { + if ($this->function_enabled('exec') && $this->function_enabled('escapeshellarg')) { + if (strlen($mime = @exec("file -bi ".escapeshellarg($this->file_src_pathname))) != 0) { + $this->file_src_mime = trim($mime); + $this->log .= '    MIME type detected as ' . $this->file_src_mime . ' by UNIX file() command
'; + if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) { + $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime); + $this->log .= '- MIME validated as ' . $this->file_src_mime . '
'; + } else { + $this->file_src_mime = null; + } + } else { + $this->log .= '    UNIX file() command failed
'; + } + } else { + $this->log .= '    PHP exec() function is disabled
'; + } + } else { + $this->log .= '    UNIX file() command not availabled
'; + } + } else { + $this->log .= '- UNIX file() command is deactivated
'; + } + } + + // checks MIME type with mime_magic + if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) { + if ($this->mime_magic) { + $this->log .= '- Checking MIME type with mime.magic file (mime_content_type())
'; + if ($this->function_enabled('mime_content_type')) { + $this->file_src_mime = mime_content_type($this->file_src_pathname); + $this->log .= '    MIME type detected as ' . $this->file_src_mime . ' by mime_content_type()
'; + if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) { + $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime); + $this->log .= '- MIME validated as ' . $this->file_src_mime . '
'; + } else { + $this->file_src_mime = null; + } + } else { + $this->log .= '    mime_content_type() is not available
'; + } + } else { + $this->log .= '- mime.magic file (mime_content_type()) is deactivated
'; + } + } + + // checks MIME type with getimagesize() + if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) { + if ($this->mime_getimagesize) { + $this->log .= '- Checking MIME type with getimagesize()
'; + $info = getimagesize($this->file_src_pathname); + if (is_array($info) && array_key_exists('mime', $info)) { + $this->file_src_mime = trim($info['mime']); + if (empty($this->file_src_mime)) { + $this->log .= '    MIME empty, guessing from type
'; + $mime = (is_array($info) && array_key_exists(2, $info) ? $info[2] : null); // 1 = GIF, 2 = JPG, 3 = PNG + $this->file_src_mime = ($mime==IMAGETYPE_GIF ? 'image/gif' : ($mime==IMAGETYPE_JPEG ? 'image/jpeg' : ($mime==IMAGETYPE_PNG ? 'image/png' : ($mime==IMAGETYPE_BMP ? 'image/bmp' : null)))); + } + $this->log .= '    MIME type detected as ' . $this->file_src_mime . ' by PHP getimagesize() function
'; + if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) { + $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime); + $this->log .= '- MIME validated as ' . $this->file_src_mime . '
'; + } else { + $this->file_src_mime = null; + } + } else { + $this->log .= '    getimagesize() failed
'; + } + } else { + $this->log .= '- getimagesize() is deactivated
'; + } + } + + // default to MIME from browser (or Flash) + if (!empty($mime_from_browser) && !$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime)) { + $this->file_src_mime =$mime_from_browser; + $this->log .= '- MIME type detected as ' . $this->file_src_mime . ' by browser
'; + if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) { + $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime); + $this->log .= '- MIME validated as ' . $this->file_src_mime . '
'; + } else { + $this->file_src_mime = null; + } + } + + // we need to work some magic if we upload via Flash + if ($this->file_src_mime == 'application/octet-stream' || !$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) { + if ($this->file_src_mime == 'application/octet-stream') $this->log .= '- Flash may be rewriting MIME as application/octet-stream
'; + $this->log .= '- Try to guess MIME type from file extension (' . $this->file_src_name_ext . '): '; + if (array_key_exists($this->file_src_name_ext, $this->mime_types)) $this->file_src_mime = $this->mime_types[$this->file_src_name_ext]; + if ($this->file_src_mime == 'application/octet-stream') { + $this->log .= 'doesn\'t look like anything known
'; + } else { + $this->log .= 'MIME type set to ' . $this->file_src_mime . '
'; + } + } + + if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === FALSE) { + $this->log .= '- MIME type couldn\'t be detected! (' . (string) $this->file_src_mime . ')
'; + } + + // determine whether the file is an image + if ($this->file_src_mime && is_string($this->file_src_mime) && !empty($this->file_src_mime) && array_key_exists($this->file_src_mime, $this->image_supported)) { + $this->file_is_image = true; + $this->image_src_type = $this->image_supported[$this->file_src_mime]; + } + + // if the file is an image, we gather some useful data + if ($this->file_is_image) { + if ($h = fopen($this->file_src_pathname, 'r')) { + fclose($h); + $info = getimagesize($this->file_src_pathname); + if (is_array($info)) { + $this->image_src_x = $info[0]; + $this->image_src_y = $info[1]; + $this->image_dst_x = $this->image_src_x; + $this->image_dst_y = $this->image_src_y; + $this->image_src_pixels = $this->image_src_x * $this->image_src_y; + $this->image_src_bits = array_key_exists('bits', $info) ? $info['bits'] : null; + } else { + $this->file_is_image = false; + $this->uploaded = false; + $this->log .= '- can\'t retrieve image information, image may have been tampered with
'; + $this->error = $this->translate('source_invalid'); + } + } else { + $this->log .= '- can\'t read source file directly. open_basedir restriction in place?
'; + } + } + + $this->log .= 'source variables
'; + $this->log .= '- You can use all these before calling process()
'; + $this->log .= '    file_src_name : ' . $this->file_src_name . '
'; + $this->log .= '    file_src_name_body : ' . $this->file_src_name_body . '
'; + $this->log .= '    file_src_name_ext : ' . $this->file_src_name_ext . '
'; + $this->log .= '    file_src_pathname : ' . $this->file_src_pathname . '
'; + $this->log .= '    file_src_mime : ' . $this->file_src_mime . '
'; + $this->log .= '    file_src_size : ' . $this->file_src_size . ' (max= ' . $this->file_max_size . ')
'; + $this->log .= '    file_src_error : ' . $this->file_src_error . '
'; + + if ($this->file_is_image) { + $this->log .= '- source file is an image
'; + $this->log .= '    image_src_x : ' . $this->image_src_x . '
'; + $this->log .= '    image_src_y : ' . $this->image_src_y . '
'; + $this->log .= '    image_src_pixels : ' . $this->image_src_pixels . '
'; + $this->log .= '    image_src_type : ' . $this->image_src_type . '
'; + $this->log .= '    image_src_bits : ' . $this->image_src_bits . '
'; + } + } + + } + + /** + * Returns the version of GD + * + * @access public + * @param boolean $full Optional flag to get precise version + * @return float GD version + */ + function gdversion($full = false) { + static $gd_version = null; + static $gd_full_version = null; + if ($gd_version === null) { + if ($this->function_enabled('gd_info')) { + $gd = gd_info(); + $gd = $gd["GD Version"]; + $regex = "/([\d\.]+)/i"; + } else { + ob_start(); + phpinfo(8); + $gd = ob_get_contents(); + ob_end_clean(); + $regex = "/\bgd\s+version\b[^\d\n\r]+?([\d\.]+)/i"; + } + if (preg_match($regex, $gd, $m)) { + $gd_full_version = (string) $m[1]; + $gd_version = (float) $m[1]; + } else { + $gd_full_version = 'none'; + $gd_version = 0; + } + } + if ($full) { + return $gd_full_version; + } else { + return $gd_version; + } + } + + /** + * Checks if a function is available + * + * @access private + * @param string $func Function name + * @return boolean Success + */ + function function_enabled($func) { + // cache the list of disabled functions + static $disabled = null; + if ($disabled === null) $disabled = array_map('trim', array_map('strtolower', explode(',', ini_get('disable_functions')))); + // cache the list of functions blacklisted by suhosin + static $blacklist = null; + if ($blacklist === null) $blacklist = extension_loaded('suhosin') ? array_map('trim', array_map('strtolower', explode(',', ini_get(' suhosin.executor.func.blacklist')))) : array(); + // checks if the function is really enabled + return (function_exists($func) && !in_array($func, $disabled) && !in_array($func, $blacklist)); + } + + /** + * Creates directories recursively + * + * @access private + * @param string $path Path to create + * @param integer $mode Optional permissions + * @return boolean Success + */ + function rmkdir($path, $mode = 0777) { + return is_dir($path) || ( $this->rmkdir(dirname($path), $mode) && $this->_mkdir($path, $mode) ); + } + + /** + * Creates directory + * + * @access private + * @param string $path Path to create + * @param integer $mode Optional permissions + * @return boolean Success + */ + function _mkdir($path, $mode = 0777) { + $old = umask(0); + $res = @mkdir($path, $mode); + umask($old); + return $res; + } + + /** + * Translate error messages + * + * @access private + * @param string $str Message to translate + * @param array $tokens Optional token values + * @return string Translated string + */ + function translate($str, $tokens = array()) { + if (array_key_exists($str, $this->translation)) $str = $this->translation[$str]; + if (is_array($tokens) && sizeof($tokens) > 0) $str = vsprintf($str, $tokens); + return $str; + } + + /** + * Returns the temp directory + * + * @access private + * @return string Temp directory string + */ + function temp_dir() { + $dir = ''; + if ($this->function_enabled('sys_get_temp_dir')) $dir = sys_get_temp_dir(); + if (!$dir && $tmp=getenv('TMP')) $dir = $tmp; + if (!$dir && $tmp=getenv('TEMP')) $dir = $tmp; + if (!$dir && $tmp=getenv('TMPDIR')) $dir = $tmp; + if (!$dir) { + $tmp = tempnam(__FILE__,''); + if (file_exists($tmp)) { + unlink($tmp); + $dir = dirname($tmp); + } + } + if (!$dir) return ''; + $slash = (strtolower(substr(PHP_OS, 0, 3)) === 'win' ? '\\' : '/'); + if (substr($dir, -1) != $slash) $dir = $dir . $slash; + return $dir; + } + + /** + * Decodes colors + * + * @access private + * @param string $color Color string + * @return array RGB colors + */ + function getcolors($color) { + $color = str_replace('#', '', $color); + if (strlen($color) == 3) $color = str_repeat(substr($color, 0, 1), 2) . str_repeat(substr($color, 1, 1), 2) . str_repeat(substr($color, 2, 1), 2); + $r = sscanf($color, "%2x%2x%2x"); + $red = (is_array($r) && array_key_exists(0, $r) && is_numeric($r[0]) ? $r[0] : 0); + $green = (is_array($r) && array_key_exists(1, $r) && is_numeric($r[1]) ? $r[1] : 0); + $blue = (is_array($r) && array_key_exists(2, $r) && is_numeric($r[2]) ? $r[2] : 0); + return array($red, $green, $blue); + } + + /** + * Decodes sizes + * + * @access private + * @param string $size Size in bytes, or shorthand byte options + * @return integer Size in bytes + */ + function getsize($size) { + if ($size === null) return null; + $last = strtolower($size{strlen($size)-1}); + $size = (int) $size; + switch($last) { + case 'g': + $size *= 1024; + case 'm': + $size *= 1024; + case 'k': + $size *= 1024; + } + return $size; + } + + /** + * Decodes offsets + * + * @access private + * @param misc $offsets Offsets, as an integer, a string or an array + * @param integer $x Reference picture width + * @param integer $y Reference picture height + * @param boolean $round Round offsets before returning them + * @param boolean $negative Allow negative offsets to be returned + * @return array Array of four offsets (TRBL) + */ + function getoffsets($offsets, $x, $y, $round = true, $negative = true) { + if (!is_array($offsets)) $offsets = explode(' ', $offsets); + if (sizeof($offsets) == 4) { + $ct = $offsets[0]; $cr = $offsets[1]; $cb = $offsets[2]; $cl = $offsets[3]; + } else if (sizeof($offsets) == 2) { + $ct = $offsets[0]; $cr = $offsets[1]; $cb = $offsets[0]; $cl = $offsets[1]; + } else { + $ct = $offsets[0]; $cr = $offsets[0]; $cb = $offsets[0]; $cl = $offsets[0]; + } + if (strpos($ct, '%')>0) $ct = $y * (str_replace('%','',$ct) / 100); + if (strpos($cr, '%')>0) $cr = $x * (str_replace('%','',$cr) / 100); + if (strpos($cb, '%')>0) $cb = $y * (str_replace('%','',$cb) / 100); + if (strpos($cl, '%')>0) $cl = $x * (str_replace('%','',$cl) / 100); + if (strpos($ct, 'px')>0) $ct = str_replace('px','',$ct); + if (strpos($cr, 'px')>0) $cr = str_replace('px','',$cr); + if (strpos($cb, 'px')>0) $cb = str_replace('px','',$cb); + if (strpos($cl, 'px')>0) $cl = str_replace('px','',$cl); + $ct = (int) $ct; $cr = (int) $cr; $cb = (int) $cb; $cl = (int) $cl; + if ($round) { + $ct = round($ct); + $cr = round($cr); + $cb = round($cb); + $cl = round($cl); + } + if (!$negative) { + if ($ct < 0) $ct = 0; + if ($cr < 0) $cr = 0; + if ($cb < 0) $cb = 0; + if ($cl < 0) $cl = 0; + } + return array($ct, $cr, $cb, $cl); + } + + /** + * Creates a container image + * + * @access private + * @param integer $x Width + * @param integer $y Height + * @param boolean $fill Optional flag to draw the background color or not + * @param boolean $trsp Optional flag to set the background to be transparent + * @return resource Container image + */ + function imagecreatenew($x, $y, $fill = true, $trsp = false) { + if ($x < 1) $x = 1; if ($y < 1) $y = 1; + if ($this->gdversion() >= 2 && !$this->image_is_palette) { + // create a true color image + $dst_im = imagecreatetruecolor($x, $y); + // this preserves transparency in PNGs, in true color + if (empty($this->image_background_color) || $trsp) { + imagealphablending($dst_im, false ); + imagefilledrectangle($dst_im, 0, 0, $x, $y, imagecolorallocatealpha($dst_im, 0, 0, 0, 127)); + } + } else { + // creates a palette image + $dst_im = imagecreate($x, $y); + // preserves transparency for palette images, if the original image has transparency + if (($fill && $this->image_is_transparent && empty($this->image_background_color)) || $trsp) { + imagefilledrectangle($dst_im, 0, 0, $x, $y, $this->image_transparent_color); + imagecolortransparent($dst_im, $this->image_transparent_color); + } + } + // fills with background color if any is set + if ($fill && !empty($this->image_background_color) && !$trsp) { + list($red, $green, $blue) = $this->getcolors($this->image_background_color); + $background_color = imagecolorallocate($dst_im, $red, $green, $blue); + imagefilledrectangle($dst_im, 0, 0, $x, $y, $background_color); + } + return $dst_im; + } + + + /** + * Transfers an image from the container to the destination image + * + * @access private + * @param resource $src_im Container image + * @param resource $dst_im Destination image + * @return resource Destination image + */ + function imagetransfer($src_im, $dst_im) { + if (is_resource($dst_im)) imagedestroy($dst_im); + $dst_im = & $src_im; + return $dst_im; + } + + /** + * Merges two images + * + * If the output format is PNG, then we do it pixel per pixel to retain the alpha channel + * + * @access private + * @param resource $dst_img Destination image + * @param resource $src_img Overlay image + * @param int $dst_x x-coordinate of destination point + * @param int $dst_y y-coordinate of destination point + * @param int $src_x x-coordinate of source point + * @param int $src_y y-coordinate of source point + * @param int $src_w Source width + * @param int $src_h Source height + * @param int $pct Optional percentage of the overlay, between 0 and 100 (default: 100) + * @return resource Destination image + */ + function imagecopymergealpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct = 0) { + $dst_x = (int) $dst_x; + $dst_y = (int) $dst_y; + $src_x = (int) $src_x; + $src_y = (int) $src_y; + $src_w = (int) $src_w; + $src_h = (int) $src_h; + $pct = (int) $pct; + $dst_w = imagesx($dst_im); + $dst_h = imagesy($dst_im); + + for ($y = $src_y; $y < $src_h; $y++) { + for ($x = $src_x; $x < $src_w; $x++) { + + if ($x + $dst_x >= 0 && $x + $dst_x < $dst_w && $x + $src_x >= 0 && $x + $src_x < $src_w + && $y + $dst_y >= 0 && $y + $dst_y < $dst_h && $y + $src_y >= 0 && $y + $src_y < $src_h) { + + $dst_pixel = imagecolorsforindex($dst_im, imagecolorat($dst_im, $x + $dst_x, $y + $dst_y)); + $src_pixel = imagecolorsforindex($src_im, imagecolorat($src_im, $x + $src_x, $y + $src_y)); + + $src_alpha = 1 - ($src_pixel['alpha'] / 127); + $dst_alpha = 1 - ($dst_pixel['alpha'] / 127); + $opacity = $src_alpha * $pct / 100; + if ($dst_alpha >= $opacity) $alpha = $dst_alpha; + if ($dst_alpha < $opacity) $alpha = $opacity; + if ($alpha > 1) $alpha = 1; + + if ($opacity > 0) { + $dst_red = round(( ($dst_pixel['red'] * $dst_alpha * (1 - $opacity)) ) ); + $dst_green = round(( ($dst_pixel['green'] * $dst_alpha * (1 - $opacity)) ) ); + $dst_blue = round(( ($dst_pixel['blue'] * $dst_alpha * (1 - $opacity)) ) ); + $src_red = round((($src_pixel['red'] * $opacity)) ); + $src_green = round((($src_pixel['green'] * $opacity)) ); + $src_blue = round((($src_pixel['blue'] * $opacity)) ); + $red = round(($dst_red + $src_red ) / ($dst_alpha * (1 - $opacity) + $opacity)); + $green = round(($dst_green + $src_green) / ($dst_alpha * (1 - $opacity) + $opacity)); + $blue = round(($dst_blue + $src_blue ) / ($dst_alpha * (1 - $opacity) + $opacity)); + if ($red > 255) $red = 255; + if ($green > 255) $green = 255; + if ($blue > 255) $blue = 255; + $alpha = round((1 - $alpha) * 127); + $color = imagecolorallocatealpha($dst_im, $red, $green, $blue, $alpha); + imagesetpixel($dst_im, $x + $dst_x, $y + $dst_y, $color); + } + } + } + } + return true; + } + + + + /** + * Actually uploads the file, and act on it according to the set processing class variables + * + * This function copies the uploaded file to the given location, eventually performing actions on it. + * Typically, you can call {@link process} several times for the same file, + * for instance to create a resized image and a thumbnail of the same file. + * The original uploaded file remains intact in its temporary location, so you can use {@link process} several times. + * You will be able to delete the uploaded file with {@link clean} when you have finished all your {@link process} calls. + * + * According to the processing class variables set in the calling file, the file can be renamed, + * and if it is an image, can be resized or converted. + * + * When the processing is completed, and the file copied to its new location, the + * processing class variables will be reset to their default value. + * This allows you to set new properties, and perform another {@link process} on the same uploaded file + * + * If the function is called with a null or empty argument, then it will return the content of the picture + * + * It will set {@link processed} (and {@link error} is an error occurred) + * + * @access public + * @param string $server_path Optional path location of the uploaded file, with an ending slash + * @return string Optional content of the image + */ + function process($server_path = null) { + $this->error = ''; + $this->processed = true; + $return_mode = false; + $return_content = null; + + // clean up dst variables + $this->file_dst_path = ''; + $this->file_dst_pathname = ''; + $this->file_dst_name = ''; + $this->file_dst_name_body = ''; + $this->file_dst_name_ext = ''; + + // clean up some parameters + $this->file_max_size = $this->getsize($this->file_max_size); + $this->jpeg_size = $this->getsize($this->jpeg_size); + + // copy some variables as we need to keep them clean + $file_src_name = $this->file_src_name; + $file_src_name_body = $this->file_src_name_body; + $file_src_name_ext = $this->file_src_name_ext; + + if (!$this->uploaded) { + $this->error = $this->translate('file_not_uploaded'); + $this->processed = false; + } + + if ($this->processed) { + if (empty($server_path) || is_null($server_path)) { + $this->log .= 'process file and return the content
'; + $return_mode = true; + } else { + if(strtolower(substr(PHP_OS, 0, 3)) === 'win') { + if (substr($server_path, -1, 1) != '\\') $server_path = $server_path . '\\'; + } else { + if (substr($server_path, -1, 1) != '/') $server_path = $server_path . '/'; + } + $this->log .= 'process file to ' . $server_path . '
'; + } + } + + if ($this->processed) { + // checks file max size + if ($this->file_src_size > $this->file_max_size) { + $this->processed = false; + $this->error = $this->translate('file_too_big') . ' : ' . $this->file_src_size . ' > ' . $this->file_max_size; + } else { + $this->log .= '- file size OK
'; + } + } + + if ($this->processed) { + // if we have an image without extension, set it + if ($this->file_force_extension && $this->file_is_image && !$this->file_src_name_ext) $file_src_name_ext = $this->image_src_type; + // turn dangerous scripts into text files + if ($this->no_script) { + // if the file has no extension, we try to guess it from the MIME type + if ($this->file_force_extension && empty($file_src_name_ext)) { + if ($key = array_search($this->file_src_mime, $this->mime_types)) { + $file_src_name_ext = $key; + $file_src_name = $file_src_name_body . '.' . $file_src_name_ext; + $this->log .= '- file renamed as ' . $file_src_name_body . '.' . $file_src_name_ext . '!
'; + } + } + // if the file is text based, or has a dangerous extension, we rename it as .txt + if ((((substr($this->file_src_mime, 0, 5) == 'text/' && $this->file_src_mime != 'text/rtf') || strpos($this->file_src_mime, 'javascript') !== false) && (substr($file_src_name, -4) != '.txt')) + || preg_match('/\.(php|php5|php4|php3|phtml|pl|py|cgi|asp|js)$/i', $this->file_src_name) + || $this->file_force_extension && empty($file_src_name_ext)) { + $this->file_src_mime = 'text/plain'; + if ($this->file_src_name_ext) $file_src_name_body = $file_src_name_body . '.' . $this->file_src_name_ext; + $file_src_name_ext = 'txt'; + $file_src_name = $file_src_name_body . '.' . $file_src_name_ext; + $this->log .= '- script renamed as ' . $file_src_name_body . '.' . $file_src_name_ext . '!
'; + } + } + + if ($this->mime_check && empty($this->file_src_mime)) { + $this->processed = false; + $this->error = $this->translate('no_mime'); + } else if ($this->mime_check && !empty($this->file_src_mime) && strpos($this->file_src_mime, '/') !== false) { + list($m1, $m2) = explode('/', $this->file_src_mime); + $allowed = false; + // check wether the mime type is allowed + if (!is_array($this->allowed)) $this->allowed = array($this->allowed); + foreach($this->allowed as $k => $v) { + list($v1, $v2) = explode('/', $v); + if (($v1 == '*' && $v2 == '*') || ($v1 == $m1 && ($v2 == $m2 || $v2 == '*'))) { + $allowed = true; + break; + } + } + // check wether the mime type is forbidden + if (!is_array($this->forbidden)) $this->forbidden = array($this->forbidden); + foreach($this->forbidden as $k => $v) { + list($v1, $v2) = explode('/', $v); + if (($v1 == '*' && $v2 == '*') || ($v1 == $m1 && ($v2 == $m2 || $v2 == '*'))) { + $allowed = false; + break; + } + } + if (!$allowed) { + $this->processed = false; + $this->error = $this->translate('incorrect_file'); + } else { + $this->log .= '- file mime OK : ' . $this->file_src_mime . '
'; + } + } else { + $this->log .= '- file mime (not checked) : ' . $this->file_src_mime . '
'; + } + + // if the file is an image, we can check on its dimensions + // these checks are not available if open_basedir restrictions are in place + if ($this->file_is_image) { + if (is_numeric($this->image_src_x) && is_numeric($this->image_src_y)) { + $ratio = $this->image_src_x / $this->image_src_y; + if (!is_null($this->image_max_width) && $this->image_src_x > $this->image_max_width) { + $this->processed = false; + $this->error = $this->translate('image_too_wide'); + } + if (!is_null($this->image_min_width) && $this->image_src_x < $this->image_min_width) { + $this->processed = false; + $this->error = $this->translate('image_too_narrow'); + } + if (!is_null($this->image_max_height) && $this->image_src_y > $this->image_max_height) { + $this->processed = false; + $this->error = $this->translate('image_too_high'); + } + if (!is_null($this->image_min_height) && $this->image_src_y < $this->image_min_height) { + $this->processed = false; + $this->error = $this->translate('image_too_short'); + } + if (!is_null($this->image_max_ratio) && $ratio > $this->image_max_ratio) { + $this->processed = false; + $this->error = $this->translate('ratio_too_high'); + } + if (!is_null($this->image_min_ratio) && $ratio < $this->image_min_ratio) { + $this->processed = false; + $this->error = $this->translate('ratio_too_low'); + } + if (!is_null($this->image_max_pixels) && $this->image_src_pixels > $this->image_max_pixels) { + $this->processed = false; + $this->error = $this->translate('too_many_pixels'); + } + if (!is_null($this->image_min_pixels) && $this->image_src_pixels < $this->image_min_pixels) { + $this->processed = false; + $this->error = $this->translate('not_enough_pixels'); + } + } else { + $this->log .= '- no image properties available, can\'t enforce dimension checks : ' . $this->file_src_mime . '
'; + } + } + } + + if ($this->processed) { + $this->file_dst_path = $server_path; + + // repopulate dst variables from src + $this->file_dst_name = $file_src_name; + $this->file_dst_name_body = $file_src_name_body; + $this->file_dst_name_ext = $file_src_name_ext; + if ($this->file_overwrite) $this->file_auto_rename = false; + + if ($this->image_convert && $this->file_is_image) { // if we convert as an image + if ($this->file_src_name_ext) $this->file_dst_name_ext = $this->image_convert; + $this->log .= '- new file name ext : ' . $this->image_convert . '
'; + } + if (!is_null($this->file_new_name_body)) { // rename file body + $this->file_dst_name_body = $this->file_new_name_body; + $this->log .= '- new file name body : ' . $this->file_new_name_body . '
'; + } + if (!is_null($this->file_new_name_ext)) { // rename file ext + $this->file_dst_name_ext = $this->file_new_name_ext; + $this->log .= '- new file name ext : ' . $this->file_new_name_ext . '
'; + } + if (!is_null($this->file_name_body_add)) { // append a string to the name + $this->file_dst_name_body = $this->file_dst_name_body . $this->file_name_body_add; + $this->log .= '- file name body append : ' . $this->file_name_body_add . '
'; + } + if (!is_null($this->file_name_body_pre)) { // prepend a string to the name + $this->file_dst_name_body = $this->file_name_body_pre . $this->file_dst_name_body; + $this->log .= '- file name body prepend : ' . $this->file_name_body_pre . '
'; + } + if ($this->file_safe_name) { // formats the name + $this->file_dst_name_body = utf8_encode(strtr(utf8_decode($this->file_dst_name_body), utf8_decode('ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöøùúûüýÿ'), 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy')); + $this->file_dst_name_body = strtr($this->file_dst_name_body, array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss', 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u')); + $this->file_dst_name_body = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $this->file_dst_name_body); + $this->log .= '- file name safe format
'; + } + + $this->log .= '- destination variables
'; + if (empty($this->file_dst_path) || is_null($this->file_dst_path)) { + $this->log .= '    file_dst_path : n/a
'; + } else { + $this->log .= '    file_dst_path : ' . $this->file_dst_path . '
'; + } + $this->log .= '    file_dst_name_body : ' . $this->file_dst_name_body . '
'; + $this->log .= '    file_dst_name_ext : ' . $this->file_dst_name_ext . '
'; + + // set the destination file name + $this->file_dst_name = $this->file_dst_name_body . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''); + + if (!$return_mode) { + if (!$this->file_auto_rename) { + $this->log .= '- no auto_rename if same filename exists
'; + $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name; + } else { + $this->log .= '- checking for auto_rename
'; + $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name; + $body = $this->file_dst_name_body; + $ext = ''; + // if we have changed the extension, then we add our increment before + if ($file_src_name_ext != $this->file_src_name_ext) { + if (substr($this->file_dst_name_body, -1 - strlen($this->file_src_name_ext)) == '.' . $this->file_src_name_ext) { + $body = substr($this->file_dst_name_body, 0, strlen($this->file_dst_name_body) - 1 - strlen($this->file_src_name_ext)); + $ext = '.' . $this->file_src_name_ext; + } + } + $cpt = 1; + while (@file_exists($this->file_dst_pathname)) { + $this->file_dst_name_body = $body . '_' . $cpt . $ext; + $this->file_dst_name = $this->file_dst_name_body . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''); + $cpt++; + $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name; + } + if ($cpt>1) $this->log .= '    auto_rename to ' . $this->file_dst_name . '
'; + } + + $this->log .= '- destination file details
'; + $this->log .= '    file_dst_name : ' . $this->file_dst_name . '
'; + $this->log .= '    file_dst_pathname : ' . $this->file_dst_pathname . '
'; + + if ($this->file_overwrite) { + $this->log .= '- no overwrite checking
'; + } else { + if (@file_exists($this->file_dst_pathname)) { + $this->processed = false; + $this->error = $this->translate('already_exists', array($this->file_dst_name)); + } else { + $this->log .= '- ' . $this->file_dst_name . ' doesn\'t exist already
'; + } + } + } + } + + if ($this->processed) { + // if we have already moved the uploaded file, we use the temporary copy as source file, and check if it exists + if (!empty($this->file_src_temp)) { + $this->log .= '- use the temp file instead of the original file since it is a second process
'; + $this->file_src_pathname = $this->file_src_temp; + if (!file_exists($this->file_src_pathname)) { + $this->processed = false; + $this->error = $this->translate('temp_file_missing'); + } + // if we haven't a temp file, and that we do check on uploads, we use is_uploaded_file() + } else if (!$this->no_upload_check) { + if (!is_uploaded_file($this->file_src_pathname)) { + $this->processed = false; + $this->error = $this->translate('source_missing'); + } + // otherwise, if we don't check on uploaded files (local file for instance), we use file_exists() + } else { + if (!file_exists($this->file_src_pathname)) { + $this->processed = false; + $this->error = $this->translate('source_missing'); + } + } + + // checks if the destination directory exists, and attempt to create it + if (!$return_mode) { + if ($this->processed && !file_exists($this->file_dst_path)) { + if ($this->dir_auto_create) { + $this->log .= '- ' . $this->file_dst_path . ' doesn\'t exist. Attempting creation:'; + if (!$this->rmkdir($this->file_dst_path, $this->dir_chmod)) { + $this->log .= ' failed
'; + $this->processed = false; + $this->error = $this->translate('destination_dir'); + } else { + $this->log .= ' success
'; + } + } else { + $this->error = $this->translate('destination_dir_missing'); + } + } + + if ($this->processed && !is_dir($this->file_dst_path)) { + $this->processed = false; + $this->error = $this->translate('destination_path_not_dir'); + } + + // checks if the destination directory is writeable, and attempt to make it writeable + $hash = md5($this->file_dst_name_body . rand(1, 1000)); + if ($this->processed && !($f = @fopen($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''), 'a+'))) { + if ($this->dir_auto_chmod) { + $this->log .= '- ' . $this->file_dst_path . ' is not writeable. Attempting chmod:'; + if (!@chmod($this->file_dst_path, $this->dir_chmod)) { + $this->log .= ' failed
'; + $this->processed = false; + $this->error = $this->translate('destination_dir_write'); + } else { + $this->log .= ' success
'; + if (!($f = @fopen($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''), 'a+'))) { // we re-check + $this->processed = false; + $this->error = $this->translate('destination_dir_write'); + } else { + @fclose($f); + } + } + } else { + $this->processed = false; + $this->error = $this->translate('destination_path_write'); + } + } else { + if ($this->processed) @fclose($f); + @unlink($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : '')); + } + + + // if we have an uploaded file, and if it is the first process, and if we can't access the file directly (open_basedir restriction) + // then we create a temp file that will be used as the source file in subsequent processes + // the third condition is there to check if the file is not accessible *directly* (it already has positively gone through is_uploaded_file(), so it exists) + if (!$this->no_upload_check && empty($this->file_src_temp) && !@file_exists($this->file_src_pathname)) { + $this->log .= '- attempting to use a temp file:'; + $hash = md5($this->file_dst_name_body . rand(1, 1000)); + if (move_uploaded_file($this->file_src_pathname, $this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''))) { + $this->file_src_pathname = $this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''); + $this->file_src_temp = $this->file_src_pathname; + $this->log .= ' file created
'; + $this->log .= '    temp file is: ' . $this->file_src_temp . '
'; + } else { + $this->log .= ' failed
'; + $this->processed = false; + $this->error = $this->translate('temp_file'); + } + } + } + } + + if ($this->processed) { + + // check if we need to autorotate, to automatically pre-rotates the image according to EXIF data (JPEG only) + $auto_flip = false; + $auto_rotate = 0; + if ($this->file_is_image && $this->image_auto_rotate && $this->image_src_type == 'jpg' && $this->function_enabled('exif_read_data')) { + $exif = @exif_read_data($this->file_src_pathname); + if (is_array($exif) && isset($exif['Orientation'])) { + $orientation = $exif['Orientation']; + switch($orientation) { + case 1: + $this->log .= '- EXIF orientation = 1 : default
'; + break; + case 2: + $auto_flip = 'v'; + $this->log .= '- EXIF orientation = 2 : vertical flip
'; + break; + case 3: + $auto_rotate = 180; + $this->log .= '- EXIF orientation = 3 : 180 rotate left
'; + break; + case 4: + $auto_flip = 'h'; + $this->log .= '- EXIF orientation = 4 : horizontal flip
'; + break; + case 5: + $auto_flip = 'h'; + $auto_rotate = 90; + $this->log .= '- EXIF orientation = 5 : horizontal flip + 90 rotate right
'; + break; + case 6: + $auto_rotate = 90; + $this->log .= '- EXIF orientation = 6 : 90 rotate right
'; + break; + case 7: + $auto_flip = 'v'; + $auto_rotate = 90; + $this->log .= '- EXIF orientation = 7 : vertical flip + 90 rotate right
'; + break; + case 8: + $auto_rotate = 270; + $this->log .= '- EXIF orientation = 8 : 90 rotate left
'; + break; + default: + $this->log .= '- EXIF orientation = '.$orientation.' : unknown
'; + break; + } + } else { + $this->log .= '- EXIF data is invalid or missing
'; + } + } else { + if (!$this->image_auto_rotate) { + $this->log .= '- auto-rotate deactivated
'; + } else if (!$this->image_src_type == 'jpg') { + $this->log .= '- auto-rotate applies only to JPEG images
'; + } else if (!$this->function_enabled('exif_read_data')) { + $this->log .= '- auto-rotate requires function exif_read_data to be enabled
'; + } + } + + // do we do some image manipulation? + $image_manipulation = ($this->file_is_image && ( + $this->image_resize + || $this->image_convert != '' + || is_numeric($this->image_brightness) + || is_numeric($this->image_contrast) + || is_numeric($this->image_opacity) + || is_numeric($this->image_threshold) + || !empty($this->image_tint_color) + || !empty($this->image_overlay_color) + || $this->image_pixelate + || $this->image_unsharp + || !empty($this->image_text) + || $this->image_greyscale + || $this->image_negative + || !empty($this->image_watermark) + || $auto_rotate || $auto_flip + || is_numeric($this->image_rotate) + || is_numeric($this->jpeg_size) + || !empty($this->image_flip) + || !empty($this->image_crop) + || !empty($this->image_precrop) + || !empty($this->image_border) + || !empty($this->image_border_transparent) + || $this->image_frame > 0 + || $this->image_bevel > 0 + || $this->image_reflection_height)); + + // we do a quick check to ensure the file is really an image + // we can do this only now, as it would have failed before in case of open_basedir + if ($image_manipulation && !@getimagesize($this->file_src_pathname)) { + $this->log .= '- the file is not an image!
'; + $image_manipulation = false; + } + + if ($image_manipulation) { + + // make sure GD doesn't complain too much + @ini_set("gd.jpeg_ignore_warning", 1); + + // checks if the source file is readable + if ($this->processed && !($f = @fopen($this->file_src_pathname, 'r'))) { + $this->processed = false; + $this->error = $this->translate('source_not_readable'); + } else { + @fclose($f); + } + + // we now do all the image manipulations + $this->log .= '- image resizing or conversion wanted
'; + if ($this->gdversion()) { + switch($this->image_src_type) { + case 'jpg': + if (!$this->function_enabled('imagecreatefromjpeg')) { + $this->processed = false; + $this->error = $this->translate('no_create_support', array('JPEG')); + } else { + $image_src = @imagecreatefromjpeg($this->file_src_pathname); + if (!$image_src) { + $this->processed = false; + $this->error = $this->translate('create_error', array('JPEG')); + } else { + $this->log .= '- source image is JPEG
'; + } + } + break; + case 'png': + if (!$this->function_enabled('imagecreatefrompng')) { + $this->processed = false; + $this->error = $this->translate('no_create_support', array('PNG')); + } else { + $image_src = @imagecreatefrompng($this->file_src_pathname); + if (!$image_src) { + $this->processed = false; + $this->error = $this->translate('create_error', array('PNG')); + } else { + $this->log .= '- source image is PNG
'; + } + } + break; + case 'gif': + if (!$this->function_enabled('imagecreatefromgif')) { + $this->processed = false; + $this->error = $this->translate('no_create_support', array('GIF')); + } else { + $image_src = @imagecreatefromgif($this->file_src_pathname); + if (!$image_src) { + $this->processed = false; + $this->error = $this->translate('create_error', array('GIF')); + } else { + $this->log .= '- source image is GIF
'; + } + } + break; + case 'bmp': + if (!method_exists($this, 'imagecreatefrombmp')) { + $this->processed = false; + $this->error = $this->translate('no_create_support', array('BMP')); + } else { + $image_src = @$this->imagecreatefrombmp($this->file_src_pathname); + if (!$image_src) { + $this->processed = false; + $this->error = $this->translate('create_error', array('BMP')); + } else { + $this->log .= '- source image is BMP
'; + } + } + break; + default: + $this->processed = false; + $this->error = $this->translate('source_invalid'); + } + } else { + $this->processed = false; + $this->error = $this->translate('gd_missing'); + } + + if ($this->processed && $image_src) { + + // we have to set image_convert if it is not already + if (empty($this->image_convert)) { + $this->log .= '- setting destination file type to ' . $this->image_src_type . '
'; + $this->image_convert = $this->image_src_type; + } + + if (!in_array($this->image_convert, $this->image_supported)) { + $this->image_convert = 'jpg'; + } + + // we set the default color to be the background color if we don't output in a transparent format + if ($this->image_convert != 'png' && $this->image_convert != 'gif' && !empty($this->image_default_color) && empty($this->image_background_color)) $this->image_background_color = $this->image_default_color; + if (!empty($this->image_background_color)) $this->image_default_color = $this->image_background_color; + if (empty($this->image_default_color)) $this->image_default_color = '#FFFFFF'; + + $this->image_src_x = imagesx($image_src); + $this->image_src_y = imagesy($image_src); + $gd_version = $this->gdversion(); + $ratio_crop = null; + + if (!imageistruecolor($image_src)) { // $this->image_src_type == 'gif' + $this->log .= '- image is detected as having a palette
'; + $this->image_is_palette = true; + $this->image_transparent_color = imagecolortransparent($image_src); + if ($this->image_transparent_color >= 0 && imagecolorstotal($image_src) > $this->image_transparent_color) { + $this->image_is_transparent = true; + $this->log .= '    palette image is detected as transparent
'; + } + // if the image has a palette (GIF), we convert it to true color, preserving transparency + $this->log .= '    convert palette image to true color
'; + $true_color = imagecreatetruecolor($this->image_src_x, $this->image_src_y); + imagealphablending($true_color, false); + imagesavealpha($true_color, true); + for ($x = 0; $x < $this->image_src_x; $x++) { + for ($y = 0; $y < $this->image_src_y; $y++) { + if ($this->image_transparent_color >= 0 && imagecolorat($image_src, $x, $y) == $this->image_transparent_color) { + imagesetpixel($true_color, $x, $y, 127 << 24); + } else { + $rgb = imagecolorsforindex($image_src, imagecolorat($image_src, $x, $y)); + imagesetpixel($true_color, $x, $y, ($rgb['alpha'] << 24) | ($rgb['red'] << 16) | ($rgb['green'] << 8) | $rgb['blue']); + } + } + } + $image_src = $this->imagetransfer($true_color, $image_src); + imagealphablending($image_src, false); + imagesavealpha($image_src, true); + $this->image_is_palette = false; + } + + $image_dst = & $image_src; + + // auto-flip image, according to EXIF data (JPEG only) + if ($gd_version >= 2 && !empty($auto_flip)) { + $this->log .= '- auto-flip image : ' . ($auto_flip == 'v' ? 'vertical' : 'horizontal') . '
'; + $tmp = $this->imagecreatenew($this->image_src_x, $this->image_src_y); + for ($x = 0; $x < $this->image_src_x; $x++) { + for ($y = 0; $y < $this->image_src_y; $y++){ + if (strpos($auto_flip, 'v') !== false) { + imagecopy($tmp, $image_dst, $this->image_src_x - $x - 1, $y, $x, $y, 1, 1); + } else { + imagecopy($tmp, $image_dst, $x, $this->image_src_y - $y - 1, $x, $y, 1, 1); + } + } + } + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + // auto-rotate image, according to EXIF data (JPEG only) + if ($gd_version >= 2 && is_numeric($auto_rotate)) { + if (!in_array($auto_rotate, array(0, 90, 180, 270))) $auto_rotate = 0; + if ($auto_rotate != 0) { + if ($auto_rotate == 90 || $auto_rotate == 270) { + $tmp = $this->imagecreatenew($this->image_src_y, $this->image_src_x); + } else { + $tmp = $this->imagecreatenew($this->image_src_x, $this->image_src_y); + } + $this->log .= '- auto-rotate image : ' . $auto_rotate . '
'; + for ($x = 0; $x < $this->image_src_x; $x++) { + for ($y = 0; $y < $this->image_src_y; $y++){ + if ($auto_rotate == 90) { + imagecopy($tmp, $image_dst, $y, $x, $x, $this->image_src_y - $y - 1, 1, 1); + } else if ($auto_rotate == 180) { + imagecopy($tmp, $image_dst, $x, $y, $this->image_src_x - $x - 1, $this->image_src_y - $y - 1, 1, 1); + } else if ($auto_rotate == 270) { + imagecopy($tmp, $image_dst, $y, $x, $this->image_src_x - $x - 1, $y, 1, 1); + } else { + imagecopy($tmp, $image_dst, $x, $y, $x, $y, 1, 1); + } + } + } + if ($auto_rotate == 90 || $auto_rotate == 270) { + $t = $this->image_src_y; + $this->image_src_y = $this->image_src_x; + $this->image_src_x = $t; + } + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + } + + // pre-crop image, before resizing + if ((!empty($this->image_precrop))) { + list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_precrop, $this->image_src_x, $this->image_src_y, true, true); + $this->log .= '- pre-crop image : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . '
'; + $this->image_src_x = $this->image_src_x - $cl - $cr; + $this->image_src_y = $this->image_src_y - $ct - $cb; + if ($this->image_src_x < 1) $this->image_src_x = 1; + if ($this->image_src_y < 1) $this->image_src_y = 1; + $tmp = $this->imagecreatenew($this->image_src_x, $this->image_src_y); + + // we copy the image into the recieving image + imagecopy($tmp, $image_dst, 0, 0, $cl, $ct, $this->image_src_x, $this->image_src_y); + + // if we crop with negative margins, we have to make sure the extra bits are the right color, or transparent + if ($ct < 0 || $cr < 0 || $cb < 0 || $cl < 0 ) { + // use the background color if present + if (!empty($this->image_background_color)) { + list($red, $green, $blue) = $this->getcolors($this->image_background_color); + $fill = imagecolorallocate($tmp, $red, $green, $blue); + } else { + $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127); + } + // fills eventual negative margins + if ($ct < 0) imagefilledrectangle($tmp, 0, 0, $this->image_src_x, -$ct, $fill); + if ($cr < 0) imagefilledrectangle($tmp, $this->image_src_x + $cr, 0, $this->image_src_x, $this->image_src_y, $fill); + if ($cb < 0) imagefilledrectangle($tmp, 0, $this->image_src_y + $cb, $this->image_src_x, $this->image_src_y, $fill); + if ($cl < 0) imagefilledrectangle($tmp, 0, 0, -$cl, $this->image_src_y, $fill); + } + + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + // resize image (and move image_src_x, image_src_y dimensions into image_dst_x, image_dst_y) + if ($this->image_resize) { + $this->log .= '- resizing...
'; + $this->image_dst_x = $this->image_x; + $this->image_dst_y = $this->image_y; + + // backward compatibility for soon to be deprecated settings + if ($this->image_ratio_no_zoom_in) { + $this->image_ratio = true; + $this->image_no_enlarging = true; + } else if ($this->image_ratio_no_zoom_out) { + $this->image_ratio = true; + $this->image_no_shrinking = true; + } + + // keeps aspect ratio with x calculated from y + if ($this->image_ratio_x) { + $this->log .= '    calculate x size
'; + $this->image_dst_x = round(($this->image_src_x * $this->image_y) / $this->image_src_y); + $this->image_dst_y = $this->image_y; + + // keeps aspect ratio with y calculated from x + } else if ($this->image_ratio_y) { + $this->log .= '    calculate y size
'; + $this->image_dst_x = $this->image_x; + $this->image_dst_y = round(($this->image_src_y * $this->image_x) / $this->image_src_x); + + // keeps aspect ratio, calculating x and y so that the image is approx the set number of pixels + } else if (is_numeric($this->image_ratio_pixels)) { + $this->log .= '    calculate x/y size to match a number of pixels
'; + $pixels = $this->image_src_y * $this->image_src_x; + $diff = sqrt($this->image_ratio_pixels / $pixels); + $this->image_dst_x = round($this->image_src_x * $diff); + $this->image_dst_y = round($this->image_src_y * $diff); + + // keeps aspect ratio with x and y dimensions, filling the space + } else if ($this->image_ratio_crop) { + if (!is_string($this->image_ratio_crop)) $this->image_ratio_crop = ''; + $this->image_ratio_crop = strtolower($this->image_ratio_crop); + if (($this->image_src_x/$this->image_x) > ($this->image_src_y/$this->image_y)) { + $this->image_dst_y = $this->image_y; + $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y)); + $ratio_crop = array(); + $ratio_crop['x'] = $this->image_dst_x - $this->image_x; + if (strpos($this->image_ratio_crop, 'l') !== false) { + $ratio_crop['l'] = 0; + $ratio_crop['r'] = $ratio_crop['x']; + } else if (strpos($this->image_ratio_crop, 'r') !== false) { + $ratio_crop['l'] = $ratio_crop['x']; + $ratio_crop['r'] = 0; + } else { + $ratio_crop['l'] = round($ratio_crop['x']/2); + $ratio_crop['r'] = $ratio_crop['x'] - $ratio_crop['l']; + } + $this->log .= '    ratio_crop_x : ' . $ratio_crop['x'] . ' (' . $ratio_crop['l'] . ';' . $ratio_crop['r'] . ')
'; + if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0); + } else { + $this->image_dst_x = $this->image_x; + $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x)); + $ratio_crop = array(); + $ratio_crop['y'] = $this->image_dst_y - $this->image_y; + if (strpos($this->image_ratio_crop, 't') !== false) { + $ratio_crop['t'] = 0; + $ratio_crop['b'] = $ratio_crop['y']; + } else if (strpos($this->image_ratio_crop, 'b') !== false) { + $ratio_crop['t'] = $ratio_crop['y']; + $ratio_crop['b'] = 0; + } else { + $ratio_crop['t'] = round($ratio_crop['y']/2); + $ratio_crop['b'] = $ratio_crop['y'] - $ratio_crop['t']; + } + $this->log .= '    ratio_crop_y : ' . $ratio_crop['y'] . ' (' . $ratio_crop['t'] . ';' . $ratio_crop['b'] . ')
'; + if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0); + } + + // keeps aspect ratio with x and y dimensions, fitting the image in the space, and coloring the rest + } else if ($this->image_ratio_fill) { + if (!is_string($this->image_ratio_fill)) $this->image_ratio_fill = ''; + $this->image_ratio_fill = strtolower($this->image_ratio_fill); + if (($this->image_src_x/$this->image_x) < ($this->image_src_y/$this->image_y)) { + $this->image_dst_y = $this->image_y; + $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y)); + $ratio_crop = array(); + $ratio_crop['x'] = $this->image_dst_x - $this->image_x; + if (strpos($this->image_ratio_fill, 'l') !== false) { + $ratio_crop['l'] = 0; + $ratio_crop['r'] = $ratio_crop['x']; + } else if (strpos($this->image_ratio_fill, 'r') !== false) { + $ratio_crop['l'] = $ratio_crop['x']; + $ratio_crop['r'] = 0; + } else { + $ratio_crop['l'] = round($ratio_crop['x']/2); + $ratio_crop['r'] = $ratio_crop['x'] - $ratio_crop['l']; + } + $this->log .= '    ratio_fill_x : ' . $ratio_crop['x'] . ' (' . $ratio_crop['l'] . ';' . $ratio_crop['r'] . ')
'; + if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0); + } else { + $this->image_dst_x = $this->image_x; + $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x)); + $ratio_crop = array(); + $ratio_crop['y'] = $this->image_dst_y - $this->image_y; + if (strpos($this->image_ratio_fill, 't') !== false) { + $ratio_crop['t'] = 0; + $ratio_crop['b'] = $ratio_crop['y']; + } else if (strpos($this->image_ratio_fill, 'b') !== false) { + $ratio_crop['t'] = $ratio_crop['y']; + $ratio_crop['b'] = 0; + } else { + $ratio_crop['t'] = round($ratio_crop['y']/2); + $ratio_crop['b'] = $ratio_crop['y'] - $ratio_crop['t']; + } + $this->log .= '    ratio_fill_y : ' . $ratio_crop['y'] . ' (' . $ratio_crop['t'] . ';' . $ratio_crop['b'] . ')
'; + if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0); + } + + // keeps aspect ratio with x and y dimensions + } else if ($this->image_ratio) { + if (($this->image_src_x/$this->image_x) > ($this->image_src_y/$this->image_y)) { + $this->image_dst_x = $this->image_x; + $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x)); + } else { + $this->image_dst_y = $this->image_y; + $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y)); + } + + // resize to provided exact dimensions + } else { + $this->log .= '    use plain sizes
'; + $this->image_dst_x = $this->image_x; + $this->image_dst_y = $this->image_y; + } + + if ($this->image_dst_x < 1) $this->image_dst_x = 1; + if ($this->image_dst_y < 1) $this->image_dst_y = 1; + $this->log .= '    image_src_x y : ' . $this->image_src_x . ' x ' . $this->image_src_y . '
'; + $this->log .= '    image_dst_x y : ' . $this->image_dst_x . ' x ' . $this->image_dst_y . '
'; + + // make sure we don't enlarge the image if we don't want to + if ($this->image_no_enlarging && ($this->image_src_x < $this->image_dst_x || $this->image_src_y < $this->image_dst_y)) { + $this->log .= '    cancel resizing, as it would enlarge the image!
'; + $this->image_dst_x = $this->image_src_x; + $this->image_dst_y = $this->image_src_y; + } + + // make sure we don't shrink the image if we don't want to + if ($this->image_no_shrinking && ($this->image_src_x > $this->image_dst_x || $this->image_src_y > $this->image_dst_y)) { + $this->log .= '    cancel resizing, as it would shrink the image!
'; + $this->image_dst_x = $this->image_src_x; + $this->image_dst_y = $this->image_src_y; + } + + // resize the image + if ($this->image_dst_x != $this->image_src_x && $this->image_dst_y != $this->image_src_y) { + $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y); + + if ($gd_version >= 2) { + $res = imagecopyresampled($tmp, $image_src, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_src_x, $this->image_src_y); + } else { + $res = imagecopyresized($tmp, $image_src, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_src_x, $this->image_src_y); + } + + $this->log .= '    resized image object created
'; + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + } else { + $this->image_dst_x = $this->image_src_x; + $this->image_dst_y = $this->image_src_y; + } + + // crop image (and also crops if image_ratio_crop is used) + if ((!empty($this->image_crop) || !is_null($ratio_crop))) { + list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_crop, $this->image_dst_x, $this->image_dst_y, true, true); + // we adjust the cropping if we use image_ratio_crop + if (!is_null($ratio_crop)) { + if (array_key_exists('t', $ratio_crop)) $ct += $ratio_crop['t']; + if (array_key_exists('r', $ratio_crop)) $cr += $ratio_crop['r']; + if (array_key_exists('b', $ratio_crop)) $cb += $ratio_crop['b']; + if (array_key_exists('l', $ratio_crop)) $cl += $ratio_crop['l']; + } + $this->log .= '- crop image : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . '
'; + $this->image_dst_x = $this->image_dst_x - $cl - $cr; + $this->image_dst_y = $this->image_dst_y - $ct - $cb; + if ($this->image_dst_x < 1) $this->image_dst_x = 1; + if ($this->image_dst_y < 1) $this->image_dst_y = 1; + $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y); + + // we copy the image into the recieving image + imagecopy($tmp, $image_dst, 0, 0, $cl, $ct, $this->image_dst_x, $this->image_dst_y); + + // if we crop with negative margins, we have to make sure the extra bits are the right color, or transparent + if ($ct < 0 || $cr < 0 || $cb < 0 || $cl < 0 ) { + // use the background color if present + if (!empty($this->image_background_color)) { + list($red, $green, $blue) = $this->getcolors($this->image_background_color); + $fill = imagecolorallocate($tmp, $red, $green, $blue); + } else { + $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127); + } + // fills eventual negative margins + if ($ct < 0) imagefilledrectangle($tmp, 0, 0, $this->image_dst_x, -$ct-1, $fill); + if ($cr < 0) imagefilledrectangle($tmp, $this->image_dst_x + $cr, 0, $this->image_dst_x, $this->image_dst_y, $fill); + if ($cb < 0) imagefilledrectangle($tmp, 0, $this->image_dst_y + $cb, $this->image_dst_x, $this->image_dst_y, $fill); + if ($cl < 0) imagefilledrectangle($tmp, 0, 0, -$cl-1, $this->image_dst_y, $fill); + } + + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + // flip image + if ($gd_version >= 2 && !empty($this->image_flip)) { + $this->image_flip = strtolower($this->image_flip); + $this->log .= '- flip image : ' . $this->image_flip . '
'; + $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y); + for ($x = 0; $x < $this->image_dst_x; $x++) { + for ($y = 0; $y < $this->image_dst_y; $y++){ + if (strpos($this->image_flip, 'v') !== false) { + imagecopy($tmp, $image_dst, $this->image_dst_x - $x - 1, $y, $x, $y, 1, 1); + } else { + imagecopy($tmp, $image_dst, $x, $this->image_dst_y - $y - 1, $x, $y, 1, 1); + } + } + } + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + // rotate image + if ($gd_version >= 2 && is_numeric($this->image_rotate)) { + if (!in_array($this->image_rotate, array(0, 90, 180, 270))) $this->image_rotate = 0; + if ($this->image_rotate != 0) { + if ($this->image_rotate == 90 || $this->image_rotate == 270) { + $tmp = $this->imagecreatenew($this->image_dst_y, $this->image_dst_x); + } else { + $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y); + } + $this->log .= '- rotate image : ' . $this->image_rotate . '
'; + for ($x = 0; $x < $this->image_dst_x; $x++) { + for ($y = 0; $y < $this->image_dst_y; $y++){ + if ($this->image_rotate == 90) { + imagecopy($tmp, $image_dst, $y, $x, $x, $this->image_dst_y - $y - 1, 1, 1); + } else if ($this->image_rotate == 180) { + imagecopy($tmp, $image_dst, $x, $y, $this->image_dst_x - $x - 1, $this->image_dst_y - $y - 1, 1, 1); + } else if ($this->image_rotate == 270) { + imagecopy($tmp, $image_dst, $y, $x, $this->image_dst_x - $x - 1, $y, 1, 1); + } else { + imagecopy($tmp, $image_dst, $x, $y, $x, $y, 1, 1); + } + } + } + if ($this->image_rotate == 90 || $this->image_rotate == 270) { + $t = $this->image_dst_y; + $this->image_dst_y = $this->image_dst_x; + $this->image_dst_x = $t; + } + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + } + + // pixelate image + if ((is_numeric($this->image_pixelate) && $this->image_pixelate > 0)) { + $this->log .= '- pixelate image (' . $this->image_pixelate . 'px)
'; + $filter = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y); + if ($gd_version >= 2) { + imagecopyresampled($filter, $image_dst, 0, 0, 0, 0, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate), $this->image_dst_x, $this->image_dst_y); + imagecopyresampled($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate)); + } else { + imagecopyresized($filter, $image_dst, 0, 0, 0, 0, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate), $this->image_dst_x, $this->image_dst_y); + imagecopyresized($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate)); + } + imagedestroy($filter); + } + + // unsharp mask + if ($gd_version >= 2 && $this->image_unsharp && is_numeric($this->image_unsharp_amount) && is_numeric($this->image_unsharp_radius) && is_numeric($this->image_unsharp_threshold)) { + // Unsharp Mask for PHP - version 2.1.1 + // Unsharp mask algorithm by Torstein Hønsi 2003-07. + // Used with permission + // Modified to support alpha transparency + if ($this->image_unsharp_amount > 500) $this->image_unsharp_amount = 500; + $this->image_unsharp_amount = $this->image_unsharp_amount * 0.016; + if ($this->image_unsharp_radius > 50) $this->image_unsharp_radius = 50; + $this->image_unsharp_radius = $this->image_unsharp_radius * 2; + if ($this->image_unsharp_threshold > 255) $this->image_unsharp_threshold = 255; + $this->image_unsharp_radius = abs(round($this->image_unsharp_radius)); + if ($this->image_unsharp_radius != 0) { + $this->image_dst_x = imagesx($image_dst); $this->image_dst_y = imagesy($image_dst); + $canvas = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, false, true); + $blur = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, false, true); + if ($this->function_enabled('imageconvolution')) { // PHP >= 5.1 + $matrix = array(array( 1, 2, 1 ), array( 2, 4, 2 ), array( 1, 2, 1 )); + imagecopy($blur, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y); + imageconvolution($blur, $matrix, 16, 0); + } else { + for ($i = 0; $i < $this->image_unsharp_radius; $i++) { + imagecopy($blur, $image_dst, 0, 0, 1, 0, $this->image_dst_x - 1, $this->image_dst_y); // left + $this->imagecopymergealpha($blur, $image_dst, 1, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, 50); // right + $this->imagecopymergealpha($blur, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, 50); // center + imagecopy($canvas, $blur, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y); + $this->imagecopymergealpha($blur, $canvas, 0, 0, 0, 1, $this->image_dst_x, $this->image_dst_y - 1, 33.33333 ); // up + $this->imagecopymergealpha($blur, $canvas, 0, 1, 0, 0, $this->image_dst_x, $this->image_dst_y, 25); // down + } + } + $p_new = array(); + if($this->image_unsharp_threshold>0) { + for ($x = 0; $x < $this->image_dst_x-1; $x++) { + for ($y = 0; $y < $this->image_dst_y; $y++) { + $p_orig = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $p_blur = imagecolorsforindex($blur, imagecolorat($blur, $x, $y)); + $p_new['red'] = (abs($p_orig['red'] - $p_blur['red']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['red'] - $p_blur['red'])) + $p_orig['red'])) : $p_orig['red']; + $p_new['green'] = (abs($p_orig['green'] - $p_blur['green']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['green'] - $p_blur['green'])) + $p_orig['green'])) : $p_orig['green']; + $p_new['blue'] = (abs($p_orig['blue'] - $p_blur['blue']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['blue'] - $p_blur['blue'])) + $p_orig['blue'])) : $p_orig['blue']; + if (($p_orig['red'] != $p_new['red']) || ($p_orig['green'] != $p_new['green']) || ($p_orig['blue'] != $p_new['blue'])) { + $color = imagecolorallocatealpha($image_dst, $p_new['red'], $p_new['green'], $p_new['blue'], $p_orig['alpha']); + imagesetpixel($image_dst, $x, $y, $color); + } + } + } + } else { + for ($x = 0; $x < $this->image_dst_x; $x++) { + for ($y = 0; $y < $this->image_dst_y; $y++) { + $p_orig = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $p_blur = imagecolorsforindex($blur, imagecolorat($blur, $x, $y)); + $p_new['red'] = ($this->image_unsharp_amount * ($p_orig['red'] - $p_blur['red'])) + $p_orig['red']; + if ($p_new['red']>255) { $p_new['red']=255; } elseif ($p_new['red']<0) { $p_new['red']=0; } + $p_new['green'] = ($this->image_unsharp_amount * ($p_orig['green'] - $p_blur['green'])) + $p_orig['green']; + if ($p_new['green']>255) { $p_new['green']=255; } elseif ($p_new['green']<0) { $p_new['green']=0; } + $p_new['blue'] = ($this->image_unsharp_amount * ($p_orig['blue'] - $p_blur['blue'])) + $p_orig['blue']; + if ($p_new['blue']>255) { $p_new['blue']=255; } elseif ($p_new['blue']<0) { $p_new['blue']=0; } + $color = imagecolorallocatealpha($image_dst, $p_new['red'], $p_new['green'], $p_new['blue'], $p_orig['alpha']); + imagesetpixel($image_dst, $x, $y, $color); + } + } + } + imagedestroy($canvas); + imagedestroy($blur); + } + } + + // add color overlay + if ($gd_version >= 2 && (is_numeric($this->image_overlay_opacity) && $this->image_overlay_opacity > 0 && !empty($this->image_overlay_color))) { + $this->log .= '- apply color overlay
'; + list($red, $green, $blue) = $this->getcolors($this->image_overlay_color); + $filter = imagecreatetruecolor($this->image_dst_x, $this->image_dst_y); + $color = imagecolorallocate($filter, $red, $green, $blue); + imagefilledrectangle($filter, 0, 0, $this->image_dst_x, $this->image_dst_y, $color); + $this->imagecopymergealpha($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_overlay_opacity); + imagedestroy($filter); + } + + // add brightness, contrast and tint, turns to greyscale and inverts colors + if ($gd_version >= 2 && ($this->image_negative || $this->image_greyscale || is_numeric($this->image_threshold)|| is_numeric($this->image_brightness) || is_numeric($this->image_contrast) || !empty($this->image_tint_color))) { + $this->log .= '- apply tint, light, contrast correction, negative, greyscale and threshold
'; + if (!empty($this->image_tint_color)) list($tint_red, $tint_green, $tint_blue) = $this->getcolors($this->image_tint_color); + //imagealphablending($image_dst, true); + for($y=0; $y < $this->image_dst_y; $y++) { + for($x=0; $x < $this->image_dst_x; $x++) { + if ($this->image_greyscale) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $r = $g = $b = round((0.2125 * $pixel['red']) + (0.7154 * $pixel['green']) + (0.0721 * $pixel['blue'])); + $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']); + imagesetpixel($image_dst, $x, $y, $color); + unset($color); unset($pixel); + } + if (is_numeric($this->image_threshold)) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $c = (round($pixel['red'] + $pixel['green'] + $pixel['blue']) / 3) - 127; + $r = $g = $b = ($c > $this->image_threshold ? 255 : 0); + $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']); + imagesetpixel($image_dst, $x, $y, $color); + unset($color); unset($pixel); + } + if (is_numeric($this->image_brightness)) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $r = max(min(round($pixel['red'] + (($this->image_brightness * 2))), 255), 0); + $g = max(min(round($pixel['green'] + (($this->image_brightness * 2))), 255), 0); + $b = max(min(round($pixel['blue'] + (($this->image_brightness * 2))), 255), 0); + $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']); + imagesetpixel($image_dst, $x, $y, $color); + unset($color); unset($pixel); + } + if (is_numeric($this->image_contrast)) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $r = max(min(round(($this->image_contrast + 128) * $pixel['red'] / 128), 255), 0); + $g = max(min(round(($this->image_contrast + 128) * $pixel['green'] / 128), 255), 0); + $b = max(min(round(($this->image_contrast + 128) * $pixel['blue'] / 128), 255), 0); + $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']); + imagesetpixel($image_dst, $x, $y, $color); + unset($color); unset($pixel); + } + if (!empty($this->image_tint_color)) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $r = min(round($tint_red * $pixel['red'] / 169), 255); + $g = min(round($tint_green * $pixel['green'] / 169), 255); + $b = min(round($tint_blue * $pixel['blue'] / 169), 255); + $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']); + imagesetpixel($image_dst, $x, $y, $color); + unset($color); unset($pixel); + } + if (!empty($this->image_negative)) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $r = round(255 - $pixel['red']); + $g = round(255 - $pixel['green']); + $b = round(255 - $pixel['blue']); + $color = imagecolorallocatealpha($image_dst, $r, $g, $b, $pixel['alpha']); + imagesetpixel($image_dst, $x, $y, $color); + unset($color); unset($pixel); + } + } + } + } + + // adds a border + if ($gd_version >= 2 && !empty($this->image_border)) { + list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_border, $this->image_dst_x, $this->image_dst_y, true, false); + $this->log .= '- add border : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . '
'; + $this->image_dst_x = $this->image_dst_x + $cl + $cr; + $this->image_dst_y = $this->image_dst_y + $ct + $cb; + if (!empty($this->image_border_color)) list($red, $green, $blue) = $this->getcolors($this->image_border_color); + $opacity = (is_numeric($this->image_border_opacity) ? (int) (127 - $this->image_border_opacity / 100 * 127): 0); + // we now create an image, that we fill with the border color + $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y); + $background = imagecolorallocatealpha($tmp, $red, $green, $blue, $opacity); + imagefilledrectangle($tmp, 0, 0, $this->image_dst_x, $this->image_dst_y, $background); + // we then copy the source image into the new image, without merging so that only the border is actually kept + imagecopy($tmp, $image_dst, $cl, $ct, 0, 0, $this->image_dst_x - $cr - $cl, $this->image_dst_y - $cb - $ct); + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + // adds a fading-to-transparent border + if ($gd_version >= 2 && !empty($this->image_border_transparent)) { + list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_border_transparent, $this->image_dst_x, $this->image_dst_y, true, false); + $this->log .= '- add transparent border : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . '
'; + // we now create an image, that we fill with the border color + $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y); + // we then copy the source image into the new image, without the borders + imagecopy($tmp, $image_dst, $cl, $ct, $cl, $ct, $this->image_dst_x - $cr - $cl, $this->image_dst_y - $cb - $ct); + // we now add the top border + $opacity = 100; + for ($y = $ct - 1; $y >= 0; $y--) { + $il = (int) ($ct > 0 ? ($cl * ($y / $ct)) : 0); + $ir = (int) ($ct > 0 ? ($cr * ($y / $ct)) : 0); + for ($x = $il; $x < $this->image_dst_x - $ir; $x++) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100; + if ($alpha > 0) { + if ($alpha > 1) $alpha = 1; + $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127)); + imagesetpixel($tmp, $x, $y, $color); + } + } + if ($opacity > 0) $opacity = $opacity - (100 / $ct); + } + // we now add the right border + $opacity = 100; + for ($x = $this->image_dst_x - $cr; $x < $this->image_dst_x; $x++) { + $it = (int) ($cr > 0 ? ($ct * (($this->image_dst_x - $x - 1) / $cr)) : 0); + $ib = (int) ($cr > 0 ? ($cb * (($this->image_dst_x - $x - 1) / $cr)) : 0); + for ($y = $it; $y < $this->image_dst_y - $ib; $y++) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100; + if ($alpha > 0) { + if ($alpha > 1) $alpha = 1; + $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127)); + imagesetpixel($tmp, $x, $y, $color); + } + } + if ($opacity > 0) $opacity = $opacity - (100 / $cr); + } + // we now add the bottom border + $opacity = 100; + for ($y = $this->image_dst_y - $cb; $y < $this->image_dst_y; $y++) { + $il = (int) ($cb > 0 ? ($cl * (($this->image_dst_y - $y - 1) / $cb)) : 0); + $ir = (int) ($cb > 0 ? ($cr * (($this->image_dst_y - $y - 1) / $cb)) : 0); + for ($x = $il; $x < $this->image_dst_x - $ir; $x++) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100; + if ($alpha > 0) { + if ($alpha > 1) $alpha = 1; + $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127)); + imagesetpixel($tmp, $x, $y, $color); + } + } + if ($opacity > 0) $opacity = $opacity - (100 / $cb); + } + // we now add the left border + $opacity = 100; + for ($x = $cl - 1; $x >= 0; $x--) { + $it = (int) ($cl > 0 ? ($ct * ($x / $cl)) : 0); + $ib = (int) ($cl > 0 ? ($cb * ($x / $cl)) : 0); + for ($y = $it; $y < $this->image_dst_y - $ib; $y++) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100; + if ($alpha > 0) { + if ($alpha > 1) $alpha = 1; + $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127)); + imagesetpixel($tmp, $x, $y, $color); + } + } + if ($opacity > 0) $opacity = $opacity - (100 / $cl); + } + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + // add frame border + if ($gd_version >= 2 && is_numeric($this->image_frame)) { + if (is_array($this->image_frame_colors)) { + $vars = $this->image_frame_colors; + $this->log .= '- add frame : ' . implode(' ', $this->image_frame_colors) . '
'; + } else { + $this->log .= '- add frame : ' . $this->image_frame_colors . '
'; + $vars = explode(' ', $this->image_frame_colors); + } + $nb = sizeof($vars); + $this->image_dst_x = $this->image_dst_x + ($nb * 2); + $this->image_dst_y = $this->image_dst_y + ($nb * 2); + $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y); + imagecopy($tmp, $image_dst, $nb, $nb, 0, 0, $this->image_dst_x - ($nb * 2), $this->image_dst_y - ($nb * 2)); + $opacity = (is_numeric($this->image_frame_opacity) ? (int) (127 - $this->image_frame_opacity / 100 * 127): 0); + for ($i=0; $i<$nb; $i++) { + list($red, $green, $blue) = $this->getcolors($vars[$i]); + $c = imagecolorallocatealpha($tmp, $red, $green, $blue, $opacity); + if ($this->image_frame == 1) { + imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c); + imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $this->image_dst_x - $i -1, $i, $c); + imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $i, $this->image_dst_y - $i -1, $c); + imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c); + } else { + imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c); + imageline($tmp, $this->image_dst_x - $nb + $i, $this->image_dst_y - $nb + $i, $this->image_dst_x - $nb + $i, $nb - $i, $c); + imageline($tmp, $this->image_dst_x - $nb + $i, $this->image_dst_y - $nb + $i, $nb - $i, $this->image_dst_y - $nb + $i, $c); + imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c); + } + } + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + // add bevel border + if ($gd_version >= 2 && $this->image_bevel > 0) { + if (empty($this->image_bevel_color1)) $this->image_bevel_color1 = '#FFFFFF'; + if (empty($this->image_bevel_color2)) $this->image_bevel_color2 = '#000000'; + list($red1, $green1, $blue1) = $this->getcolors($this->image_bevel_color1); + list($red2, $green2, $blue2) = $this->getcolors($this->image_bevel_color2); + $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y); + imagecopy($tmp, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y); + imagealphablending($tmp, true); + for ($i=0; $i<$this->image_bevel; $i++) { + $alpha = round(($i / $this->image_bevel) * 127); + $c1 = imagecolorallocatealpha($tmp, $red1, $green1, $blue1, $alpha); + $c2 = imagecolorallocatealpha($tmp, $red2, $green2, $blue2, $alpha); + imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c1); + imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i, $this->image_dst_x - $i -1, $i, $c2); + imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $i, $this->image_dst_y - $i -1, $c2); + imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c1); + } + // we transfert tmp into image_dst + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + // add watermark image + if ($this->image_watermark!='' && file_exists($this->image_watermark)) { + $this->log .= '- add watermark
'; + $this->image_watermark_position = strtolower($this->image_watermark_position); + $watermark_info = getimagesize($this->image_watermark); + $watermark_type = (array_key_exists(2, $watermark_info) ? $watermark_info[2] : null); // 1 = GIF, 2 = JPG, 3 = PNG + $watermark_checked = false; + if ($watermark_type == IMAGETYPE_GIF) { + if (!$this->function_enabled('imagecreatefromgif')) { + $this->error = $this->translate('watermark_no_create_support', array('GIF')); + } else { + $filter = @imagecreatefromgif($this->image_watermark); + if (!$filter) { + $this->error = $this->translate('watermark_create_error', array('GIF')); + } else { + $this->log .= '    watermark source image is GIF
'; + $watermark_checked = true; + } + } + } else if ($watermark_type == IMAGETYPE_JPEG) { + if (!$this->function_enabled('imagecreatefromjpeg')) { + $this->error = $this->translate('watermark_no_create_support', array('JPEG')); + } else { + $filter = @imagecreatefromjpeg($this->image_watermark); + if (!$filter) { + $this->error = $this->translate('watermark_create_error', array('JPEG')); + } else { + $this->log .= '    watermark source image is JPEG
'; + $watermark_checked = true; + } + } + } else if ($watermark_type == IMAGETYPE_PNG) { + if (!$this->function_enabled('imagecreatefrompng')) { + $this->error = $this->translate('watermark_no_create_support', array('PNG')); + } else { + $filter = @imagecreatefrompng($this->image_watermark); + if (!$filter) { + $this->error = $this->translate('watermark_create_error', array('PNG')); + } else { + $this->log .= '    watermark source image is PNG
'; + $watermark_checked = true; + } + } + } else if ($watermark_type == IMAGETYPE_BMP) { + if (!method_exists($this, 'imagecreatefrombmp')) { + $this->error = $this->translate('watermark_no_create_support', array('BMP')); + } else { + $filter = @$this->imagecreatefrombmp($this->image_watermark); + if (!$filter) { + $this->error = $this->translate('watermark_create_error', array('BMP')); + } else { + $this->log .= '    watermark source image is BMP
'; + $watermark_checked = true; + } + } + } else { + $this->error = $this->translate('watermark_invalid'); + } + if ($watermark_checked) { + $watermark_dst_width = $watermark_src_width = imagesx($filter); + $watermark_dst_height = $watermark_src_height = imagesy($filter); + + // if watermark is too large/tall, resize it first + if ((!$this->image_watermark_no_zoom_out && ($watermark_dst_width > $this->image_dst_x || $watermark_dst_height > $this->image_dst_y)) + || (!$this->image_watermark_no_zoom_in && $watermark_dst_width < $this->image_dst_x && $watermark_dst_height < $this->image_dst_y)) { + $canvas_width = $this->image_dst_x - abs($this->image_watermark_x); + $canvas_height = $this->image_dst_y - abs($this->image_watermark_y); + if (($watermark_src_width/$canvas_width) > ($watermark_src_height/$canvas_height)) { + $watermark_dst_width = $canvas_width; + $watermark_dst_height = intval($watermark_src_height*($canvas_width / $watermark_src_width)); + } else { + $watermark_dst_height = $canvas_height; + $watermark_dst_width = intval($watermark_src_width*($canvas_height / $watermark_src_height)); + } + $this->log .= '    watermark resized from '.$watermark_src_width.'x'.$watermark_src_height.' to '.$watermark_dst_width.'x'.$watermark_dst_height.'
'; + + } + // determine watermark position + $watermark_x = 0; + $watermark_y = 0; + if (is_numeric($this->image_watermark_x)) { + if ($this->image_watermark_x < 0) { + $watermark_x = $this->image_dst_x - $watermark_dst_width + $this->image_watermark_x; + } else { + $watermark_x = $this->image_watermark_x; + } + } else { + if (strpos($this->image_watermark_position, 'r') !== false) { + $watermark_x = $this->image_dst_x - $watermark_dst_width; + } else if (strpos($this->image_watermark_position, 'l') !== false) { + $watermark_x = 0; + } else { + $watermark_x = ($this->image_dst_x - $watermark_dst_width) / 2; + } + } + if (is_numeric($this->image_watermark_y)) { + if ($this->image_watermark_y < 0) { + $watermark_y = $this->image_dst_y - $watermark_dst_height + $this->image_watermark_y; + } else { + $watermark_y = $this->image_watermark_y; + } + } else { + if (strpos($this->image_watermark_position, 'b') !== false) { + $watermark_y = $this->image_dst_y - $watermark_dst_height; + } else if (strpos($this->image_watermark_position, 't') !== false) { + $watermark_y = 0; + } else { + $watermark_y = ($this->image_dst_y - $watermark_dst_height) / 2; + } + } + imagealphablending($image_dst, true); + imagecopyresampled($image_dst, $filter, $watermark_x, $watermark_y, 0, 0, $watermark_dst_width, $watermark_dst_height, $watermark_src_width, $watermark_src_height); + } else { + $this->error = $this->translate('watermark_invalid'); + } + } + + // add text + if (!empty($this->image_text)) { + $this->log .= '- add text
'; + + // calculate sizes in human readable format + $src_size = $this->file_src_size / 1024; + $src_size_mb = number_format($src_size / 1024, 1, ".", " "); + $src_size_kb = number_format($src_size, 1, ".", " "); + $src_size_human = ($src_size > 1024 ? $src_size_mb . " MB" : $src_size_kb . " kb"); + + $this->image_text = str_replace( + array('[src_name]', + '[src_name_body]', + '[src_name_ext]', + '[src_pathname]', + '[src_mime]', + '[src_size]', + '[src_size_kb]', + '[src_size_mb]', + '[src_size_human]', + '[src_x]', + '[src_y]', + '[src_pixels]', + '[src_type]', + '[src_bits]', + '[dst_path]', + '[dst_name_body]', + '[dst_name_ext]', + '[dst_name]', + '[dst_pathname]', + '[dst_x]', + '[dst_y]', + '[date]', + '[time]', + '[host]', + '[server]', + '[ip]', + '[gd_version]'), + array($this->file_src_name, + $this->file_src_name_body, + $this->file_src_name_ext, + $this->file_src_pathname, + $this->file_src_mime, + $this->file_src_size, + $src_size_kb, + $src_size_mb, + $src_size_human, + $this->image_src_x, + $this->image_src_y, + $this->image_src_pixels, + $this->image_src_type, + $this->image_src_bits, + $this->file_dst_path, + $this->file_dst_name_body, + $this->file_dst_name_ext, + $this->file_dst_name, + $this->file_dst_pathname, + $this->image_dst_x, + $this->image_dst_y, + date('Y-m-d'), + date('H:i:s'), + (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'n/a'), + (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'n/a'), + (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'n/a'), + $this->gdversion(true)), + $this->image_text); + + if (!is_numeric($this->image_text_padding)) $this->image_text_padding = 0; + if (!is_numeric($this->image_text_line_spacing)) $this->image_text_line_spacing = 0; + if (!is_numeric($this->image_text_padding_x)) $this->image_text_padding_x = $this->image_text_padding; + if (!is_numeric($this->image_text_padding_y)) $this->image_text_padding_y = $this->image_text_padding; + $this->image_text_position = strtolower($this->image_text_position); + $this->image_text_direction = strtolower($this->image_text_direction); + $this->image_text_alignment = strtolower($this->image_text_alignment); + + $font_type = 'gd'; + + // if the font is a string with a GDF font path, we assume that we might want to load a font + if (!is_numeric($this->image_text_font) && strlen($this->image_text_font) > 4 && substr(strtolower($this->image_text_font), -4) == '.gdf') { + if (strpos($this->image_text_font, '/') === false) $this->image_text_font = "./" . $this->image_text_font; + $this->log .= '    try to load font ' . $this->image_text_font . '... '; + if ($this->image_text_font = @imageloadfont($this->image_text_font)) { + $this->log .= 'success
'; + } else { + $this->log .= 'error
'; + $this->image_text_font = 5; + } + } + + // if the font is a string with a TTF font path, we check if we can access the font file + if (!is_numeric($this->image_text_font) && strlen($this->image_text_font) > 4 && substr(strtolower($this->image_text_font), -4) == '.ttf') { + $this->log .= '    try to load font ' . $this->image_text_font . '... '; + if (strpos($this->image_text_font, '/') === false) $this->image_text_font = "./" . $this->image_text_font; + if (file_exists($this->image_text_font) && is_readable($this->image_text_font)) { + $this->log .= 'success
'; + $font_type = 'tt'; + } else { + $this->log .= 'error
'; + $this->image_text_font = 5; + } + } + + // get the text bounding box (GD fonts) + if ($font_type == 'gd') { + $text = explode("\n", $this->image_text); + $char_width = imagefontwidth($this->image_text_font); + $char_height = imagefontheight($this->image_text_font); + $text_height = 0; + $text_width = 0; + $line_height = 0; + $line_width = 0; + foreach ($text as $k => $v) { + if ($this->image_text_direction == 'v') { + $h = ($char_width * strlen($v)); + if ($h > $text_height) $text_height = $h; + $line_width = $char_height; + $text_width += $line_width + ($k < (sizeof($text)-1) ? $this->image_text_line_spacing : 0); + } else { + $w = ($char_width * strlen($v)); + if ($w > $text_width) $text_width = $w; + $line_height = $char_height; + $text_height += $line_height + ($k < (sizeof($text)-1) ? $this->image_text_line_spacing : 0); + } + } + $text_width += (2 * $this->image_text_padding_x); + $text_height += (2 * $this->image_text_padding_y); + + // get the text bounding box (TrueType fonts) + } else if ($font_type == 'tt') { + $text = $this->image_text; + if (!$this->image_text_angle) $this->image_text_angle = $this->image_text_direction == 'v' ? 90 : 0; + $text_height = 0; + $text_width = 0; + $text_offset_x = 0; + $text_offset_y = 0; + $rect = imagettfbbox($this->image_text_size, $this->image_text_angle, $this->image_text_font, $text ); + if ($rect) { + $minX = min(array($rect[0],$rect[2],$rect[4],$rect[6])); + $maxX = max(array($rect[0],$rect[2],$rect[4],$rect[6])); + $minY = min(array($rect[1],$rect[3],$rect[5],$rect[7])); + $maxY = max(array($rect[1],$rect[3],$rect[5],$rect[7])); + $text_offset_x = abs($minX) - 1; + $text_offset_y = abs($minY) - 1; + $text_width = $maxX - $minX + (2 * $this->image_text_padding_x); + $text_height = $maxY - $minY + (2 * $this->image_text_padding_y); + } + } + + // position the text block + $text_x = 0; + $text_y = 0; + if (is_numeric($this->image_text_x)) { + if ($this->image_text_x < 0) { + $text_x = $this->image_dst_x - $text_width + $this->image_text_x; + } else { + $text_x = $this->image_text_x; + } + } else { + if (strpos($this->image_text_position, 'r') !== false) { + $text_x = $this->image_dst_x - $text_width; + } else if (strpos($this->image_text_position, 'l') !== false) { + $text_x = 0; + } else { + $text_x = ($this->image_dst_x - $text_width) / 2; + } + } + if (is_numeric($this->image_text_y)) { + if ($this->image_text_y < 0) { + $text_y = $this->image_dst_y - $text_height + $this->image_text_y; + } else { + $text_y = $this->image_text_y; + } + } else { + if (strpos($this->image_text_position, 'b') !== false) { + $text_y = $this->image_dst_y - $text_height; + } else if (strpos($this->image_text_position, 't') !== false) { + $text_y = 0; + } else { + $text_y = ($this->image_dst_y - $text_height) / 2; + } + } + + // add a background, maybe transparent + if (!empty($this->image_text_background)) { + list($red, $green, $blue) = $this->getcolors($this->image_text_background); + if ($gd_version >= 2 && (is_numeric($this->image_text_background_opacity)) && $this->image_text_background_opacity >= 0 && $this->image_text_background_opacity <= 100) { + $filter = imagecreatetruecolor($text_width, $text_height); + $background_color = imagecolorallocate($filter, $red, $green, $blue); + imagefilledrectangle($filter, 0, 0, $text_width, $text_height, $background_color); + $this->imagecopymergealpha($image_dst, $filter, $text_x, $text_y, 0, 0, $text_width, $text_height, $this->image_text_background_opacity); + imagedestroy($filter); + } else { + $background_color = imagecolorallocate($image_dst ,$red, $green, $blue); + imagefilledrectangle($image_dst, $text_x, $text_y, $text_x + $text_width, $text_y + $text_height, $background_color); + } + } + + $text_x += $this->image_text_padding_x; + $text_y += $this->image_text_padding_y; + $t_width = $text_width - (2 * $this->image_text_padding_x); + $t_height = $text_height - (2 * $this->image_text_padding_y); + list($red, $green, $blue) = $this->getcolors($this->image_text_color); + + // add the text, maybe transparent + if ($gd_version >= 2 && (is_numeric($this->image_text_opacity)) && $this->image_text_opacity >= 0 && $this->image_text_opacity <= 100) { + if ($t_width < 0) $t_width = 0; + if ($t_height < 0) $t_height = 0; + $filter = $this->imagecreatenew($t_width, $t_height, false, true); + $text_color = imagecolorallocate($filter ,$red, $green, $blue); + + if ($font_type == 'gd') { + foreach ($text as $k => $v) { + if ($this->image_text_direction == 'v') { + imagestringup($filter, + $this->image_text_font, + $k * ($line_width + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)), + $text_height - (2 * $this->image_text_padding_y) - ($this->image_text_alignment == 'l' ? 0 : (($t_height - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))) , + $v, + $text_color); + } else { + imagestring($filter, + $this->image_text_font, + ($this->image_text_alignment == 'l' ? 0 : (($t_width - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))), + $k * ($line_height + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)), + $v, + $text_color); + } + } + } else if ($font_type == 'tt') { + imagettftext($filter, + $this->image_text_size, + $this->image_text_angle, + $text_offset_x, + $text_offset_y, + $text_color, + $this->image_text_font, + $text); + } + $this->imagecopymergealpha($image_dst, $filter, $text_x, $text_y, 0, 0, $t_width, $t_height, $this->image_text_opacity); + imagedestroy($filter); + + } else { + $text_color = imagecolorallocate($image_dst ,$red, $green, $blue); + if ($font_type == 'gd') { + foreach ($text as $k => $v) { + if ($this->image_text_direction == 'v') { + imagestringup($image_dst, + $this->image_text_font, + $text_x + $k * ($line_width + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)), + $text_y + $text_height - (2 * $this->image_text_padding_y) - ($this->image_text_alignment == 'l' ? 0 : (($t_height - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))), + $v, + $text_color); + } else { + imagestring($image_dst, + $this->image_text_font, + $text_x + ($this->image_text_alignment == 'l' ? 0 : (($t_width - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))), + $text_y + $k * ($line_height + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)), + $v, + $text_color); + } + } + } else if ($font_type == 'tt') { + imagettftext($image_dst, + $this->image_text_size, + $this->image_text_angle, + $text_offset_x + ($this->image_dst_x / 2) - ($text_width / 2) + $this->image_text_padding_x, + $text_offset_y + ($this->image_dst_y / 2) - ($text_height / 2) + $this->image_text_padding_y, + $text_color, + $this->image_text_font, + $text); + } + } + } + + // add a reflection + if ($this->image_reflection_height) { + $this->log .= '- add reflection : ' . $this->image_reflection_height . '
'; + // we decode image_reflection_height, which can be a integer, a string in pixels or percentage + $image_reflection_height = $this->image_reflection_height; + if (strpos($image_reflection_height, '%')>0) $image_reflection_height = $this->image_dst_y * (str_replace('%','',$image_reflection_height / 100)); + if (strpos($image_reflection_height, 'px')>0) $image_reflection_height = str_replace('px','',$image_reflection_height); + $image_reflection_height = (int) $image_reflection_height; + if ($image_reflection_height > $this->image_dst_y) $image_reflection_height = $this->image_dst_y; + if (empty($this->image_reflection_opacity)) $this->image_reflection_opacity = 60; + // create the new destination image + $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y + $image_reflection_height + $this->image_reflection_space, true); + $transparency = $this->image_reflection_opacity; + + // copy the original image + imagecopy($tmp, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y + ($this->image_reflection_space < 0 ? $this->image_reflection_space : 0)); + + // we have to make sure the extra bit is the right color, or transparent + if ($image_reflection_height + $this->image_reflection_space > 0) { + // use the background color if present + if (!empty($this->image_background_color)) { + list($red, $green, $blue) = $this->getcolors($this->image_background_color); + $fill = imagecolorallocate($tmp, $red, $green, $blue); + } else { + $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127); + } + // fill in from the edge of the extra bit + imagefill($tmp, round($this->image_dst_x / 2), $this->image_dst_y + $image_reflection_height + $this->image_reflection_space - 1, $fill); + } + + // copy the reflection + for ($y = 0; $y < $image_reflection_height; $y++) { + for ($x = 0; $x < $this->image_dst_x; $x++) { + $pixel_b = imagecolorsforindex($tmp, imagecolorat($tmp, $x, $y + $this->image_dst_y + $this->image_reflection_space)); + $pixel_o = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $this->image_dst_y - $y - 1 + ($this->image_reflection_space < 0 ? $this->image_reflection_space : 0))); + $alpha_o = 1 - ($pixel_o['alpha'] / 127); + $alpha_b = 1 - ($pixel_b['alpha'] / 127); + $opacity = $alpha_o * $transparency / 100; + if ($opacity > 0) { + $red = round((($pixel_o['red'] * $opacity) + ($pixel_b['red'] ) * $alpha_b) / ($alpha_b + $opacity)); + $green = round((($pixel_o['green'] * $opacity) + ($pixel_b['green']) * $alpha_b) / ($alpha_b + $opacity)); + $blue = round((($pixel_o['blue'] * $opacity) + ($pixel_b['blue'] ) * $alpha_b) / ($alpha_b + $opacity)); + $alpha = ($opacity + $alpha_b); + if ($alpha > 1) $alpha = 1; + $alpha = round((1 - $alpha) * 127); + $color = imagecolorallocatealpha($tmp, $red, $green, $blue, $alpha); + imagesetpixel($tmp, $x, $y + $this->image_dst_y + $this->image_reflection_space, $color); + } + } + if ($transparency > 0) $transparency = $transparency - ($this->image_reflection_opacity / $image_reflection_height); + } + + // copy the resulting image into the destination image + $this->image_dst_y = $this->image_dst_y + $image_reflection_height + $this->image_reflection_space; + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + // change opacity + if ($gd_version >= 2 && is_numeric($this->image_opacity) && $this->image_opacity < 100) { + $this->log .= '- change opacity
'; + // create the new destination image + $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, true); + for($y=0; $y < $this->image_dst_y; $y++) { + for($x=0; $x < $this->image_dst_x; $x++) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $alpha = $pixel['alpha'] + round((127 - $pixel['alpha']) * (100 - $this->image_opacity) / 100); + if ($alpha > 127) $alpha = 127; + if ($alpha > 0) { + $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], $alpha); + imagesetpixel($tmp, $x, $y, $color); + } + } + } + // copy the resulting image into the destination image + $image_dst = $this->imagetransfer($tmp, $image_dst); + } + + // reduce the JPEG image to a set desired size + if (is_numeric($this->jpeg_size) && $this->jpeg_size > 0 && ($this->image_convert == 'jpeg' || $this->image_convert == 'jpg')) { + // inspired by: JPEGReducer class version 1, 25 November 2004, Author: Huda M ElMatsani, justhuda at netscape dot net + $this->log .= '- JPEG desired file size : ' . $this->jpeg_size . '
'; + // calculate size of each image. 75%, 50%, and 25% quality + ob_start(); imagejpeg($image_dst,null,75); $buffer = ob_get_contents(); ob_end_clean(); + $size75 = strlen($buffer); + ob_start(); imagejpeg($image_dst,null,50); $buffer = ob_get_contents(); ob_end_clean(); + $size50 = strlen($buffer); + ob_start(); imagejpeg($image_dst,null,25); $buffer = ob_get_contents(); ob_end_clean(); + $size25 = strlen($buffer); + + // make sure we won't divide by 0 + if ($size50 == $size25) $size50++; + if ($size75 == $size50 || $size75 == $size25) $size75++; + + // calculate gradient of size reduction by quality + $mgrad1 = 25 / ($size50-$size25); + $mgrad2 = 25 / ($size75-$size50); + $mgrad3 = 50 / ($size75-$size25); + $mgrad = ($mgrad1 + $mgrad2 + $mgrad3) / 3; + // result of approx. quality factor for expected size + $q_factor = round($mgrad * ($this->jpeg_size - $size50) + 50); + + if ($q_factor<1) { + $this->jpeg_quality=1; + } elseif ($q_factor>100) { + $this->jpeg_quality=100; + } else { + $this->jpeg_quality=$q_factor; + } + $this->log .= '    JPEG quality factor set to ' . $this->jpeg_quality . '
'; + } + + // converts image from true color, and fix transparency if needed + $this->log .= '- converting...
'; + $this->image_dst_type = $this->image_convert; + switch($this->image_convert) { + case 'gif': + // if the image is true color, we convert it to a palette + if (imageistruecolor($image_dst)) { + $this->log .= '    true color to palette
'; + // creates a black and white mask + $mask = array(array()); + for ($x = 0; $x < $this->image_dst_x; $x++) { + for ($y = 0; $y < $this->image_dst_y; $y++) { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $mask[$x][$y] = $pixel['alpha']; + } + } + list($red, $green, $blue) = $this->getcolors($this->image_default_color); + // first, we merge the image with the background color, so we know which colors we will have + for ($x = 0; $x < $this->image_dst_x; $x++) { + for ($y = 0; $y < $this->image_dst_y; $y++) { + if ($mask[$x][$y] > 0){ + // we have some transparency. we combine the color with the default color + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + $alpha = ($mask[$x][$y] / 127); + $pixel['red'] = round(($pixel['red'] * (1 -$alpha) + $red * ($alpha))); + $pixel['green'] = round(($pixel['green'] * (1 -$alpha) + $green * ($alpha))); + $pixel['blue'] = round(($pixel['blue'] * (1 -$alpha) + $blue * ($alpha))); + $color = imagecolorallocate($image_dst, $pixel['red'], $pixel['green'], $pixel['blue']); + imagesetpixel($image_dst, $x, $y, $color); + } + } + } + // transforms the true color image into palette, with its merged default color + if (empty($this->image_background_color)) { + imagetruecolortopalette($image_dst, true, 255); + $transparency = imagecolorallocate($image_dst, 254, 1, 253); + imagecolortransparent($image_dst, $transparency); + // make the transparent areas transparent + for ($x = 0; $x < $this->image_dst_x; $x++) { + for ($y = 0; $y < $this->image_dst_y; $y++) { + // we test wether we have enough opacity to justify keeping the color + if ($mask[$x][$y] > 120) imagesetpixel($image_dst, $x, $y, $transparency); + } + } + } + unset($mask); + } + break; + case 'jpg': + case 'bmp': + // if the image doesn't support any transparency, then we merge it with the default color + $this->log .= '    fills in transparency with default color
'; + list($red, $green, $blue) = $this->getcolors($this->image_default_color); + $transparency = imagecolorallocate($image_dst, $red, $green, $blue); + // make the transaparent areas transparent + for ($x = 0; $x < $this->image_dst_x; $x++) { + for ($y = 0; $y < $this->image_dst_y; $y++) { + // we test wether we have some transparency, in which case we will merge the colors + if (imageistruecolor($image_dst)) { + $rgba = imagecolorat($image_dst, $x, $y); + $pixel = array('red' => ($rgba >> 16) & 0xFF, + 'green' => ($rgba >> 8) & 0xFF, + 'blue' => $rgba & 0xFF, + 'alpha' => ($rgba & 0x7F000000) >> 24); + } else { + $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y)); + } + if ($pixel['alpha'] == 127) { + // we have full transparency. we make the pixel transparent + imagesetpixel($image_dst, $x, $y, $transparency); + } else if ($pixel['alpha'] > 0) { + // we have some transparency. we combine the color with the default color + $alpha = ($pixel['alpha'] / 127); + $pixel['red'] = round(($pixel['red'] * (1 -$alpha) + $red * ($alpha))); + $pixel['green'] = round(($pixel['green'] * (1 -$alpha) + $green * ($alpha))); + $pixel['blue'] = round(($pixel['blue'] * (1 -$alpha) + $blue * ($alpha))); + $color = imagecolorclosest($image_dst, $pixel['red'], $pixel['green'], $pixel['blue']); + imagesetpixel($image_dst, $x, $y, $color); + } + } + } + + break; + default: + break; + } + + // interlace options + if($this->image_interlace) imageinterlace($image_dst, true); + + // outputs image + $this->log .= '- saving image...
'; + switch($this->image_convert) { + case 'jpeg': + case 'jpg': + if (!$return_mode) { + $result = @imagejpeg($image_dst, $this->file_dst_pathname, $this->jpeg_quality); + } else { + ob_start(); + $result = @imagejpeg($image_dst, null, $this->jpeg_quality); + $return_content = ob_get_contents(); + ob_end_clean(); + } + if (!$result) { + $this->processed = false; + $this->error = $this->translate('file_create', array('JPEG')); + } else { + $this->log .= '    JPEG image created
'; + } + break; + case 'png': + imagealphablending( $image_dst, false ); + imagesavealpha( $image_dst, true ); + if (!$return_mode) { + if (is_numeric($this->png_compression) && version_compare(PHP_VERSION, '5.1.2') >= 0) { + $result = @imagepng($image_dst, $this->file_dst_pathname, $this->png_compression); + } else { + $result = @imagepng($image_dst, $this->file_dst_pathname); + } + } else { + ob_start(); + if (is_numeric($this->png_compression) && version_compare(PHP_VERSION, '5.1.2') >= 0) { + $result = @imagepng($image_dst, null, $this->png_compression); + } else { + $result = @imagepng($image_dst); + } + $return_content = ob_get_contents(); + ob_end_clean(); + } + if (!$result) { + $this->processed = false; + $this->error = $this->translate('file_create', array('PNG')); + } else { + $this->log .= '    PNG image created
'; + } + break; + case 'gif': + if (!$return_mode) { + $result = @imagegif($image_dst, $this->file_dst_pathname); + } else { + ob_start(); + $result = @imagegif($image_dst); + $return_content = ob_get_contents(); + ob_end_clean(); + } + if (!$result) { + $this->processed = false; + $this->error = $this->translate('file_create', array('GIF')); + } else { + $this->log .= '    GIF image created
'; + } + break; + case 'bmp': + if (!$return_mode) { + $result = $this->imagebmp($image_dst, $this->file_dst_pathname); + } else { + ob_start(); + $result = $this->imagebmp($image_dst); + $return_content = ob_get_contents(); + ob_end_clean(); + } + if (!$result) { + $this->processed = false; + $this->error = $this->translate('file_create', array('BMP')); + } else { + $this->log .= '    BMP image created
'; + } + break; + + default: + $this->processed = false; + $this->error = $this->translate('no_conversion_type'); + } + if ($this->processed) { + if (is_resource($image_src)) imagedestroy($image_src); + if (is_resource($image_dst)) imagedestroy($image_dst); + $this->log .= '    image objects destroyed
'; + } + } + + } else { + $this->log .= '- no image processing wanted
'; + + if (!$return_mode) { + // copy the file to its final destination. we don't use move_uploaded_file here + // if we happen to have open_basedir restrictions, it is a temp file that we copy, not the original uploaded file + if (!copy($this->file_src_pathname, $this->file_dst_pathname)) { + $this->processed = false; + $this->error = $this->translate('copy_failed'); + } + } else { + // returns the file, so that its content can be received by the caller + $return_content = @file_get_contents($this->file_src_pathname); + if ($return_content === FALSE) { + $this->processed = false; + $this->error = $this->translate('reading_failed'); + } + } + } + } + + if ($this->processed) { + $this->log .= '- process OK
'; + } else { + $this->log .= '- error: ' . $this->error . '
'; + } + + // we reinit all the vars + $this->init(); + + // we may return the image content + if ($return_mode) return $return_content; + + } + + /** + * Deletes the uploaded file from its temporary location + * + * When PHP uploads a file, it stores it in a temporary location. + * When you {@link process} the file, you actually copy the resulting file to the given location, it doesn't alter the original file. + * Once you have processed the file as many times as you wanted, you can delete the uploaded file. + * If there is open_basedir restrictions, the uploaded file is in fact a temporary file + * + * You might want not to use this function if you work on local files, as it will delete the source file + * + * @access public + */ + function clean() { + $this->log .= 'cleanup
'; + $this->log .= '- delete temp file ' . $this->file_src_pathname . '
'; + @unlink($this->file_src_pathname); + } + + + /** + * Opens a BMP image + * + * This function has been written by DHKold, and is used with permission of the author + * + * @access public + */ + function imagecreatefrombmp($filename) { + if (! $f1 = fopen($filename,"rb")) return false; + + $file = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14)); + if ($file['file_type'] != 19778) return false; + + $bmp = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'. + '/Vcompression/Vsize_bitmap/Vhoriz_resolution'. + '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40)); + $bmp['colors'] = pow(2,$bmp['bits_per_pixel']); + if ($bmp['size_bitmap'] == 0) $bmp['size_bitmap'] = $file['file_size'] - $file['bitmap_offset']; + $bmp['bytes_per_pixel'] = $bmp['bits_per_pixel']/8; + $bmp['bytes_per_pixel2'] = ceil($bmp['bytes_per_pixel']); + $bmp['decal'] = ($bmp['width']*$bmp['bytes_per_pixel']/4); + $bmp['decal'] -= floor($bmp['width']*$bmp['bytes_per_pixel']/4); + $bmp['decal'] = 4-(4*$bmp['decal']); + if ($bmp['decal'] == 4) $bmp['decal'] = 0; + + $palette = array(); + if ($bmp['colors'] < 16777216) { + $palette = unpack('V'.$bmp['colors'], fread($f1,$bmp['colors']*4)); + } + + $im = fread($f1,$bmp['size_bitmap']); + $vide = chr(0); + + $res = imagecreatetruecolor($bmp['width'],$bmp['height']); + $P = 0; + $Y = $bmp['height']-1; + while ($Y >= 0) { + $X=0; + while ($X < $bmp['width']) { + if ($bmp['bits_per_pixel'] == 24) + $color = unpack("V",substr($im,$P,3).$vide); + elseif ($bmp['bits_per_pixel'] == 16) { + $color = unpack("n",substr($im,$P,2)); + $color[1] = $palette[$color[1]+1]; + } elseif ($bmp['bits_per_pixel'] == 8) { + $color = unpack("n",$vide.substr($im,$P,1)); + $color[1] = $palette[$color[1]+1]; + } elseif ($bmp['bits_per_pixel'] == 4) { + $color = unpack("n",$vide.substr($im,floor($P),1)); + if (($P*2)%2 == 0) $color[1] = ($color[1] >> 4) ; else $color[1] = ($color[1] & 0x0F); + $color[1] = $palette[$color[1]+1]; + } elseif ($bmp['bits_per_pixel'] == 1) { + $color = unpack("n",$vide.substr($im,floor($P),1)); + if (($P*8)%8 == 0) $color[1] = $color[1] >>7; + elseif (($P*8)%8 == 1) $color[1] = ($color[1] & 0x40)>>6; + elseif (($P*8)%8 == 2) $color[1] = ($color[1] & 0x20)>>5; + elseif (($P*8)%8 == 3) $color[1] = ($color[1] & 0x10)>>4; + elseif (($P*8)%8 == 4) $color[1] = ($color[1] & 0x8)>>3; + elseif (($P*8)%8 == 5) $color[1] = ($color[1] & 0x4)>>2; + elseif (($P*8)%8 == 6) $color[1] = ($color[1] & 0x2)>>1; + elseif (($P*8)%8 == 7) $color[1] = ($color[1] & 0x1); + $color[1] = $palette[$color[1]+1]; + } else + return FALSE; + imagesetpixel($res,$X,$Y,$color[1]); + $X++; + $P += $bmp['bytes_per_pixel']; + } + $Y--; + $P+=$bmp['decal']; + } + fclose($f1); + return $res; + } + + /** + * Saves a BMP image + * + * This function has been published on the PHP website, and can be used freely + * + * @access public + */ + function imagebmp(&$im, $filename = "") { + + if (!$im) return false; + $w = imagesx($im); + $h = imagesy($im); + $result = ''; + + // if the image is not true color, we convert it first + if (!imageistruecolor($im)) { + $tmp = imagecreatetruecolor($w, $h); + imagecopy($tmp, $im, 0, 0, 0, 0, $w, $h); + imagedestroy($im); + $im = & $tmp; + } + + $biBPLine = $w * 3; + $biStride = ($biBPLine + 3) & ~3; + $biSizeImage = $biStride * $h; + $bfOffBits = 54; + $bfSize = $bfOffBits + $biSizeImage; + + $result .= substr('BM', 0, 2); + $result .= pack ('VvvV', $bfSize, 0, 0, $bfOffBits); + $result .= pack ('VVVvvVVVVVV', 40, $w, $h, 1, 24, 0, $biSizeImage, 0, 0, 0, 0); + + $numpad = $biStride - $biBPLine; + for ($y = $h - 1; $y >= 0; --$y) { + for ($x = 0; $x < $w; ++$x) { + $col = imagecolorat ($im, $x, $y); + $result .= substr(pack ('V', $col), 0, 3); + } + for ($i = 0; $i < $numpad; ++$i) + $result .= pack ('C', 0); + } + + if($filename==""){ + echo $result; + } else { + $file = fopen($filename, "wb"); + fwrite($file, $result); + fclose($file); + } + return true; + } +} + +?> diff --git a/deployed/jsn/administrator/components/com_jsn/config.xml b/deployed/jsn/administrator/components/com_jsn/config.xml new file mode 100644 index 00000000..e1adb475 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/config.xml @@ -0,0 +1,692 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
+
diff --git a/deployed/jsn/administrator/components/com_jsn/controller.php b/deployed/jsn/administrator/components/com_jsn/controller.php new file mode 100644 index 00000000..bed272ad --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/controller.php @@ -0,0 +1,152 @@ +input->get('view', 'fields'); + $layout = $this->input->get('layout', 'default'); + $id = $this->input->getInt('id'); + + // Check for edit form. + if ($view == 'field' && $layout == 'edit' && !$this->checkEditId('com_jsn.edit.field', $id)) + { + // Somehow the person just went to the form - we don't allow that. + $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id)); + $this->setMessage($this->getError(), 'error'); + $this->setRedirect(JRoute::_('index.php?option=com_jsn&view=fields', false)); + + return false; + } + if($view == 'opField'){ + foreach (glob(JPATH_ADMINISTRATOR . '/components/com_jsn/helpers/fields/*.php') as $filename) { + require_once $filename; + } + //$user=JsnHelper::getUser(); + if(/*!$user->guest && */JFactory::getApplication()->input->get('type','')!=''){ + $class='Jsn'.ucfirst(JFactory::getApplication()->input->get('type','')).'FieldHelper'; + if(class_exists($class)) + { + $class::operations(); + } + } + } + else + parent::display(); + + return $this; + + } + + public function install() + { + $db=JFactory::getDbo(); + $query=$db->getQuery(true); + $query->update('#__extensions')->set($db->quoteName('enabled').'=1') + ->where($db->quoteName('element').' IN ('. + $db->quote('jsn_author').','. + $db->quote('jsn_auth').','. + $db->quote('jsn_system').','. + $db->quote('jsn_content').','. + $db->quote('jsn_users').','. + $db->quote('usergroups').','. + $db->quote('socialconnect').')'); + $db->setQuery($query); + + $result = $db->query(); + $this->setMessage(JText::_('COM_JSN_INSTALL')); + $this->syncuserRun(); + $this->setRedirect(JRoute::_('index.php?option=com_jsn&view=fields', false)); + } + + public function update() + { + $db=JFactory::getDbo(); + $query=$db->getQuery(true); + $query->update('#__extensions')->set($db->quoteName('enabled').'=1') + ->where($db->quoteName('element').' IN ('. + $db->quote('jsn_auth').','. + $db->quote('jsn_system').','. + $db->quote('jsn_content').','. + $db->quote('jsn_users').','. + $db->quote('usergroups').','. + $db->quote('socialconnect').')'); + $db->setQuery($query); + + $result = $db->query(); + $this->setMessage(JText::_('COM_JSN_UPDATE')); + $this->syncuserRun(); + $this->setRedirect(JRoute::_('index.php?option=com_jsn&view=fields', false)); + } + + public function syncuser() + { + $this->syncuserRun(); + $this->setMessage(JText::_('COM_JSN_SYNCUSER')); + $this->setRedirect(JRoute::_('index.php?option=com_jsn&view=fields', false)); + } + + public function syncuserRun() + { + $config = JComponentHelper::getParams('com_jsn'); + $namestyle=$config->get('namestyle','FIRSTNAME_LASTNAME'); + + $db=JFactory::getDbo(); + $query=$db->getQuery(true); + $query->select('a.id,a.name,b.id as bid')->from('#__users as a')->join('left','#__jsn_users as b ON a.id=b.id'); + + $db->setQuery($query); + $users=$db->loadObjectList(); + + + foreach($users as $user){ + if($user->bid==null || $user->bid==''){ + $query=$db->getQuery(true); + $fields=array(); + $values=array(); + switch($namestyle){ + case 'FIRSTNAME': + $fields[]=$db->quoteName('firstname'); + $values[]=$db->quote($user->name); + break; + default: + $fields[]=$db->quoteName('firstname'); + $fields[]=$db->quoteName('lastname'); + $name=explode(' ',$user->name,2); + $values[]=$db->quote((isset($name[0]) ? $name[0] : '')); + $values[]=$db->quote((isset($name[1]) ? $name[1] : '')); + break; + } + $query="INSERT INTO #__jsn_users(id,".implode(', ',$fields).") VALUES(".$user->id.", ".implode(', ',$values).")"; + $db->setQuery($query); + $db->execute(); + } + + } + + + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/controllers/field.php b/deployed/jsn/administrator/components/com_jsn/controllers/field.php new file mode 100644 index 00000000..d346349c --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/controllers/field.php @@ -0,0 +1,82 @@ +setRedirect('index.php?option=com_jsn&view=field&layout=editgroup'); + } + public function editgroup() + { + parent::edit(); + $id=$this->input->get('id'); + $this->setRedirect('index.php?option=com_jsn&view=field&layout=editgroup&id='.$id); + } + /** + * Method to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 3.1 + */ + protected function allowAdd($data = array()) + { + $user = JFactory::getUser(); + return ($user->authorise('core.create', 'com_jsn')); + } + + /** + * Method to check if you can edit a record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 3.1 + */ + protected function allowEdit($data = array(), $key = 'id') + { + $user = JFactory::getUser(); + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + // Since there is no asset tracking and no categories, revert to the component permissions. + return parent::allowEdit($data, $key); + + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 3.1 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Field'); + + // Preset the redirect + $this->setRedirect('index.php?option=com_jsn&view=fields'); + + return parent::batch($model); + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/controllers/fields.php b/deployed/jsn/administrator/components/com_jsn/controllers/fields.php new file mode 100644 index 00000000..fcf7f2ad --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/controllers/fields.php @@ -0,0 +1,290 @@ +registerTask('unpublish', 'publish'); + $this->registerTask('required_unpublish', 'required_publish'); + $this->registerTask('profile_unpublish', 'profile_publish'); + $this->registerTask('register_unpublish', 'register_publish'); + $this->registerTask('search_unpublish', 'search_publish'); + $this->registerTask('edit_unpublish', 'edit_publish'); + } + + public function required_publish() + { + // Check for request forgeries. + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + $ids = $this->input->get('cid', array(), 'array'); + $values = array('required_publish' => 1, 'required_unpublish' => 0); + $task = $this->getTask(); + $value = JArrayHelper::getValue($values, $task, 0, 'int'); + + if (empty($ids)) + { + JFactory::getApplication()->enqueueMessage(JText::_('COM_JSN_NO_FIELDS_SELECTED')); + } + else + { + // Get the model. + $model = $this->getModel(); + + // Change the state of the records. + if (!$model->toggle($ids, $value, 'required')) + { + JFactory::getApplication()->enqueueMessage($model->getError()); + } else { + if ($value == 1) + { + $ntext = 'COM_JSN_N_FIELDS_REQUIRED'; + } else { + $ntext = 'COM_JSN_N_FIELDS_UNREQUIRED'; + } + $this->setMessage(JText::plural($ntext, count($ids))); + } + } + + $this->setRedirect('index.php?option=com_jsn&view=fields'); + } + public function profile_publish() + { + // Check for request forgeries. + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + $ids = $this->input->get('cid', array(), 'array'); + $values = array('profile_publish' => 1, 'profile_unpublish' => 0); + $task = $this->getTask(); + $value = JArrayHelper::getValue($values, $task, 0, 'int'); + + if (empty($ids)) + { + JFactory::getApplication()->enqueueMessage(JText::_('COM_JSN_NO_FIELDS_SELECTED')); + } + else + { + // Get the model. + $model = $this->getModel(); + + // Change the state of the records. + if (!$model->toggle($ids, $value, 'profile')) + { + JFactory::getApplication()->enqueueMessage($model->getError()); + } else { + if ($value == 1) + { + $ntext = 'COM_JSN_N_FIELDS_PROFILE'; + } else { + $ntext = 'COM_JSN_N_FIELDS_UNPROFILE'; + } + $this->setMessage(JText::plural($ntext, count($ids))); + } + } + + $this->setRedirect('index.php?option=com_jsn&view=fields'); + } + public function register_publish() + { + // Check for request forgeries. + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + $ids = $this->input->get('cid', array(), 'array'); + $values = array('register_publish' => 1, 'register_unpublish' => 0); + $task = $this->getTask(); + $value = JArrayHelper::getValue($values, $task, 0, 'int'); + + if (empty($ids)) + { + JFactory::getApplication()->enqueueMessage(JText::_('COM_JSN_NO_FIELDS_SELECTED')); + } + else + { + // Get the model. + $model = $this->getModel(); + + // Change the state of the records. + if (!$model->toggle($ids, $value, 'register')) + { + JFactory::getApplication()->enqueueMessage($model->getError()); + } else { + if ($value == 1) + { + $ntext = 'COM_JSN_N_FIELDS_REGISTER'; + } else { + $ntext = 'COM_JSN_N_FIELDS_UNREGISTER'; + } + $this->setMessage(JText::plural($ntext, count($ids))); + } + } + + $this->setRedirect('index.php?option=com_jsn&view=fields'); + } + public function edit_publish() + { + // Check for request forgeries. + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + $ids = $this->input->get('cid', array(), 'array'); + $values = array('edit_publish' => 1, 'edit_unpublish' => 0); + $task = $this->getTask(); + $value = JArrayHelper::getValue($values, $task, 0, 'int'); + + if (empty($ids)) + { + JFactory::getApplication()->enqueueMessage(JText::_('COM_JSN_NO_FIELDS_SELECTED')); + } + else + { + // Get the model. + $model = $this->getModel(); + + // Change the state of the records. + if (!$model->toggle($ids, $value, 'edit')) + { + JFactory::getApplication()->enqueueMessage($model->getError()); + } else { + if ($value == 1) + { + $ntext = 'COM_JSN_N_FIELDS_EDIT'; + } else { + $ntext = 'COM_JSN_N_FIELDS_UNEDIT'; + } + $this->setMessage(JText::plural($ntext, count($ids))); + } + } + + $this->setRedirect('index.php?option=com_jsn&view=fields'); + } + + public function search_publish() + { + // Check for request forgeries. + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + $ids = $this->input->get('cid', array(), 'array'); + $values = array('search_publish' => 1, 'search_unpublish' => 0); + $task = $this->getTask(); + $value = JArrayHelper::getValue($values, $task, 0, 'int'); + + if (empty($ids)) + { + JFactory::getApplication()->enqueueMessage(JText::_('COM_JSN_NO_FIELDS_SELECTED')); + } + else + { + // Get the model. + $model = $this->getModel(); + + // Change the state of the records. + if (!$model->toggle($ids, $value, 'search')) + { + JFactory::getApplication()->enqueueMessage($model->getError()); + } else { + if ($value == 1) + { + $ntext = 'COM_JSN_N_FIELDS_SERCHABLE'; + } else { + $ntext = 'COM_JSN_N_FIELDS_UNSERCHABLE'; + } + $this->setMessage(JText::plural($ntext, count($ids))); + } + } + + $this->setRedirect('index.php?option=com_jsn&view=fields'); + } + + /** + * Proxy for getModel + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * + * @return JModelLegacy The model. + * @since 3.1 + */ + public function getModel($name = 'Field', $prefix = 'JsnModel', $config = array('ignore_request' => true)) + { + $model = parent::getModel($name, $prefix, $config); + return $model; + } + + /** + * Rebuild the nested set tree. + * + * @return boolean False on failure or error, true on success. + * + * @since 3.1 + */ + public function rebuild() + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + $extension = $this->input->get('extension'); + $this->setRedirect(JRoute::_('index.php?option=com_jsn&view=fields', false)); + + $model = $this->getModel(); + + if ($model->rebuild()) { + // Rebuild succeeded. + $this->setMessage(JText::_('COM_JSN_REBUILD_SUCCESS')); + return true; + } else { + // Rebuild failed. + $this->setMessage(JText::_('COM_JSN_REBUILD_FAILURE')); + return false; + } + } + + /** + * Method to save the submitted ordering values for records via AJAX. + * + * @return void + * + * @since 3.0 + */ + public function saveOrderAjax() + { + // Get the input + $input = JFactory::getApplication()->input; + $pks = $input->post->get('cid', array(), 'array'); + $order = $input->post->get('order', array(), 'array'); + + // Sanitize the input + JArrayHelper::toInteger($pks); + JArrayHelper::toInteger($order); + + // Get the model + $model = $this->getModel(); + + // Save the ordering + $return = $model->saveorder($pks, $order); + + if ($return) + { + echo "1"; + } + + // Close the application + JFactory::getApplication()->close(); + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/controllers/user.php b/deployed/jsn/administrator/components/com_jsn/controllers/user.php new file mode 100644 index 00000000..dd4aa9dd --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/controllers/user.php @@ -0,0 +1,22 @@ + true)) + { + return parent::getModel($name, $prefix, $config); + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/defines.php b/deployed/jsn/administrator/components/com_jsn/defines.php new file mode 100644 index 00000000..364bc379 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/defines.php @@ -0,0 +1,14 @@ +quoteName($alias)." VARCHAR(255)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('checkbox_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('checkbox_defaultvalue','')).'"' : '');//(isset($item->params['text_defaultvalue']) && $item->params['text_defaultvalue']!='' ? 'default="'.$item->params['text_defaultvalue'].'"' : ''); + $inline=($item->params->get('checkbox_inline',0) ? 'optioninline="'.$item->params->get('checkbox_inline','').'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $options=array(); + $optTxt=explode("\n",$item->params->get('checkbox_options','')); + foreach($optTxt as $opt) + { + $opt=explode('|',$opt); + if(count($opt)==1) $options[]=''; + if(count($opt)==2) $options[]=''; + } + + $xml=''; + + $xml.=' + + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + '.$defaultvalue.' + '.$inline.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + > + '.implode(' ',$options).' + + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=json_decode($user->$alias); + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=json_encode($data[$alias]); + else $storeData[$alias]=''; + if($field->params->get('field_readonly','')=="1" && JFactory::getApplication()->isSite() && isset($storeData[$alias])) {unset($storeData[$alias]);} + if($field->params->get('field_readonly','')=="2" && JFactory::getApplication()->input->get->get('task','')=='profile.save' && JFactory::getApplication()->isSite() && isset($storeData[$alias])) {unset($storeData[$alias]);} + } + + public static function checkboxlist($field) + { + $value=$field->__get('value'); + if (empty($value) && (string) $value != '0') + { + return JHtml::_('users.value', $value); + } + else + { + $options=$field->getOptions(); + $result=array(); + foreach($options as $option) + { + if(in_array($option->value,$value)) $result[]=JText::_($option->text); + } + return implode(', ',$result); + } + } + + public static function getSearchInput($field) + { + $selectedOptions=JFactory::getApplication()->input->get($field->alias,null,'raw'); + $options=array(); + $optTxt=explode("\n",$field->params->get('checkbox_options','')); + foreach($optTxt as $opt) + { + $opt=explode('|',$opt); + if(count($opt)==1) $options[]=JHtml::_('select.option', trim($opt[0]), JText::_(trim(htmlspecialchars($opt[0])))); + if(count($opt)==2) $options[]=JHtml::_('select.option', trim($opt[0]), JText::_(trim(htmlspecialchars($opt[1])))); + } + + $return=JHtml::_('select.radiolist', $options, $field->alias.'[]', null, 'value', 'text', null, $field->alias); + $from=array('','type="radio"','class="radio"','class="controls"'); + if($field->params->get('checkbox_inline',0)==0) $to=array('
','type="checkbox"','class="checkbox"','id="jform_'.str_replace('-','_',$field->alias).'"'); + else $to=array('
','type="checkbox"','class="checkbox inline"','id="jform_'.str_replace('-','_',$field->alias).'"'); + if($selectedOptions!=null) + { + foreach($selectedOptions as $selectedOption) + { + $from[]='value="'.$selectedOption.'"'; + $to[]='value="'.$selectedOption.'" checked="checked"'; + } + } + return str_replace($from,$to,$return); + } + + public static function getSearchQuery($field, &$query) + { + $options=JFactory::getApplication()->input->get($field->alias,null,'raw'); + $db=JFactory::getDbo(); + + $where=''; + foreach($options as $option) + { + $where.='b.'.$db->quoteName($field->alias).' LIKE '.$db->quote('%"'.$option.'"%').' OR '; + } + $where=substr($where, 0,-4); + $query->where('('.$where.')'); + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/checkboxlist.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/checkboxlist.xml new file mode 100644 index 00000000..bdead417 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/checkboxlist.xml @@ -0,0 +1,39 @@ + +
+ +
+ + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/core.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/core.php new file mode 100644 index 00000000..9046cf34 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/core.php @@ -0,0 +1,89 @@ +isAdmin()) + { + $xml=' + '; + if($config->get('facebook_enabled',0) || $config->get('twitter_enabled',0) || $config->get('google_enabled',0) || $config->get('linkedin_enabled',0) || $config->get('instagram_enabled',0)) { + $xml.=''; + if($config->get('facebook_enabled',0)) $xml.=''; + if($config->get('twitter_enabled',0)) $xml.=''; + if($config->get('google_enabled',0)) $xml.=''; + if($config->get('linkedin_enabled',0)) $xml.=''; + if($config->get('instagram_enabled',0)) $xml.=''; + } + } + elseif(JFactory::getApplication()->input->get('view')=='registration') + { + $xml=' + + '; + } + else + { + $xml=' + + + '; + } + return $xml; + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/date.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/date.php new file mode 100644 index 00000000..e4530a51 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/date.php @@ -0,0 +1,214 @@ +quoteName($alias)." DATETIME DEFAULT NULL"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $xml=''; + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + if($item->params->get('date_default','')!="") $default=date('Y-m-d',strtotime($item->params->get('date_default',''))); + else $default=""; + $placeholder=($item->params->get('date_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('date_placeholder','')).'"' : 'hint="COM_JSN_CLICKONCALENDAR"'); + $formformat=($item->params->get('date_formformat','')!='' ? 'formformat="'.JsnHelper::xmlentities($item->params->get('date_formformat','')).'"' : 'formformat="d MM yyyy"'); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonlydate="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonlydate="true"'; + else $readonly=''; + + $xml=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + description="'.JsnHelper::xmlentities(($item->description)).'" + dateformat="'.$item->params->get('date_format','j F Y').'" + size="22" + datetype="'.$item->params->get('date_type',0).'" + default="'.$default.'" + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + readonly="true" + viewmode="'.$item->params->get('date_viewmode','days').'" + span="'.$item->params->get('date_span',0).'" + spanyear="'.$item->params->get('date_span_year',0).'" + spanmonth="'.$item->params->get('date_span_month',0).'" + spanday="'.$item->params->get('date_span_day',0).'" + '.$placeholder.' + '.$formformat.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias) && $user->$alias!='0000-00-00 00:00:00' && $user->$alias!='0000-00-00') + { + $date=new JDate($user->$alias); + $data->$alias=$date->toSql(); + } + else $data->$alias=''; + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias]) && $data[$alias]!='0000-00-00 00:00:00' && $data[$alias]!='0000-00-00') + { + if($data[$alias]=='') + $storeData[$alias]='';//'0000-00-00 00:00:00'; + else + { + $p1 = strpos($data[$alias],'-'); + $p2 = strrpos($data[$alias],'-'); + if( $p1 == 4 && $p2 == 7 ) $storeData[$alias] = $data[$alias]; + } + } + } + + public static function date($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + if ($value != '0000-00-00 00:00:00' && $value != '0000-00-00') + return $field->getDate(); + else + return JHtml::_('users.value', null); + } + } + + public static function getSearchInput($field) + { + if($field->params->get('date_type',0)!=1) + { + if(JText::_('COM_JSN_STARTMONDAY')=='1') $date_weekstart=' data-date-weekstart="1"'; + else $date_weekstart=''; + + $doc=JFactory::getDocument(); + JHtml::_('bootstrap.framework'); + $doc->addScript(JURI::root().'components/com_jsn/assets/js/bootstrap-datepicker.min.js'); + $doc->addStylesheet(JURI::root().'components/com_jsn/assets/css/datepicker.min.css'); + $return=array(); + $return[]='
'; + $return[]='
'; + $return[]='
'; + $return[]='
'; + $return[]='
'.JText::_('COM_JSN_CHOOSEDATEINTERVAL').'
'; + static $init=0; + if($init==0){ + $script=' + var DPGlobalDates = { + days: ["'.JText::_("SUNDAY").'", "'.JText::_("MONDAY").'", "'.JText::_("TUESDAY").'", "'.JText::_("WEDNESDAY").'", "'.JText::_("THURSDAY").'", "'.JText::_("FRIDAY").'", "'.JText::_("SATURDAY").'", "'.JText::_("SUNDAY").'"], + daysShort: ["'.JText::_("SUN").'", "'.JText::_("MON").'", "'.JText::_("TUE").'", "'.JText::_("WED").'", "'.JText::_("THU").'", "'.JText::_("FRI").'", "'.JText::_("SAT").'", "'.JText::_("SUN").'"], + daysMin: ["'.JText::_("SUN").'", "'.JText::_("MON").'", "'.JText::_("TUE").'", "'.JText::_("WED").'", "'.JText::_("THU").'", "'.JText::_("FRI").'", "'.JText::_("SAT").'", "'.JText::_("SUN").'"], + months: ["'.JText::_("JANUARY").'", "'.JText::_("FEBRUARY").'", "'.JText::_("MARCH").'", "'.JText::_("APRIL").'", "'.JText::_("MAY").'", "'.JText::_("JUNE").'", "'.JText::_("JULY").'", "'.JText::_("AUGUST").'", "'.JText::_("SEPTEMBER").'", "'.JText::_("OCTOBER").'", "'.JText::_("NOVEMBER").'", "'.JText::_("DECEMBER").'"], + monthsShort: ["'.JText::_("JANUARY_SHORT").'", "'.JText::_("FEBRUARY_SHORT").'", "'.JText::_("MARCH_SHORT").'", "'.JText::_("APRIL_SHORT").'", "'.JText::_("MAY_SHORT").'", "'.JText::_("JUNE_SHORT").'", "'.JText::_("JULY_SHORT").'", "'.JText::_("AUGUST_SHORT").'", "'.JText::_("SEPTEMBER_SHORT").'", "'.JText::_("OCTOBER_SHORT").'", "'.JText::_("NOVEMBER_SHORT").'", "'.JText::_("DECEMBER_SHORT").'"] + }; + '; + } + else $script=''; + $init=1; + $script.=' + jQuery(document).ready(function($){ + var nowTemp = new Date(); + var now = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0); + $("#'.$field->alias.'_from").jsndatepicker(); + $("#'.$field->alias.'_to").jsndatepicker(); + + + $("#'.$field->alias.'_from .jsndateremove").click(function(){ + //'.$field->alias.'_from.setValue(newDate); + $("#'.$field->alias.'_from input").val(""); + return false; + }); + $("#'.$field->alias.'_to .jsndateremove").click(function(){ + //'.$field->alias.'_to.setValue(newDate); + //$("#'.$field->alias.'_to").attr("data-date",""); + $("#'.$field->alias.'_to input").val(""); + return false; + }); + }); + '; + $doc->addScriptDeclaration( $script ); + } + else + { + $return=array(); + $return[]='
'; + $return[]=''; + $return[]='
'; + $return[]=''; + $return[]='
'.JText::_('COM_JSN_CHOOSEAGEINTERVAL').'
'; + } + return implode('',$return); + } + + public static function getSearchQuery($field, &$query) + { if($field->params->get('date_type',0)!=1) + { + $date_from=new JDate(str_replace('/','-',JFactory::getApplication()->input->get($field->alias.'_from','','raw'))); + $date_to=new JDate(str_replace('/','-',JFactory::getApplication()->input->get($field->alias.'_to','','raw'))); + $db=JFactory::getDbo(); + if(JFactory::getApplication()->input->get($field->alias.'_from','','raw')!='') $query->where('b.'.$db->quoteName($field->alias).' >= '.$db->quote($date_from->toSql())); + if(JFactory::getApplication()->input->get($field->alias.'_to','','raw')!='') $query->where('b.'.$db->quoteName($field->alias).' <= '.$db->quote($date_to->toSql())); + } + else + { + if(is_numeric(JFactory::getApplication()->input->get($field->alias.'_from','','raw')) && JFactory::getApplication()->input->get($field->alias.'_from','','raw')>0){ + $date_from=date('Y-m-d',strtotime('-'.JFactory::getApplication()->input->get($field->alias.'_from','','raw').' years')); + $db=JFactory::getDbo(); + $query->where('b.'.$db->quoteName($field->alias).' <= '.$db->quote($date_from)); + } + else JFactory::getApplication()->input->set($field->alias.'_from',''); + if(is_numeric(JFactory::getApplication()->input->get($field->alias.'_to','','raw')) && JFactory::getApplication()->input->get($field->alias.'_to','','raw')>0){ + $date_to=date('Y-m-d',strtotime('-'.(JFactory::getApplication()->input->get($field->alias.'_to','','raw')+1).' years')); + $db=JFactory::getDbo(); + $query->where('b.'.$db->quoteName($field->alias).' >= '.$db->quote($date_to)); + } + else JFactory::getApplication()->input->set($field->alias.'_to',''); + } + + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/date.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/date.xml new file mode 100644 index 00000000..95a9c316 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/date.xml @@ -0,0 +1,131 @@ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/delimeter.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/delimeter.php new file mode 100644 index 00000000..aab8d755 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/delimeter.php @@ -0,0 +1,74 @@ +params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $xml=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + class="'.$item->params->get('field_cssclass','').'" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + $data->$alias=$field->description; + } + + public static function storeData($field, $data, &$storeData) + { + + } + + public static function delimeter($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + //if(JText::_(strip_tags($value)) != strip_tags($value)) $value=JText::_(strip_tags($value)); + if(substr_count($value,'

')==1 && substr_count($value,' ')==0) $value=JText::_(strip_tags($value)); + JPluginHelper::importPlugin('content'); + return JHtml::_('content.prepare', $value, '', 'jsn_content.content'); + } + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/email.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/email.php new file mode 100644 index 00000000..b94129e4 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/email.php @@ -0,0 +1,116 @@ +quoteName($alias)." VARCHAR(255)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('email_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('email_defaultvalue','')).'"' : ''); + $maxlength=($item->params->get('text_maxlength','')!='' ? 'maxlength="'.$item->params->get('text_maxlength','').'"' : ''); + $placeholder=($item->params->get('email_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('email_placeholder','')).'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $filter='string'; + $type='emailfull'; + + $xml=''; + + $xml.=' + + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + size="30" + '.$defaultvalue.' + '.$maxlength.' + '.$placeholder.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=$user->$alias; + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=$data[$alias]; + } + + public static function email($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + JPluginHelper::importPlugin('content'); + return JHtml::_('content.prepare', ''.$value.'', '', 'jsn_content.content'); + } + } + + public static function getSearchInput($field) + { + $return=''; + return $return; + } + + public static function getSearchQuery($field, &$query) + { + $db=JFactory::getDbo(); + $query->where('b.'.$db->quoteName($field->alias).' LIKE '.$db->quote('%'.JFactory::getApplication()->input->get($field->alias,null,'raw').'%')); + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/email.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/email.xml new file mode 100644 index 00000000..7582625e --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/email.xml @@ -0,0 +1,25 @@ + +

+ +
+ + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/filetype.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/filetype.php new file mode 100644 index 00000000..c6fffbad --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/filetype.php @@ -0,0 +1,139 @@ +quoteName($alias)." VARCHAR(255)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue='';//($item->params->get('image_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('image_defaultvalue','')).'"' : '');//(isset($item->params['image_defaultvalue']) && $item->params['image_defaultvalue']!='' ? 'default="'.$item->params['image_defaultvalue'].'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $xml=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + required="'.($item->required && JFactory::getApplication()->input->get('jform',null,'array')==null ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + requiredfile="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + validate="filetype" + '.$readonly.' + mime="'.$item->params->get('filetype_ext','pdf|zip|doc|docx').'" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias) && $user->$alias!='' && file_exists(JPATH_SITE.'/'.$user->$alias)) + { + $data->$alias=$user->$alias; + } + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $upload_path=$field->params->get('filetype_path','images/profiler/'); + + // Set Upload Dir + $upload_dir=JPATH_SITE.'/'.$upload_path; + if(!file_exists($upload_dir)) + { + mkdir($upload_dir); + } + + // Get Alias + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=$data[$alias]; + + // Delete Image + $jform=JFactory::getApplication()->input->post->getArray(); + if(isset($jform['jform'][$field->alias.'_delete'])) + { + // Delete old file + foreach (glob($upload_dir.$alias.$data['id'].'*') as $deletefile) + { + unlink($deletefile); + } + + $storeData[$alias]=''; + return; + } + + + $jform=JFactory::getApplication()->input->files->get('jform',null,'raw'); + if(isset($jform['upload_'.$alias])) $jform_file=$jform['upload_'.$alias]; + if(isset($jform_file['name']) && strlen($jform_file['name'])>4) + { + foreach (glob($upload_dir.$alias.$data['id'].'*') as $deletefile) + { + unlink($deletefile); + } + $md5=md5(time().rand()); + $filename=$alias.$data['id'].'_'.$md5; + $name=$jform_file['name']; + $ext = strtolower($name[strlen($name)-4].$name[strlen($name)-3].$name[strlen($name)-2].$name[strlen($name)-1]); + if ($ext[0] == '.') $ext = substr($ext, 1, 3); + move_uploaded_file($jform_file['tmp_name'], $upload_dir.'/'.$filename.'.'.$ext); + $storeData[$alias]=$upload_path.$filename.'.'.$ext; + } + + } + + public static function filetype($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + return $field->getFile(); + } + + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/filetype.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/filetype.xml new file mode 100644 index 00000000..28f66a61 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/filetype.xml @@ -0,0 +1,39 @@ + +
+ +
+ + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/hide.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/hide.php new file mode 100644 index 00000000..30f9f6b2 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/hide.php @@ -0,0 +1,92 @@ +quoteName($alias)." VARCHAR(255)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('hide_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('hide_defaultvalue','')).'"' : ''); + $xml=''; + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $xml.=' + + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + size="30" + '.$defaultvalue.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=$user->$alias; + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=$data[$alias]; + } + + public static function getSearchInput($field) + { + $return=''; + return $return; + } + + public static function getSearchQuery($field, &$query) + { + $db=JFactory::getDbo(); + $query->where('b.'.$db->quoteName($field->alias).' LIKE '.$db->quote('%'.JFactory::getApplication()->input->get($field->alias,null,'raw').'%')); + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/hide.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/hide.xml new file mode 100644 index 00000000..0c02d88e --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/hide.xml @@ -0,0 +1,18 @@ + +
+ +
+ + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/image.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/image.php new file mode 100644 index 00000000..1af714a3 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/image.php @@ -0,0 +1,632 @@ +quoteName($alias)." VARCHAR(255)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('image_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('image_defaultvalue','')).'"' : '');//(isset($item->params['image_defaultvalue']) && $item->params['image_defaultvalue']!='' ? 'default="'.$item->params['image_defaultvalue'].'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $xml=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + alt="'.$item->params->get('image_alt','').'" + '.$defaultvalue.' + '.$readonly.' + width="'.$item->params->get('image_width','500').'" + height="'.$item->params->get('image_height','500').'" + width_thumb="'.$item->params->get('image_thumbwidth','100').'" + height_thumb="'.$item->params->get('image_thumbheight','100').'" + cropwebcam="'.$item->params->get('image_cropwebcam','0').'" + required="'.($item->required && JFactory::getApplication()->input->get('jform',null,'array')==null ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + requiredfile="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + validate="image" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + $alias_clean=$field->alias.'_clean'; + $alias_mini=$field->alias.'_mini'; + + $jsn_config = JComponentHelper::getParams('com_jsn'); + if($jsn_config->get('avatar',1) == 2 && isset($data->email)) // Gravatar + { + $email = $data->email; + if($field->params->get('image_defaultvalue','')!='') + $default = '&d='.urlencode(JURI::root().$field->params->get('image_defaultvalue','')); + else + $default = ''; + $size = $field->params->get('image_height',500); + $size_mini = $field->params->get('image_thumbwidth',100); + + $data->$alias = "https://www.gravatar.com/avatar/" . md5( strtolower( trim( $email ) ) ) . "?s=" . $size . $default; + $data->$alias_mini = "https://www.gravatar.com/avatar/" . md5( strtolower( trim( $email ) ) ) . "?s=" . $size_mini . $default; + return; + } + + if(isset($user->$alias) && $user->$alias!='' && file_exists(JPATH_SITE.'/'.$user->$alias)) + { + $data->$alias=$user->$alias; + $data->$alias_clean=$data->$alias; + $data->$alias_mini=preg_replace('~_(?!.*_)~', 'mini_', $data->$alias); + if(!file_exists(JPATH_SITE.'/'.$data->$alias_mini)) $data->$alias_mini=$user->$alias; + } + elseif($field->params->get('image_defaultvalue','')!='') + { + $data->$alias=$field->params->get('image_defaultvalue',''); + $data->$alias_mini=$data->$alias; + $data->$alias_clean=''; + } + elseif($alias == 'avatar') + { + $data->$alias='components/com_jsn/assets/img/default.jpg'; + $data->$alias_mini='components/com_jsn/assets/img/default.jpg'; + $data->$alias_clean=''; + } + } + + public static function storeData($field, $data, &$storeData) + { + $jsn_config = JComponentHelper::getParams('com_jsn'); + if($jsn_config->get('avatar',1) == 2) // Gravatar + { + return; + } + + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $upload_path=$field->params->get('image_path','images/profiler/'); + + // Set Upload Dir + $upload_dir=JPATH_SITE.'/'.$upload_path; + if(!file_exists($upload_dir)) + { + mkdir($upload_dir); + } + + // Get Alias + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=$data[$alias]; + + // Delete Image + $jform=JFactory::getApplication()->input->post->getArray(); + if(isset($storeData[$alias]) && $storeData[$alias]=='') + { + // Delete old file + foreach (glob($upload_dir.$alias.$data['id'].'*') as $deletefile) + { + unlink($deletefile); + } + + $storeData[$alias]=''; + return; + } + + /* ------ METHOD INPUT ------ */ + $jform=JFactory::getApplication()->input->files->get('jform',null,'raw'); + if(isset($jform['upload_'.$alias])) $jform_file=$jform['upload_'.$alias]; + if(isset($jform_file['name']) && strlen($jform_file['name'])>4) + $fileArray=array( + 'name' => $jform_file['name'], + 'type' => $jform_file['type'], + 'tmp_name' => $jform_file['tmp_name'], + 'error' => $jform_file['error'], + 'size' => $jform_file['size'], + ); + else + $fileArray=array(); + + if(file_exists(JPATH_ADMINISTRATOR.'/components/com_k2/lib/class.upload.php')) require_once(JPATH_ADMINISTRATOR.'/components/com_k2/lib/class.upload.php'); + else require_once(JPATH_ADMINISTRATOR.'/components/com_jsn/assets/class.upload.php'); + $foo = new Upload($fileArray); + $session = JFactory::getSession(); + if ($foo->uploaded) + { + // Delete old file + foreach (glob($upload_dir.$alias.$data['id'].'*') as $deletefile) + { + unlink($deletefile); + } + + $md5=md5(time().rand()); + // Store & Resize Image Thumbs + $filename=$alias.$data['id'].'mini_'.$md5; + $foo->file_new_name_body = $filename; + $foo->image_resize = true; + $foo->image_ratio_crop = true; + $foo->image_convert = 'png'; + if($field->params->get('image_thumbwidth',100)>0) $foo->image_x = $field->params->get('image_thumbwidth',100);//$field->params['image_thumbwidth']; + if($field->params->get('image_thumbheight',100)>0) $foo->image_y = $field->params->get('image_thumbheight',100);//$field->params['image_thumbheight']; + //die($foo->image_x); + $foo->Process($upload_dir); + // Store & Resize Image + $filename=$alias.$data['id'].'_'.$md5; + $foo->file_new_name_body = $filename; + $foo->image_resize = true; + $foo->image_ratio_crop = true; + $foo->image_convert = 'png'; + if($field->params->get('image_width',500)>0) $foo->image_x = $field->params->get('image_width',500);//$field->params['image_width']; + if($field->params->get('image_height',500)>0) $foo->image_y = $field->params->get('image_height',500);//$field->params['image_height']; + $foo->Process($upload_dir); + if ($foo->processed) + { + $storeData[$alias]=$upload_path.$foo->file_dst_name; + $foo->Clean(); + } + } + /* ------ METHOD CROP & WEBCAM ------ */ + if($session->get('_tmp_img_'.$alias,'')!=''){ + $md5=md5(time().rand()); + $file = $session->get('_tmp_img_'.$alias,''); + $ext = pathinfo($file, PATHINFO_EXTENSION); + $filename=$alias.$data['id'].'_'.$md5.'.'.$ext; + $filename_mini=$alias.$data['id'].'mini_'.$md5.'.'.$ext; + $path = JPATH_SITE.'/images/_tmp/'; + if(file_exists($path . str_replace('.','-big.',$file)) && file_exists($path . str_replace('.','-big.',$file))){ + foreach (glob($upload_dir.$alias.$data['id'].'*') as $deletefile) + { + unlink($deletefile); + } + rename($path . str_replace('.','-big.',$file),$upload_dir.$filename); + rename($path . str_replace('.','-mini.',$file),$upload_dir.$filename_mini); + unlink($path . $file); + $storeData[$alias]=$upload_path.$filename; + } + /* Clean Session Var */ + $session->set('_tmp_img_'.$alias,''); + } + /* ------ METHOD CROP ------ */ + $images = Slim::getImages('imgupload_'.$alias); + if(count($images)){ + + foreach ($images as $image) { + switch ($image['input']['type']) { + case 'image/gif': + $extension = '.gif'; + break; + case 'image/jpeg': + $extension = '.jpg'; + break; + case 'image/png': + $extension = '.png'; + break; + default: + $extension = '.jpg'; + break; + } + // Clean Old Images + foreach (glob($upload_dir.$alias.$data['id'].'*') as $deletefile) + { + unlink($deletefile); + } + + // Copy uploaded images + $md5=md5(time().rand()); + $filename=$alias.$data['id'].'_'.$md5.$extension; + $filename_mini=$alias.$data['id'].'mini_'.$md5; + $file = Slim::saveFile($image['output']['data'], $filename, $upload_dir,false); + $file = Slim::saveFile($image['output']['data'], $filename_mini, $upload_dir,false); + $storeData[$alias]=$upload_path.$filename; + + // Resize Thumbs + $handle = new upload($upload_dir.$filename_mini); + $handle->file_new_name_body=$filename_mini; + if($field->params->get('image_thumbwidth',100)>0) $handle->image_x = $field->params->get('image_thumbwidth',100); + if($field->params->get('image_thumbheight',100)>0) $handle->image_y = $field->params->get('image_thumbheight',100); + $handle->image_resize = true; + $handle->image_ratio_crop = true; + $handle->process($upload_dir); + $handle->clean(); + + } + } + + /* Temp folder path to clean */ + $path = JPATH_SITE.'/images/_tmp/'; + + /* Clean Tmp folder from not saved images */ + if($session->get('_tmp_rand_'.$alias,'')!='') + { + + $rand=$session->get('_tmp_rand_'.$alias,'')!=''; + + $filename_prefix=substr(md5($_SERVER['REMOTE_ADDR'].$alias.$rand),0,10); + + if (file_exists($path)) + { + foreach (glob($path.$filename_prefix.'*') as $deletefile) + { + unlink($deletefile); + } + } + } + } + + public static function image($field,$user) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + return $field->getImage($user); + } + + } + + public static function operations() + { + JFactory::getConfig()->set('gzip',false); + $db=JFactory::getDbo(); + $query=$db->getQuery(true); + $query->select('params')->from('#__jsn_fields')->where('alias='.$db->quote(JFactory::getApplication()->input->get('field'))); + $params = new JRegistry; + $db->setQuery($query); + $params->loadString($db->loadResult()); + $name=JFactory::getApplication()->input->get('field'); + + $session = JFactory::getSession(); + + + require_once(JPATH_ADMINISTRATOR.'/components/com_jsn/assets/ImgPicker.php'); + + if($session->get('_tmp_rand_'.$name,'')=='') $session->set('_tmp_rand_'.$name,md5(time().rand())); + + $rand=$session->get('_tmp_rand_'.$name,''); + + $filename=substr(md5($_SERVER['REMOTE_ADDR'].$name.$rand),0,10); + + $upload_tmp = JPATH_SITE.'/images/_tmp/'; + if (!file_exists($upload_tmp)) { + mkdir($upload_tmp); + } + + $options = array( + + // Upload directory path + 'upload_dir' => $upload_tmp, + + // Upload directory url: + //'upload_url' => 'http://localhost/imgPicker/files/', + 'upload_url' => JURI::root(true) . '/images/_tmp/', + + // Accepted file types: + 'accept_file_types' => 'png|jpg|jpeg|gif', + + // Directory mode: + 'mkdir_mode' => 0777, + + // File size restrictions (in bytes): + 'max_file_size' => null, + 'min_file_size' => 1, + + // Image resolution restrictions (in px): + 'max_width' => null, + 'max_height' => null, + 'min_width' => 1, + 'min_height' => 1, + + // Image versions: + 'versions' => array( + // This will create 2 image versions: the original one and a 200x200 one + 'mini' => array( + //'upload_dir' => '', + //'upload_url' => '', + // Create square image + //'crop' => true, + 'max_width' => $params->get('image_thumbwidth',100), + 'max_height' => $params->get('image_thumbheight',100) + ), + 'big' => array( + //'upload_dir' => '', + //'upload_url' => '', + // Create square imag + //'crop' => true, + 'max_width' => $params->get('image_width',500), + 'max_height' => $params->get('image_height',500) + ), + ), + + /** + * Load callback + * + * @param ImgPicker $instance + * @return string|array + */ + 'load' => function($instance) { + //return 'avatar.jpg'; + }, + + /** + * Delete callback + * + * @param string $filename + * @param ImgPicker $instance + * @return boolean + */ + 'delete' => function($filename, $instance) { + return true; + }, + + /** + * Upload start callback + * + * @param stdClass $image + * @param ImgPicker $instance + * @return void + */ + 'upload_start' => function($image, $instance) { + $session = JFactory::getSession(); + $rand=$session->get('_tmp_rand_'.JFactory::getApplication()->input->get('field')); + $filename=substr(md5($_SERVER['REMOTE_ADDR'].JFactory::getApplication()->input->get('field').$rand),0,10); + $image->name = $filename . '.' . $image->type; + }, + + /** + * Upload complete callback + * + * @param stdClass $image + * @param ImgPicker $instance + * @return void + */ + 'upload_complete' => function($image, $instance) { + }, + + /** + * Crop start callback + * + * @param stdClass $image + * @param ImgPicker $instance + * @return void + */ + 'crop_start' => function($image, $instance) { + $session = JFactory::getSession(); + $rand=$session->get('_tmp_rand_'.JFactory::getApplication()->input->get('field')); + $filename=substr(md5($_SERVER['REMOTE_ADDR'].JFactory::getApplication()->input->get('field').$rand),0,10); + $image->name = $filename . '.' . $image->type; + $session->set('_tmp_img_'.JFactory::getApplication()->input->get('field'),$filename . '.' . $image->type); + }, + + /** + * Crop complete callback + * + * @param stdClass $image + * @param ImgPicker $instance + * @return void + */ + 'crop_complete' => function($image, $instance) { + + } + ); + + // Create new ImgPicker instance + new ImgPicker($options); + + } + +} + + +abstract class SlimStatus { + const FAILURE = 'failure'; + const SUCCESS = 'success'; +} + +class Slim { + + public static function getImages($inputName = 'slim') { + + $values = Slim::getPostData($inputName); + + // test for errors + if ($values === false) { + return false; + } + + // determine if contains multiple input values, if is singular, put in array + $data = array(); + if (!is_array($values)) { + $values = array($values); + } + + // handle all posted fields + foreach ($values as $value) { + $inputValue = Slim::parseInput($value); + if ($inputValue) { + array_push($data, $inputValue); + } + } + + // return the data collected from the fields + return $data; + + } + + // $value should be in JSON format + private static function parseInput($value) { + + // if no json received, exit, don't handle empty input values. + if (empty($value)) {return null;} + + // The data is posted as a JSON String so to be used it needs to be deserialized first + $data = json_decode($value); + + // shortcut + $input = null; + $actions = null; + $output = null; + $meta = null; + + if (isset ($data->input)) { + $inputData = isset($data->input->image) ? Slim::getBase64Data($data->input->image) : null; + $input = array( + 'data' => $inputData, + 'name' => $data->input->name, + 'type' => $data->input->type, + 'size' => $data->input->size, + 'width' => $data->input->width, + 'height' => $data->input->height, + ); + } + + if (isset($data->output)) { + $outputData = isset($data->output->image) ? Slim::getBase64Data($data->output->image) : null; + $output = array( + 'data' => $outputData, + 'width' => $data->output->width, + 'height' => $data->output->height + ); + } + + if (isset($data->actions)) { + $actions = array( + 'crop' => $data->actions->crop ? array( + 'x' => $data->actions->crop->x, + 'y' => $data->actions->crop->y, + 'width' => $data->actions->crop->width, + 'height' => $data->actions->crop->height, + 'type' => $data->actions->crop->type + ) : null, + 'size' => $data->actions->size ? array( + 'width' => $data->actions->size->width, + 'height' => $data->actions->size->height + ) : null + ); + } + + if (isset($data->meta)) { + $meta = $data->meta; + } + + // We've sanitized the base64data and will now return the clean file object + return array( + 'input' => $input, + 'output' => $output, + 'actions' => $actions, + 'meta' => $meta + ); + } + + // $path should have trailing slash + public static function saveFile($data, $name, $path = 'tmp/', $uid = true) { + + // Add trailing slash if omitted + if (substr($path, -1) !== '/') { + $path .= '/'; + } + + // Test if directory already exists + if(!is_dir($path)){ + mkdir($path, 0755, true); + } + + // Let's put a unique id in front of the filename so we don't accidentally overwrite older files + if ($uid) { + $name = uniqid() . '_' . $name; + } + + // Add name to path, we need the full path including the name to save the file + $path = $path . $name; + + // store the file + Slim::save($data, $path); + + // return the files new name and location + return array( + 'name' => $name, + 'path' => $path + ); + } + + public static function outputJSON($data) { + header('Content-Type: application/json'); + echo json_encode($data); + } + + /** + * Gets the posted data from the POST or FILES object. If was using Slim to upload it will be in POST (as posted with hidden field) if not enhanced with Slim it'll be in FILES. + * @param $inputName + * @return array|bool + */ + private static function getPostData($inputName) { + + $values = array(); + + if (isset($_POST[$inputName])) { + $values = $_POST[$inputName]; + } + else if (isset($_FILES[$inputName])) { + // Slim was not used to upload this file + return false; + } + + return $values; + } + + /** + * Saves the data to a given location + * @param $data + * @param $path + */ + private static function save($data, $path) { + file_put_contents($path, $data); + } + + /** + * Strips the "data:image..." part of the base64 data string so PHP can save the string as a file + * @param $data + * @return string + */ + private static function getBase64Data($data) { + return base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $data)); + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/image.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/image.xml new file mode 100644 index 00000000..5af2989b --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/image.xml @@ -0,0 +1,93 @@ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/lastvisitdate.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/lastvisitdate.php new file mode 100644 index 00000000..c670c7c0 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/lastvisitdate.php @@ -0,0 +1,137 @@ +params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + if(JFactory::getApplication()->isSite()) + $xml=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + description="" + readonly="true" + format="%Y-%m-%d %H:%M:%S" + size="22" + filter="user_utc" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + if(isset($data->lastvisitDate)) $data->lastvisitdate=$data->lastvisitDate; + } + + public static function storeData($field, $data, &$storeData) + { + + } + + public static function lastvisitdate($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + if ($value != '0000-00-00 00:00:00') + return JHtml::_('date', $value); + else + return JText::_('COM_JSN_NEVER'); + } + } + + public static function getSearchInput($field) + { + if(JText::_('COM_JSN_STARTMONDAY')=='1') $date_weekstart=' data-date-weekstart="1"'; + else $date_weekstart=''; + + $doc=JFactory::getDocument(); + JHtml::_('bootstrap.framework'); + $doc->addScript(JURI::root().'components/com_jsn/assets/js/bootstrap-datepicker.js'); + $doc->addStylesheet(JURI::root().'components/com_jsn/assets/css/datepicker.css'); + $return=array(); + $return[]='
'; + $return[]='
'; + $return[]='
'; + $return[]='
'; + $return[]='
'.JText::_('COM_JSN_CHOOSEDATEINTERVAL').'
'; + static $init=0; + if($init==0){ + $script=' + var DPGlobalDates = { + days: ["'.JText::_("SUNDAY").'", "'.JText::_("MONDAY").'", "'.JText::_("TUESDAY").'", "'.JText::_("WEDNESDAY").'", "'.JText::_("THURSDAY").'", "'.JText::_("FRIDAY").'", "'.JText::_("SATURDAY").'", "'.JText::_("SUNDAY").'"], + daysShort: ["'.JText::_("SUN").'", "'.JText::_("MON").'", "'.JText::_("TUE").'", "'.JText::_("WED").'", "'.JText::_("THU").'", "'.JText::_("FRI").'", "'.JText::_("SAT").'", "'.JText::_("SUN").'"], + daysMin: ["'.JText::_("SUN").'", "'.JText::_("MON").'", "'.JText::_("TUE").'", "'.JText::_("WED").'", "'.JText::_("THU").'", "'.JText::_("FRI").'", "'.JText::_("SAT").'", "'.JText::_("SUN").'"], + months: ["'.JText::_("JANUARY").'", "'.JText::_("FEBRUARY").'", "'.JText::_("MARCH").'", "'.JText::_("APRIL").'", "'.JText::_("MAY").'", "'.JText::_("JUNE").'", "'.JText::_("JULY").'", "'.JText::_("AUGUST").'", "'.JText::_("SEPTEMBER").'", "'.JText::_("OCTOBER").'", "'.JText::_("NOVEMBER").'", "'.JText::_("DECEMBER").'"], + monthsShort: ["'.JText::_("JANUARY_SHORT").'", "'.JText::_("FEBRUARY_SHORT").'", "'.JText::_("MARCH_SHORT").'", "'.JText::_("APRIL_SHORT").'", "'.JText::_("MAY_SHORT").'", "'.JText::_("JUNE_SHORT").'", "'.JText::_("JULY_SHORT").'", "'.JText::_("AUGUST_SHORT").'", "'.JText::_("SEPTEMBER_SHORT").'", "'.JText::_("OCTOBER_SHORT").'", "'.JText::_("NOVEMBER_SHORT").'", "'.JText::_("DECEMBER_SHORT").'"] + }; + '; + } + else $script=''; + $init=1; + $script.=' + jQuery(document).ready(function($){ + var nowTemp = new Date(); + var now = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0); + $("#'.$field->alias.'_from").jsndatepicker(); + $("#'.$field->alias.'_to").jsndatepicker(); + + + $("#'.$field->alias.'_from .jsndateremove").click(function(){ + //'.$field->alias.'_from.setValue(newDate); + $("#'.$field->alias.'_from input").val(""); + return false; + }); + $("#'.$field->alias.'_to .jsndateremove").click(function(){ + //'.$field->alias.'_to.setValue(newDate); + //$("#'.$field->alias.'_to").attr("data-date",""); + $("#'.$field->alias.'_to input").val(""); + return false; + }); + }); + '; + $doc->addScriptDeclaration( $script ); + return implode('',$return); + } + + public static function getSearchQuery($field, &$query) + { + $date_from=new JDate(str_replace('/','-',JFactory::getApplication()->input->get($field->alias.'_from','','raw'))); + $date_to=new JDate(str_replace('/','-',JFactory::getApplication()->input->get($field->alias.'_to','','raw'))); + $db=JFactory::getDbo(); + if(JFactory::getApplication()->input->get($field->alias.'_from','','raw')!='') $query->where('a.'.$db->quoteName('lastvisitDate').' > '.$db->quote($date_from->toSql())); + if(JFactory::getApplication()->input->get($field->alias.'_to','','raw')!='') $query->where('a.'.$db->quoteName('lastvisitDate').' < '.$db->quote($date_to->toSql())); + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/link.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/link.php new file mode 100644 index 00000000..e42427b6 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/link.php @@ -0,0 +1,119 @@ +quoteName($alias)." VARCHAR(255)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('link_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('link_defaultvalue','')).'"' : ''); + $maxlength=($item->params->get('link_maxlength','')!='' ? 'maxlength="'.$item->params->get('link_maxlength','').'"' : ''); + $placeholder=($item->params->get('link_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('link_placeholder','')).'"' : ''); + $robots=$item->params->get('link_robots',''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $type='link'; + + $xml=''; + + $xml.=' + + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + size="30" + '.$defaultvalue.' + '.$maxlength.' + '.$placeholder.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + rel="'.$robots.'" + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=$user->$alias; + if(isset($user->$alias) && $data->$alias=='http://') $data->$alias=''; + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias])){ + if(substr(trim($data[$alias]), 0, 4)=='http') $storeData[$alias]=$data[$alias]; + else $storeData[$alias]='http://'.$data[$alias]; + } + if($storeData[$alias]=='http://') $storeData[$alias]=''; + } + + public static function link($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + return $field->getLink(); + } + } + + public static function getSearchInput($field) + { + $return=''; + return $return; + } + + public static function getSearchQuery($field, &$query) + { + $db=JFactory::getDbo(); + $query->where('b.'.$db->quoteName($field->alias).' LIKE '.$db->quote('%'.JFactory::getApplication()->input->get($field->alias,null,'raw').'%')); + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/link.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/link.xml new file mode 100644 index 00000000..768f2643 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/link.xml @@ -0,0 +1,45 @@ + +
+ +
+ + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/numeric.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/numeric.php new file mode 100644 index 00000000..1f2f1533 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/numeric.php @@ -0,0 +1,115 @@ +quoteName($alias)." INTEGER"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('numeric_defaultvalue','')!='' ? 'default="'.$item->params->get('numeric_defaultvalue','').'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $max='max="'.$item->params->get('numeric_max',999999).'"'; + $min='min="'.$item->params->get('numeric_min',0).'"'; + $step='step="'.$item->params->get('numeric_step',1).'"'; + + if(isset($_SERVER['HTTP_USER_AGENT'])) $agent = $_SERVER['HTTP_USER_AGENT']; else $agent=''; + if(strlen(strstr($agent,"Firefox")) > 0 ) $type='text'; + else $type='numeric'; + + $xml=''; + + $xml.=' + + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + size="30" + '.$defaultvalue.' + '.$max.' + '.$min.' + '.$step.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + validate="numeric" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=$user->$alias; + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=$data[$alias]; + } + + public static function getSearchInput($field) + { + $max='max="'.$field->params->get('numeric_max',999999).'"'; + $min='min="'.$field->params->get('numeric_min',0).'"'; + $step='step="'.$field->params->get('numeric_step',1).'"'; + + $return=array(); + $return[]='
'; + $return[]=''; + $return[]='
'; + $return[]=''; + $return[]='
'.JText::_('COM_JSN_CHOOSENUMERICINTERVAL').'
'; + + return implode('',$return); + } + + public static function getSearchQuery($field, &$query) + { + $db=JFactory::getDbo(); + if(JFactory::getApplication()->input->get($field->alias.'_from','','raw')!='') $query->where('b.'.$db->quoteName($field->alias).' >= '.$db->quote(JFactory::getApplication()->input->get($field->alias.'_from','','raw'))); + if(JFactory::getApplication()->input->get($field->alias.'_to','','raw')!='') $query->where('b.'.$db->quoteName($field->alias).' <= '.$db->quote(JFactory::getApplication()->input->get($field->alias.'_to','','raw'))); + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/numeric.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/numeric.xml new file mode 100644 index 00000000..1c8714b8 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/numeric.xml @@ -0,0 +1,45 @@ + +
+ +
+ + + + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/password.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/password.php new file mode 100644 index 00000000..d31fb620 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/password.php @@ -0,0 +1,136 @@ +isSite()) + { + $configUsers=JComponentHelper::getParams('com_users'); + $configJsn=JComponentHelper::getParams('com_jsn'); + if(JFactory::getApplication()->input->get('view')=='registration') $required='required="true"'; + else $required=''; + if($configJsn->get('passwordstrengthmeter',0)) $strengthmeter='strengthmeter="true"'; + else $strengthmeter=''; + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $placeholder=($item->params->get('password_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('password_placeholder','')).'"' : ''); + $placeholder2=($item->params->get('password_placeholder2','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('password_placeholder2','')).'"' : ''); + $xml.=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + size="30" + minimum_length="'.$configUsers->get('minimum_length',4).'" + minimum_integers="'.$configUsers->get('minimum_integers',0).'" + minimum_symbols="'.$configUsers->get('minimum_symbols',0).'" + minimum_uppercase="'.$configUsers->get('minimum_uppercase',0).'" + '.(($version->RELEASE=='3.0' || $version->getShortVersion()=='3.1.1' || $version->getShortVersion()=='3.1.0') ? 'field="password2" validate="equals" message="COM_USERS_PROFILE_PASSWORD1_MESSAGE"' : 'validate="password"').' + '.$required.' + '.$placeholder.' + '.$strengthmeter.' + /> + '; + $config = JComponentHelper::getParams('com_jsn'); + if($config->get('confirmuserpassword',1) || JFactory::getApplication()->input->get('layout','')=='edit') + { + $xml.=' + RELEASE=='3.0' || $version->getShortVersion()=='3.1.1' || $version->getShortVersion()=='3.1.0') ? '' : 'field="password1" validate="equals" message="COM_USERS_PROFILE_PASSWORD1_MESSAGE"').' + class="validate-confirmpassword" + description="COM_USERS_PROFILE_PASSWORD2_DESC" + filter="raw" + label="'.($hideTitle ? JsnHelper::xmlentities(''.JText::_('COM_JSN_PROFILE_PASSWORD2_LABEL').'') : 'COM_JSN_PROFILE_PASSWORD2_LABEL').'" + size="30" + '.$required.' + '.$placeholder2.' + /> + '; + } + } + else{ + $configJsn=JComponentHelper::getParams('com_jsn'); + if($configJsn->get('passwordstrengthmeter',0)) $strengthmeter='strengthmeter="true"'; + + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $placeholder=($item->params->get('password_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('password_placeholder','')).'"' : ''); + $placeholder2=($item->params->get('password_placeholder2','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('password_placeholder2','')).'"' : ''); + if(JFactory::getApplication()->input->get('option','')=='com_admin') + { + $password1_desc='COM_ADMIN_USER_FIELD_PASSWORD_DESC'; + $password2_label='COM_ADMIN_USER_FIELD_PASSWORD2_LABEL'; + $password2_desc='COM_ADMIN_USER_FIELD_PASSWORD2_DESC'; + } + else { + $password1_desc='COM_USERS_USER_FIELD_PASSWORD_DESC'; + $password2_label='COM_USERS_USER_FIELD_PASSWORD2_LABEL'; + $password2_desc='COM_USERS_USER_FIELD_PASSWORD2_DESC'; + } + + $xml.=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + size="30" + '.$placeholder.' + /> + + '.JText::_($password2_label).'') : $password2_label).'" + size="30" + validate="equals" + field="password" + '.$placeholder2.' + /> + '; + + } + return $xml; + } + + public static function loadData($field, $user, &$data) + { + + } + + public static function storeData($field, $data, &$storeData) + { + + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/password.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/password.xml new file mode 100644 index 00000000..3a9b558a --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/password.xml @@ -0,0 +1,27 @@ + +
+ +
+ + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/phone.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/phone.php new file mode 100644 index 00000000..a9aecfb5 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/phone.php @@ -0,0 +1,109 @@ +quoteName($alias)." VARCHAR(100)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('phone_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('phone_defaultvalue','')).'"' : ''); + $placeholder=($item->params->get('phone_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('phone_placeholder','')).'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $type='phone'; + + $xml=''; + + $xml.=' + + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + size="30" + '.$defaultvalue.' + '.$placeholder.' + '.$readonly.' + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=$user->$alias; + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=$data[$alias]; + } + + public static function getSearchInput($field) + { + $return=''; + return $return; + } + + public static function getSearchQuery($field, &$query) + { + $db=JFactory::getDbo(); + $query->where('b.'.$db->quoteName($field->alias).' LIKE '.$db->quote('%'.JFactory::getApplication()->input->get($field->alias,null,'raw').'%')); + } + + public static function phone($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + return ''.$value.''; + } + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/phone.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/phone.xml new file mode 100644 index 00000000..528876e9 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/phone.xml @@ -0,0 +1,25 @@ + +
+ +
+ + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/radiolist.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/radiolist.php new file mode 100644 index 00000000..5c3d7831 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/radiolist.php @@ -0,0 +1,153 @@ +quoteName($alias)." VARCHAR(255)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('radio_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('radio_defaultvalue','')).'"' : ''); + $inline=($item->params->get('radio_inline',0) ? 'optioninline="'.$item->params->get('radio_inline','').'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $options=array(); + $optTxt=explode("\n",$item->params->get('radio_options','')); + foreach($optTxt as $opt) + { + $opt=explode('|',$opt); + if(count($opt)==1) $options[]=''; + if(count($opt)==2) $options[]=''; + } + + $xml=''; + + $xml.=' + + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + '.$defaultvalue.' + '.$inline.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + > + '.implode(' ',$options).' + + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=$user->$alias; + //elseif($field->params->get('radio_defaultvalue','')!=''/*isset($field->params['text_defaultvalue']) && $field->params['text_defaultvalue']!=''*/) $data->$alias=$field->params->get('radio_defaultvalue','');//$field->params['text_defaultvalue']; + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=$data[$alias]; + } + + public static function radiolist($field) + { + $value=$field->__get('value'); + if (empty($value) && (string) $value != '0') + { + return JHtml::_('users.value', $value); + } + else + { + $options=$field->getOptions(); + $result=''; + foreach($options as $option) + { + if($option->value==$value) $result=JText::_($option->text); + } + return $result; + } + } + + public static function getSearchInput($field) + { + $selectedOptions=JFactory::getApplication()->input->get($field->alias,null,'raw'); + $options=array(); + $optTxt=explode("\n",$field->params->get('radio_options','')); + foreach($optTxt as $opt) + { + $opt=explode('|',$opt); + if(count($opt)==1) $options[]=JHtml::_('select.option', trim($opt[0]), JText::_(trim(htmlspecialchars($opt[0])))); + if(count($opt)==2) $options[]=JHtml::_('select.option', trim($opt[0]), JText::_(trim(htmlspecialchars($opt[1])))); + } + + $return=JHtml::_('select.radiolist', $options, $field->alias.'[]', null, 'value', 'text', null, $field->alias); + $from=array('','type="radio"','class="radio"','class="controls"'); + if($field->params->get('radio_inline',0)==0) $to=array('
','type="checkbox"','class="checkbox"','id="jform_'.str_replace('-','_',$field->alias).'"'); + else $to=array('
','type="checkbox"','class="checkbox inline"','id="jform_'.str_replace('-','_',$field->alias).'"'); + if($selectedOptions!=null) + { + foreach($selectedOptions as $selectedOption) + { + $from[]='value="'.$selectedOption.'"'; + $to[]='value="'.$selectedOption.'" checked="checked"'; + } + } + return str_replace($from,$to,$return); + } + + public static function getSearchQuery($field, &$query) + { + $options=JFactory::getApplication()->input->get($field->alias,null,'raw'); + $db=JFactory::getDbo(); + + $where=''; + foreach($options as $option) + { + $where.='b.'.$db->quoteName($field->alias).' = '.$db->quote($option).' OR '; + } + $where=substr($where, 0,-4); + $query->where('('.$where.')'); + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/radiolist.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/radiolist.xml new file mode 100644 index 00000000..d401a963 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/radiolist.xml @@ -0,0 +1,39 @@ + +
+ +
+ + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/registerdate.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/registerdate.php new file mode 100644 index 00000000..0eb328f8 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/registerdate.php @@ -0,0 +1,137 @@ +params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + if(JFactory::getApplication()->isSite()) + $xml=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + description="" + readonly="true" + format="%Y-%m-%d %H:%M:%S" + size="22" + filter="user_utc" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + if(isset($data->registerDate)) $data->registerdate=$data->registerDate; + } + + public static function storeData($field, $data, &$storeData) + { + + } + + public static function registerdate($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + return JHtml::_('date', $value); + } + } + + public static function getSearchInput($field) + { + if(JText::_('COM_JSN_STARTMONDAY')=='1') $date_weekstart=' data-date-weekstart="1"'; + else $date_weekstart=''; + + $doc=JFactory::getDocument(); + JHtml::_('bootstrap.framework'); + $doc->addScript(JURI::root().'components/com_jsn/assets/js/bootstrap-datepicker.js'); + $doc->addStylesheet(JURI::root().'components/com_jsn/assets/css/datepicker.css'); + $return=array(); + $return[]='
'; + $return[]='
'; + $return[]='
'; + $return[]='
'; + $return[]='
'.JText::_('COM_JSN_CHOOSEDATEINTERVAL').'
'; + static $init=0; + if($init==0){ + $script=' + var DPGlobalDates = { + days: ["'.JText::_("SUNDAY").'", "'.JText::_("MONDAY").'", "'.JText::_("TUESDAY").'", "'.JText::_("WEDNESDAY").'", "'.JText::_("THURSDAY").'", "'.JText::_("FRIDAY").'", "'.JText::_("SATURDAY").'", "'.JText::_("SUNDAY").'"], + daysShort: ["'.JText::_("SUN").'", "'.JText::_("MON").'", "'.JText::_("TUE").'", "'.JText::_("WED").'", "'.JText::_("THU").'", "'.JText::_("FRI").'", "'.JText::_("SAT").'", "'.JText::_("SUN").'"], + daysMin: ["'.JText::_("SUN").'", "'.JText::_("MON").'", "'.JText::_("TUE").'", "'.JText::_("WED").'", "'.JText::_("THU").'", "'.JText::_("FRI").'", "'.JText::_("SAT").'", "'.JText::_("SUN").'"], + months: ["'.JText::_("JANUARY").'", "'.JText::_("FEBRUARY").'", "'.JText::_("MARCH").'", "'.JText::_("APRIL").'", "'.JText::_("MAY").'", "'.JText::_("JUNE").'", "'.JText::_("JULY").'", "'.JText::_("AUGUST").'", "'.JText::_("SEPTEMBER").'", "'.JText::_("OCTOBER").'", "'.JText::_("NOVEMBER").'", "'.JText::_("DECEMBER").'"], + monthsShort: ["'.JText::_("JANUARY_SHORT").'", "'.JText::_("FEBRUARY_SHORT").'", "'.JText::_("MARCH_SHORT").'", "'.JText::_("APRIL_SHORT").'", "'.JText::_("MAY_SHORT").'", "'.JText::_("JUNE_SHORT").'", "'.JText::_("JULY_SHORT").'", "'.JText::_("AUGUST_SHORT").'", "'.JText::_("SEPTEMBER_SHORT").'", "'.JText::_("OCTOBER_SHORT").'", "'.JText::_("NOVEMBER_SHORT").'", "'.JText::_("DECEMBER_SHORT").'"] + }; + '; + } + else $script=''; + $init=1; + $script.=' + jQuery(document).ready(function($){ + var nowTemp = new Date(); + var now = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0); + $("#'.$field->alias.'_from").jsndatepicker(); + $("#'.$field->alias.'_to").jsndatepicker(); + + + $("#'.$field->alias.'_from .jsndateremove").click(function(){ + //'.$field->alias.'_from.setValue(newDate); + $("#'.$field->alias.'_from input").val(""); + return false; + }); + $("#'.$field->alias.'_to .jsndateremove").click(function(){ + //'.$field->alias.'_to.setValue(newDate); + //$("#'.$field->alias.'_to").attr("data-date",""); + $("#'.$field->alias.'_to input").val(""); + return false; + }); + }); + '; + $doc->addScriptDeclaration( $script ); + return implode('',$return); + + } + + public static function getSearchQuery($field, &$query) + { + $date_from=new JDate(str_replace('/','-',JFactory::getApplication()->input->get($field->alias.'_from','','raw'))); + $date_to=new JDate(str_replace('/','-',JFactory::getApplication()->input->get($field->alias.'_to','','raw'))); + $db=JFactory::getDbo(); + //$from=JDate::getInstance((JFactory::getApplication()->input->get($field->alias.'_from','')=='' ? '0000-00-00' : $date_from->toSql())); + //$to=JDate::getInstance((JFactory::getApplication()->input->get($field->alias.'_to','')=='' ? '9999-00-00' : $date_to->toSql())); + if(JFactory::getApplication()->input->get($field->alias.'_from','','raw')!='') $query->where('a.'.$db->quoteName('registerDate').' > '.$db->quote($date_from->toSql())); + if(JFactory::getApplication()->input->get($field->alias.'_to','','raw')!='') $query->where('a.'.$db->quoteName('registerDate').' < '.$db->quote($date_to->toSql())); + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/selectlist.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/selectlist.php new file mode 100644 index 00000000..c48622e8 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/selectlist.php @@ -0,0 +1,405 @@ +quoteName($alias)." VARCHAR(255)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('select_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('select_defaultvalue','')).'"' : '');//(isset($item->params['text_defaultvalue']) && $item->params['text_defaultvalue']!='' ? 'default="'.$item->params['text_defaultvalue'].'"' : ''); + $multiple=($item->params->get('select_multiple',0) ? 'multiple="true"' : ''); + $dbtable=($item->params->get('select_dbopttable','')=='' ? '' : 'dbopttable="'.$item->params->get('select_dbopttable','').'"'); + $dbvalue=($item->params->get('select_dboptvalue','')=='' ? '' : 'dboptvalue="'.$item->params->get('select_dboptvalue','').'"'); + $dbtext=($item->params->get('select_dbopttext','')=='' ? '' : 'dbopttext="'.$item->params->get('select_dbopttext','').'"'); + $dbwhere=($item->params->get('select_dboptwhere','')=='' ? '' : 'dboptwhere="'.JsnHelper::xmlentities($item->params->get('select_dboptwhere','')).'"'); + $dbfiltervalue=($item->params->get('select_dboptfiltervalue','')=='' ? '' : 'dboptfiltervalue="'.JsnHelper::xmlentities($item->params->get('select_dboptfiltervalue','')).'"'); + $dbfiltercolumn=($item->params->get('select_dboptfiltercolumn','')=='' ? '' : 'dboptfiltercolumn="'.JsnHelper::xmlentities($item->params->get('select_dboptfiltercolumn','')).'"'); + $placeholder=($item->params->get('select_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('select_placeholder','')).'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $options=array(); + $optTxt=explode("\n",$item->params->get('select_options','')); + foreach($optTxt as $opt) + { + $opt=trim($opt); + if($opt!=''){ + $opt=explode('|',$opt); + if(count($opt)==1) $options[]=''; + if(count($opt)==2) $options[]=''; + } + } + + $xml=''; + + if(!$item->params->get('select_multiple',0)) { + if($item->params->get('select_placeholder','')=='') $noval=''; + else $noval=''; + } + else $noval=''; + + $xml.=' + + '.JText::_($item->title).'') : htmlspecialchars($item->title)).'" + '.$defaultvalue.' + '.$multiple.' + '.$dbtable.' + '.$dbvalue.' + '.$dbtext.' + '.$dbwhere.' + '.$placeholder.' + '.$dbfiltervalue.' + '.$dbfiltercolumn.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + > + '.$noval.' + '.implode(' ',$options).' + + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=($field->params->get('select_multiple',0) ? json_decode($user->$alias) : $user->$alias); + } + + public static function storeData($field, $data, &$storeData) + { + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=($field->params->get('select_multiple',0) ? json_encode($data[$alias]) : $data[$alias]); + elseif(JFactory::getApplication()->input->get('jform_'.$alias,null,'raw')) $storeData[$alias]=''; + } + + public static function selectlist($field) + { + $value=$field->__get('value'); + if (empty($value) && (string) $value != '0') + { + return JHtml::_('users.value', $value); + } + else + { + $options=$field->getOptions(); + if(is_array($value)) + { + $result=array(); + foreach($options as $option) + { + if(in_array($option->value,$value)) $result[]=JText::_($option->text); + } + return implode(', ',$result); + } + else + { + $result=''; + foreach($options as $option) + { + if($option->value==$value) $result=JText::_($option->text); + } + return $result; + } + } + } + + public static function getSearchInput($field) + { + JHtml::_('formbehavior.chosen', 'select'); + $script = ''; + $selectedOptions=JFactory::getApplication()->input->get($field->alias,null,'raw'); + $options=array(); + $optTxt=explode("\n",$field->params->get('select_options','')); + //if(!$field->params->get('select_multiple',0)) $options[]=JHtml::_('select.option', '', JText::_('COM_JSN_NOSELECTION')); + foreach($optTxt as $opt) + { + $opt=trim($opt); + if($opt!=''){ + $opt=explode('|',$opt); + if(count($opt)==1) $options[]=JHtml::_('select.option', trim($opt[0]), JText::_(trim(htmlspecialchars($opt[0])))); + if(count($opt)==2) $options[]=JHtml::_('select.option', trim($opt[0]), JText::_(trim(htmlspecialchars($opt[1])))); + } + } + + $dbOptTable=$field->params->get('select_dbopttable',''); + $dbOptValue=$field->params->get('select_dboptvalue',''); + $dbOptText=$field->params->get('select_dbopttext',''); + $dbOptWhere=$field->params->get('select_dboptwhere',''); + $dbOptFilterColumn=$field->params->get('select_dboptfiltercolumn',''); + $dbOptFilterValue=$field->params->get('select_dboptfiltervalue',''); + if(!empty($dbOptTable) && !empty($dbOptValue) && !empty($dbOptText)) // set the alias of your field (width this conditions the select type work normally for all field except for this field) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + $query->select($dbOptValue.' AS value, '.$dbOptText.' AS text')->from($dbOptTable); + + if(!empty($dbOptWhere)) $query->where($dbOptWhere); + + + if(!empty($dbOptFilterColumn) && !empty($dbOptFilterValue)) + { + $script = JsnSelectlistFieldHelper::getAjaxScript($dbOptFilterValue,$field->alias,'jform_',true); + $optionParent=JFactory::getApplication()->input->get($dbOptFilterValue,'','raw'); + if(empty($optionParent)) + { + $query->where('FALSE'); + } + elseif(is_array($optionParent)) + { + $value=$optionParent; + foreach($value as &$val) + $val=$db->quote($val); + $value=implode(',',$value); + $query->where($dbOptFilterColumn.' IN ('.$value.')'); + } + else{ + $query->where($dbOptFilterColumn.' = '.$db->quote($optionParent)); + } + } + + $query->order('text'); + + $db->setQuery($query); + + try + { + $dbOptions = $db->loadObjectList(); + foreach($dbOptions as $option) + { + $options[]=JHtml::_('select.option', trim($option->value), JText::_(trim(htmlspecialchars($option->text)))); + } + } + catch (RuntimeException $e) + { + } + + + } + + $from=array(); + $to=array(); + //if($field->params->get('select_multiple',0)) + //{ + $return=JHtml::_('select.genericlist', $options, $field->alias.'[]', 'multiple="multiple"', 'value', 'text', null, 'jform_'.str_replace('-','_',$field->alias)); + + if($selectedOptions!=null) + { + foreach($selectedOptions as $selectedOption) + { + $from[]='value="'.$selectedOption.'"'; + $to[]='value="'.$selectedOption.'" selected="selected"'; + } + } + /*} + else + { + $return=JHtml::_('select.genericlist', $options, $field->alias, null, 'value', 'text', null, 'jform_'.str_replace('-','_',$field->alias)); + $from[]='value="'.$selectedOptions.'"'; + $to[]='value="'.$selectedOptions.'" selected="selected"'; + }*/ + + return str_replace($from,$to,$return).$script; + } + + public static function getSearchQuery($field, &$query) + { + $option=JFactory::getApplication()->input->get($field->alias,null,'raw'); + $db=JFactory::getDbo(); + //if($field->params->get('select_multiple',0)) + //{ + $where=''; + foreach($option as $opt) + { + $where.='b.'.$db->quoteName($field->alias).' LIKE '.$db->quote('%"'.$opt.'"%').' OR '.'b.'.$db->quoteName($field->alias).' = '.$db->quote($opt).' OR '; + } + $where=substr($where, 0,-4); + $query->where('('.$where.')'); + /*} + else + { + $query->where('b.'.$db->quoteName($field->alias).' = '.$db->quote($option)); + }*/ + + } + + public static function operations() + { + JFactory::getConfig()->set('gzip',false); + $db=JFactory::getDbo(); + $query=$db->getQuery(true); + $field=JFactory::getApplication()->input->get('field','','raw'); + $value=JFactory::getApplication()->input->get('value','','raw'); + $multi=(int) JFactory::getApplication()->input->get('multi',0,'raw'); + $query->select('params')->from('#__jsn_fields')->where('alias='.$db->quote($field)); + $params = new JRegistry; + $db->setQuery($query); + $params->loadString($db->loadResult()); + + JHtml::_('formbehavior.chosen', 'select'); + $options=array(); + $optTxt=explode("\n",$params->get('select_options','')); + if(!$params->get('select_multiple',0) && !$multi) $options[]=JHtml::_('select.option', '', JText::_('COM_JSN_NOSELECTION')); + foreach($optTxt as $opt) + { + $opt=trim($opt); + if($opt!=''){ + $opt=explode('|',$opt); + if(count($opt)==1) $options[]=JHtml::_('select.option', trim($opt[0]), JText::_(trim(htmlspecialchars($opt[0])))); + if(count($opt)==2) $options[]=JHtml::_('select.option', trim($opt[0]), JText::_(trim(htmlspecialchars($opt[1])))); + } + } + + $dbOptTable=$params->get('select_dbopttable',''); + $dbOptValue=$params->get('select_dboptvalue',''); + $dbOptText=$params->get('select_dbopttext',''); + $dbOptWhere=$params->get('select_dboptwhere',''); + if(!empty($value) && !empty($dbOptTable) && !empty($dbOptValue) && !empty($dbOptText)) // set the alias of your field (width this conditions the select type work normally for all field except for this field) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + $query->select($dbOptValue.' AS value, '.$dbOptText.' AS text')->from($dbOptTable); + + if(!empty($dbOptWhere)) $query->where($dbOptWhere); + + $select_dboptfiltercolumn=$params->get('select_dboptfiltercolumn',''); + if(!empty($select_dboptfiltercolumn) && !empty($value)) + { + $value = explode(',', $value); + + $filter_value = array(); + foreach($value as $v) + $filter_value[] = $db->quote($v); + + $where=$db->quoteName($params->get('select_dboptfiltercolumn','')).' IN ('.implode(',',$filter_value).')'; + + $query->where($where); + } + + $query->order('text'); + + $db->setQuery($query); + + try + { + $dbOptions = $db->loadObjectList(); + foreach($dbOptions as $option) + { + $options[]=JHtml::_('select.option', trim($option->value), JText::_(trim(htmlspecialchars($option->text)))); + } + } + catch (RuntimeException $e) + { + } + + + } + + echo json_encode($options); + + + } + + public static function getAjaxScript($parentField,$thisField,$prefix='jform_',$force_multiple = false) + { $rand=rand(0,10000); + if($force_multiple) $multi = '&multi=1'; + else $multi = '&multi=0'; + $script=' + '; + return $script; + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/selectlist.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/selectlist.xml new file mode 100644 index 00000000..01e8c99b --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/selectlist.xml @@ -0,0 +1,104 @@ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/text.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/text.php new file mode 100644 index 00000000..8e8316f4 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/text.php @@ -0,0 +1,118 @@ +quoteName($alias)." VARCHAR(255)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('text_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('text_defaultvalue','')).'"' : ''); + $maxlength=($item->params->get('text_maxlength','')!='' ? 'maxlength="'.$item->params->get('text_maxlength','').'"' : ''); + $placeholder=($item->params->get('text_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('text_placeholder','')).'"' : ''); + if($item->params->get('text_regex','')!='custom') $regex=($item->params->get('text_regex','')!='' ? 'class="validate-pattern '.$item->params->get('field_cssclass','').'" validate="regex" pattern="'.$item->params->get('text_regex','').'"' : 'class="'.$item->params->get('field_cssclass','').'"'); + else $regex='class="validate-pattern '.$item->params->get('field_cssclass','').'" validate="regex" pattern="'.$item->params->get('text_customregex','').'"'; + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + + $type='textfull'; + + $xml=''; + + $xml.=' + + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + description="'.JsnHelper::xmlentities(($item->description)).'" + size="30" + '.$defaultvalue.' + '.$maxlength.' + '.$placeholder.' + '.$regex.' + '.$readonly.' + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + message-regex="'.JsnHelper::xmlentities($item->params->get('text_messageregex','')).'" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=$user->$alias; + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=$data[$alias]; + } + + public static function getSearchInput($field) + { + $return=''; + return $return; + } + + public static function getSearchQuery($field, &$query) + { + $db=JFactory::getDbo(); + if($field->params->get('text_searchmode','like')=='like') $query->where('b.'.$db->quoteName($field->alias).' LIKE '.$db->quote('%'.JFactory::getApplication()->input->get($field->alias,null,'raw').'%')); + else $query->where('LOWER(b.'.$db->quoteName($field->alias).') = LOWER('.$db->quote(JFactory::getApplication()->input->get($field->alias,null,'raw')).')'); + } + + public static function editScript() + { + return ''; + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/text.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/text.xml new file mode 100644 index 00000000..4a2a245b --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/text.xml @@ -0,0 +1,76 @@ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/textarea.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/textarea.php new file mode 100644 index 00000000..016f94a9 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/textarea.php @@ -0,0 +1,118 @@ +quoteName($alias)." TEXT"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('textarea_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('textarea_defaultvalue','')).'"' : ''); + $maxlength=($item->params->get('textarea_maxlength','')!='' ? 'maxlength="'.$item->params->get('textarea_maxlength','').'"' : ''); + $type=$item->params->get('textarea_type','textarea'); + $placeholder=($item->params->get('textarea_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('textarea_placeholder','')).'"' : ''); + if($type=='textarea') $filter='filter="raw"'; + else $filter='filter="raw"'; + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + if(JFactory::getApplication()->input->get('option')=='com_jsn') $type='textarea'; + + $xml=''; + + $xml.=' + + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + '.$filter.' + '.$defaultvalue.' + '.$maxlength.' + '.$placeholder.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=$user->$alias; + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias])) $storeData[$alias]=$data[$alias]; + } + + public static function getSearchInput($field) + { + $return=''; + return $return; + } + + public static function getSearchQuery($field, &$query) + { + $db=JFactory::getDbo(); + $query->where('b.'.$db->quoteName($field->alias).' LIKE '.$db->quote('%'.JFactory::getApplication()->input->get($field->alias,null,'raw').'%')); + } + + public static function textarea($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + //if(JText::_(strip_tags($value)) != strip_tags($value)) $value=JText::_(strip_tags($value)); + if(substr_count($value,'

')==1 && substr_count($value,' ')==0) $text=JText::_(strip_tags($value)); + if(method_exists($field,'getAttribute') && $field->getAttribute('origintype')=='textarea') return str_replace("\n","
",htmlspecialchars($value)); + else return $value; + } + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/textarea.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/textarea.xml new file mode 100644 index 00000000..6a1605e0 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/textarea.xml @@ -0,0 +1,44 @@ + +

+ +
+ + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/usermail.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/usermail.php new file mode 100644 index 00000000..e3a1044d --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/usermail.php @@ -0,0 +1,131 @@ +isSite()) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $placeholder=($item->params->get('usermail_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('usermail_placeholder','')).'"' : ''); + $placeholder2=($item->params->get('usermail_placeholder2','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('usermail_placeholder2','')).'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $xml.=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + message="COM_USERS_PROFILE_EMAIL1_MESSAGE" + required="true" + size="30" + unique="true" + validate="email" + '.$placeholder.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + /> + + + '; + $config = JComponentHelper::getParams('com_jsn'); + if($config->get('confirmusermail',0)) + { + $xml.=' + '.JText::_('COM_USERS_PROFILE_EMAIL2_LABEL').'') : 'COM_USERS_PROFILE_EMAIL2_LABEL').'" + message="COM_USERS_PROFILE_EMAIL2_MESSAGE" + required="true" + size="30" + validate="equals" + '.$placeholder2.' + '.$readonly.' + /> + '; + } + } + else{ + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + $placeholder=($item->params->get('usermail_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('usermail_placeholder','')).'"' : ''); + $xml.=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + required="true" + size="30" + validate="email" + '.$placeholder.' + /> + '; + } + return $xml; + } + + public static function loadData($field, $user, &$data) + { + + } + + public static function storeData($field, $data, &$storeData) + { + + } + + public static function getSearchInput($field) + { + $return=''; + return $return; + } + + public static function getSearchQuery($field, &$query) + { + $db=JFactory::getDbo(); + $query->where('a.'.$db->quoteName('email').' LIKE '.$db->quote('%'.JFactory::getApplication()->input->get('email',null,'raw').'%')); + } + + public static function usermail($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + JPluginHelper::importPlugin('content'); + return JHtml::_('content.prepare', ''.$value.'', '', 'jsn_content.content'); + } + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/usermail.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/usermail.xml new file mode 100644 index 00000000..22063f1f --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/usermail.xml @@ -0,0 +1,27 @@ + +
+ +
+ + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/username.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/username.php new file mode 100644 index 00000000..e12da805 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/username.php @@ -0,0 +1,97 @@ +isSite()) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $placeholder=($item->params->get('username_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('username_placeholder','')).'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + if($item->params->get('username_regex','')!='custom') $regex=($item->params->get('username_regex','')!='' ? 'class="validate-pattern '.$item->params->get('field_cssclass','').'" pattern="'.$item->params->get('username_regex','').'"' : 'class="validate-username '.$item->params->get('field_cssclass','').'"'); + else $regex='class="validate-pattern '.$item->params->get('field_cssclass','').'" pattern="'.$item->params->get('username_customregex','').'"'; + + $xml=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + message="COM_USERS_PROFILE_USERNAME_MESSAGE" + required="true" + '.$placeholder.' + '.$readonly.' + size="30" + validate="username" + message-regex="'.JsnHelper::xmlentities($item->params->get('username_messageregex','')).'" + /> + '; + } + else{ + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + $placeholder=($item->params->get('username_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('username_placeholder','')).'"' : ''); + $xml=' + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + required="true" + size="30" + '.$placeholder.' + class="'.$item->params->get('field_cssclass','').'" + /> + '; + } + return $xml; + } + + public static function loadData($field, $user, &$data) + { + + } + + public static function storeData($field, $data, &$storeData) + { + + } + + public static function getSearchInput($field) + { + $return=''; + return $return; + } + + public static function getSearchQuery($field, &$query) + { + $db=JFactory::getDbo(); + if($field->params->get('username_searchmode','like')=='like') $query->where('a.'.$db->quoteName('username').' LIKE '.$db->quote('%'.JFactory::getApplication()->input->get('username',null,'raw').'%')); + else $query->where('LOWER(a.'.$db->quoteName('username').') = LOWER('.$db->quote(JFactory::getApplication()->input->get('username',null,'raw')).')'); + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/username.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/username.xml new file mode 100644 index 00000000..e2bdbc5e --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/username.xml @@ -0,0 +1,62 @@ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/video.php b/deployed/jsn/administrator/components/com_jsn/helpers/fields/video.php new file mode 100644 index 00000000..88c99f31 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/video.php @@ -0,0 +1,124 @@ +quoteName($alias)." VARCHAR(255)"; + $db->setQuery($query); + $db->query(); + } + + public static function delete($alias) + { + $db = JFactory::getDbo(); + $query = "ALTER TABLE #__jsn_users DROP COLUMN ".$db->quoteName($alias); + $db->setQuery($query); + $db->query(); + } + + public static function getXml($item) + { + require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + $hideTitle= ($item->params->get('hidetitle',0) && JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn') || ($item->params->get('hidetitleedit',0) && (JFactory::getApplication()->input->get('layout','')=='edit' || JFactory::getApplication()->input->get('view','')=='registration')); + if(JFactory::getApplication()->input->get('view','profile')=='profile' && JFactory::getApplication()->input->get('option','')=='com_jsn' && $item->params->get('titleprofile','')!='') $item->title=$item->params->get('titleprofile',''); + $defaultvalue=($item->params->get('video_defaultvalue','')!='' ? 'default="'.JsnHelper::xmlentities($item->params->get('video_defaultvalue','')).'"' : ''); + $maxlength=($item->params->get('video_maxlength','')!='' ? 'maxlength="'.$item->params->get('video_maxlength','').'"' : ''); + $placeholder=($item->params->get('video_placeholder','')!='' ? 'hint="'.JsnHelper::xmlentities($item->params->get('video_placeholder','')).'"' : ''); + + if($item->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + elseif($item->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('view')!='registration' && JFactory::getApplication()->isSite()) $readonly='readonly="true"'; + else $readonly=''; + + $type='video'; + + $xml=''; + + $xml.=' + + '.JText::_($item->title).'') : JsnHelper::xmlentities($item->title)).'" + size="30" + '.$defaultvalue.' + '.$maxlength.' + '.$placeholder.' + '.$readonly.' + class="'.$item->params->get('field_cssclass','').'" + required="'.($item->required ? ($item->required==2 ? 'admin' : 'frontend' ) : 'false' ).'" + /> + '; + return $xml; + } + + public static function loadData($field, $user, &$data) + { + $alias=$field->alias; + if(isset($user->$alias)) $data->$alias=$user->$alias; + if(isset($user->$alias) && $data->$alias=='http://') $data->$alias=''; + } + + public static function storeData($field, $data, &$storeData) + { + //if($field->params->get('field_readonly','')==1 && JFactory::getApplication()->isSite()) return; + //if($field->params->get('field_readonly','')==2 && JFactory::getApplication()->input->get('task')=='profile.save' && JFactory::getApplication()->isSite()) return; + $alias=$field->alias; + if(isset($data[$alias])){ + if(substr(trim($data[$alias]), 0, 4)=='http') $storeData[$alias]=$data[$alias]; + else $storeData[$alias]='http://'.$data[$alias]; + } + if(isset($data[$alias]) && $storeData[$alias]=='http://') $storeData[$alias]=''; + } + + public static function video($field) + { + $value=$field->__get('value'); + if (empty($value)) + { + return JHtml::_('users.value', $value); + } + else + { + if(strpos(' '.$value,'vimeo')>1) + { + $value=substr($value,strrpos($value,'/')+1); + return ''; + } + $value=substr($value,strrpos($value,'/')+1); + if(strrpos($value,'?v=')) $value=substr($value,strrpos($value,'?v=')+3); + return ''; + } + } + + public static function getSearchInput($field) + { + $return=''; + return $return; + } + + public static function getSearchQuery($field, &$query) + { + $db=JFactory::getDbo(); + $query->where('b.'.$db->quoteName($field->alias).' LIKE '.$db->quote('%'.JFactory::getApplication()->input->get($field->alias,null,'raw').'%')); + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/fields/video.xml b/deployed/jsn/administrator/components/com_jsn/helpers/fields/video.xml new file mode 100644 index 00000000..a555925f --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/fields/video.xml @@ -0,0 +1,34 @@ + +
+ +
+ + + + + + + +
+
+
\ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/html/field.php b/deployed/jsn/administrator/components/com_jsn/helpers/html/field.php new file mode 100644 index 00000000..57049ce8 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/html/field.php @@ -0,0 +1,181 @@ + array( + 'required_unpublish', + '', + '', + '', + false, + 'publish', + 'publish' + ), + 1 => array( + 'required_unpublish', + '', + '', + '', + false, + 'publish icon-star', + 'publish' + ), + 0 => array( + 'required_publish', + '', + '', + '', + false, + 'unpublish', + 'unpublish' + ), + ); + + return JHtml::_('jgrid.state', $states, $value, $i, 'fields.', $enabled, true, $checkbox); + } + + public static function core($value, $i, $enabled = false, $checkbox = 'cb') + { + $states = array( + 1 => array( + '', + '', + '', + '', + false, + 'publish', + 'publish' + ), + 0 => array( + '', + '', + '', + '', + false, + 'unpublish', + 'unpublish' + ), + ); + + return JHtml::_('jgrid.state', $states, $value, $i, 'fields.', $enabled, true, $checkbox); + } + + public static function profile($value, $i, $enabled = true, $checkbox = 'cb') + { + $states = array( + 1 => array( + 'profile_unpublish', + '', + '', + '', + false, + 'publish', + 'publish' + ), + 0 => array( + 'profile_publish', + '', + '', + '', + false, + 'unpublish', + 'unpublish' + ), + ); + + return JHtml::_('jgrid.state', $states, $value, $i, 'fields.', $enabled, true, $checkbox); + } + + public static function edit($value, $i, $enabled = true, $checkbox = 'cb') + { + $states = array( + 1 => array( + 'edit_unpublish', + '', + '', + '', + false, + 'publish', + 'publish' + ), + 0 => array( + 'edit_publish', + '', + '', + '', + false, + 'unpublish', + 'unpublish' + ), + ); + + return JHtml::_('jgrid.state', $states, $value, $i, 'fields.', $enabled, true, $checkbox); + } + + public static function register($value, $i, $enabled = true, $checkbox = 'cb') + { + $states = array( + 1 => array( + 'register_unpublish', + '', + '', + '', + false, + 'publish', + 'publish' + ), + 0 => array( + 'register_publish', + '', + '', + '', + false, + 'unpublish', + 'unpublish' + ), + ); + + return JHtml::_('jgrid.state', $states, $value, $i, 'fields.', $enabled, true, $checkbox); + } + + public static function search($value, $i, $enabled = true, $checkbox = 'cb') + { + $states = array( + 1 => array( + 'search_unpublish', + '', + '', + '', + false, + 'publish', + 'publish' + ), + 0 => array( + 'search_publish', + '', + '', + '', + false, + 'unpublish', + 'unpublish' + ), + ); + + return JHtml::_('jgrid.state', $states, $value, $i, 'fields.', $enabled, true, $checkbox); + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/html/jsnbatch.php b/deployed/jsn/administrator/components/com_jsn/helpers/html/jsnbatch.php new file mode 100644 index 00000000..16604e19 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/html/jsnbatch.php @@ -0,0 +1,100 @@ + '.modal-body')); + + // Create the batch selector to change an access level on a selection list. + return + '' + . JHtml::_( + 'access.assetgrouplist', + 'batch[assetgroup_id]', '', + 'class="inputbox"', + array( + 'title' => JText::_('JNONE'), + 'id' => 'batch-access' + ) + ); + } + + public static function accessview() + { + JHtml::_('bootstrap.tooltip', '.modalTooltip', array('container' => '.modal-body')); + + // Create the batch selector to change an access level on a selection list. + return + '' + . JHtml::_( + 'access.assetgrouplist', + 'batch[assetgroupview_id]', '', + 'class="inputbox"', + array( + 'title' => JText::_('JNONE'), + 'id' => 'batch-accessview' + ) + ); + } + + public static function fieldgroup() + { + JHtml::_('bootstrap.tooltip', '.modalTooltip', array('container' => '.modal-body')); + + // Create the batch selector to change an access level on a selection list. + $dataArray=array('0'=>JText::_('JNONE')); + $db=JFactory::getDbo(); + $query=$db->getQuery(true); + $query->select('id, title')->from('#__jsn_fields')->where('level=1 AND published=1'); + $db->setQuery($query); + $results=$db->loadAssocList('id', 'title'); + foreach($results as $k => $v) + { + $dataArray[$k]=JText::_($v); + } + return + '' + . JHtml::_( + 'select.genericlist',$dataArray, + 'batch[fieldgroup_id]', + array( + 'id' => 'batch-fieldgroup' + ) + ); + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/html/users.php b/deployed/jsn/administrator/components/com_jsn/helpers/html/users.php new file mode 100644 index 00000000..ea78ddce --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/html/users.php @@ -0,0 +1,12 @@ +addScriptDeclaration("(function($){ + $('#$selector a').click(function (e) + { + e.preventDefault(); + $(this).tab('show'); + }); + })(jQuery);"); + + // Set static array + self::$loaded[__METHOD__][$sig] = true; + self::$loaded[__METHOD__][$selector]['active'] = $opt['active']; + } + + $html = ' +
'; + + return $html; + } + + public static function endTabSet() + { + $html = '
'; + + return $html; + } + + public static function addTab($selector, $id, $title) + { + static $tabScriptLayout = null; + static $tabLayout = null; + + $tabScriptLayout = is_null($tabScriptLayout) ? new JLayoutFile('addtabscript') : $tabScriptLayout; + $tabLayout = is_null($tabLayout) ? new JLayoutFile('addtab') : $tabLayout; + + $active = (self::$loaded['JHtmlBootstrapJ30::startTabSet'][$selector]['active'] == $id) ? ' active' : ''; + + // Inject tab into UL + JFactory::getDocument() + ->addScriptDeclaration("(function($){ + $(document).ready(function() { + // Handler for .ready() called. + var tab = $('
  • $title
  • '); + $('#" . $selector . "Tabs').append(tab); + }); + })(jQuery);"); + + $html = '
    '; + + return $html; + } + + public static function endTab() + { + $html = '
    '; + + return $html; + } + +} + +?> diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/j30/rule/notequals.php b/deployed/jsn/administrator/components/com_jsn/helpers/j30/rule/notequals.php new file mode 100644 index 00000000..ee0862cb --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/j30/rule/notequals.php @@ -0,0 +1,68 @@ + tag for the form field object. + * @param mixed $value The form field value to validate. + * @param string $group The field name group control value. This acts as as an array container for the field. + * For example if the field has name="foo" and the group value is set to "bar" then the + * full field name would end up being "bar[foo]". + * @param JRegistry $input An optional JRegistry object with the entire data set to validate against the entire form. + * @param JForm $form The form object for which the field is being tested. + * + * @return boolean True if the value is valid, false otherwise. + * + * @since 11.1 + * @throws InvalidArgumentException + * @throws UnexpectedValueException + */ + public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null) + { + $field = (string) $element['field']; + + // Check that a validation field is set. + if (!$field) + { + throw new UnexpectedValueException(sprintf('$field empty in %s::test', get_class($this))); + } + + if (is_null($form)) + { + throw new InvalidArgumentException(sprintf('The value for $form must not be null in %s', get_class($this))); + } + + if (is_null($input)) + { + throw new InvalidArgumentException(sprintf('The value for $input must not be null in %s', get_class($this))); + } + + // Test the two values against each other. + if ($value != $input->get($field)) + { + return true; + } + + return false; + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/jsn.php b/deployed/jsn/administrator/components/com_jsn/helpers/jsn.php new file mode 100644 index 00000000..f7acfcb1 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/jsn.php @@ -0,0 +1,252 @@ +authorise('core.admin.import', 'com_jsn')){ + JHtmlSidebar::addEntry( + JText::_('COM_JSN_IMPORT_USERS'), + 'index.php?option=com_jsn&view=import' + ); + } + + + $parts = explode('.', $extension); + $component = $parts[0]; + + if (count($parts) > 1) + { + $section = $parts[1]; + } + + // Try to find the component helper. + $file = JPath::clean(JPATH_ADMINISTRATOR . '/components/com_jsn/helpers/jsn.php'); + + if (file_exists($file)) + { + require_once $file; + + $cName = 'JsnHelperAdmin'; + + if (class_exists($cName)) + { + if (is_callable(array($cName, 'addSubmenu'))) + { + $lang = JFactory::getLanguage(); + // loading language file from the administrator/language directory then + // loading language file from the administrator/components/*extension*/language directory + $lang->load($component, JPATH_BASE, null, false, false) + || $lang->load($component, JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component), null, false, false) + || $lang->load($component, JPATH_BASE, $lang->getDefault(), false, false) + || $lang->load($component, JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component), $lang->getDefault(), false, false); + + } + } + } + } + + /** + * Gets a list of the actions that can be performed. + * + * @return JObject + * + * @since 3.1 + */ + public static function getActions() + { + $user = JFactory::getUser(); + $result = new JObject; + + $assetName = 'com_jsn'; + $level = 'component'; + $actions = JAccess::getActions('com_jsn', $level); + + foreach ($actions as $action) + { + $result->set($action->name, $user->authorise($action->name, $assetName)); + } + + return $result; + } + + /*public static function excludeFromProfile($data){ + $db=JFactory::getDbo(); + $query = $db->getQuery(true); + $query->select('a.*')->from('#__jsn_fields AS a')->where('a.level = 2')->where('a.published = 1')->order($db->escape('a.lft') . ' ASC'); + $db->setQuery( $query ); + $fields = $db->loadObjectList('alias'); + $userData=$data; + $excludeFromProfile=array(); + foreach($fields as $field) + { + // Load Options + $registry = new JRegistry; + $registry->loadString($field->params); + $field->params = $registry->toArray(); + + $condition_suffix=array('','1','2','3','4'); + foreach($condition_suffix as $suffix) + { + if(isset($field->params['condition_operator'.$suffix]) && $field->params['condition_operator'.$suffix]!=0 && count($field->params['condition_hide'.$suffix])>0){ + if($field->params['condition_field'.$suffix]=='_custom') $value=$field->params['condition_custom'.$suffix]; + else + { + $alias=$field->params['condition_field'.$suffix]; + if(isset($userData->$alias)) $value=$userData->$alias; + else $value=''; + if(is_array($value)) $value=implode(',',$value); + } + $alias=$field->alias; + if(!isset($userData->$alias)) $userData->$alias=''; + + if(is_array($userData->$alias)) + { + foreach($userData->$alias as $userValue) + { + switch($field->params['condition_operator'.$suffix]) + { + case 1: + if($userValue==$value) + { + foreach($field->params['condition_hide'.$suffix] as $fieldToHide) + { + $excludeFromProfile[]='jform['.$fieldToHide.']'; + } + } + break; + case 2: + if($userValue>$value) + { + foreach($field->params['condition_hide'.$suffix] as $fieldToHide) + { + $excludeFromProfile[]='jform['.$fieldToHide.']'; + } + } + break; + case 3: + if($userValue<$value) + { + foreach($field->params['condition_hide'.$suffix] as $fieldToHide) + { + $excludeFromProfile[]='jform['.$fieldToHide.']'; + } + } + break; + case 4: + if(strpos(' '.$userValue,$value)>0) + { + foreach($field->params['condition_hide'.$suffix] as $fieldToHide) + { + $excludeFromProfile[]='jform['.$fieldToHide.']'; + } + } + break; + case 5: + if($userValue!=$value) + { + foreach($field->params['condition_hide'.$suffix] as $fieldToHide) + { + $excludeFromProfile[]='jform['.$fieldToHide.']'; + } + } + break; + } + } + } + else + { + switch($field->params['condition_operator'.$suffix]) + { + case 1: + if($userData->$alias==$value) + { + foreach($field->params['condition_hide'.$suffix] as $fieldToHide) + { + $excludeFromProfile[]='jform['.$fieldToHide.']'; + } + } + break; + case 2: + if($userData->$alias>$value) + { + foreach($field->params['condition_hide'.$suffix] as $fieldToHide) + { + $excludeFromProfile[]='jform['.$fieldToHide.']'; + } + } + break; + case 3: + if($userData->$alias<$value) + { + foreach($field->params['condition_hide'.$suffix] as $fieldToHide) + { + $excludeFromProfile[]='jform['.$fieldToHide.']'; + } + } + break; + case 4: + if(strpos(' '.$userData->$alias,$value)>0) + { + foreach($field->params['condition_hide'.$suffix] as $fieldToHide) + { + $excludeFromProfile[]='jform['.$fieldToHide.']'; + } + } + break; + case 5: + if($userData->$alias!=$value) + { + foreach($field->params['condition_hide'.$suffix] as $fieldToHide) + { + $excludeFromProfile[]='jform['.$fieldToHide.']'; + } + } + break; + } + } + } + } + } + return $excludeFromProfile; + }*/ + +} diff --git a/deployed/jsn/administrator/components/com_jsn/helpers/trigger_com_config.php b/deployed/jsn/administrator/components/com_jsn/helpers/trigger_com_config.php new file mode 100644 index 00000000..30e3a187 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/helpers/trigger_com_config.php @@ -0,0 +1,61 @@ +get('namestyle', 'FIRSTNAME_LASTNAME')){ + case 'FIRSTNAME_LASTNAME': + $unpublish=array($db->quote('secondname')); + $publish=array($db->quote('firstname'),$db->quote('lastname')); + break; + case 'FIRSTNAME_SECONDNAME_LASTNAME': + $unpublish=array(); + $publish=array($db->quote('firstname'),$db->quote('lastname'),$db->quote('secondname')); + break; + case 'FIRSTNAME': + $unpublish=array($db->quote('secondname'),$db->quote('lastname')); + $publish=array($db->quote('firstname')); + break; + } + if(count($unpublish)>0) + { + $query = $db->getQuery(true); + $query->update("#__jsn_fields"); + $query->set($db->quoteName('published').' = 0'); + $query->where('alias IN ('. implode(', ',$unpublish) .')'); + $db->setQuery($query); + $db->execute(); + } + if(count($publish)>0) + { + $query = $db->getQuery(true); + $query->update("#__jsn_fields"); + $query->set($db->quoteName('published').' = 1'); + $query->where('alias IN ('. implode(', ',$publish) .')'); + $db->setQuery($query); + $db->execute(); + } + + + $query = $db->getQuery(true); + $query->update("#__jsn_fields"); + $query->set($db->quoteName('published').' = '. ($config->get('avatar', 1) ? 1 : 0) ); + $query->where('alias = '.$db->quote('avatar')); + $db->setQuery($query); + $db->execute(); + + +} +onConfigurationBeforeSave(); +?> \ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/install.jsn.php b/deployed/jsn/administrator/components/com_jsn/install.jsn.php new file mode 100644 index 00000000..db2e9f0d --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/install.jsn.php @@ -0,0 +1,864 @@ +setQuery($query); + $db->execute(); + $query ="UPDATE `#__jsn_fields` SET `edit`=1 WHERE `level`=2 AND `params` NOT LIKE '%\"hideonedit\":\"1\"%'"; + $db->setQuery($query); + $db->execute(); + $query ="UPDATE `#__jsn_fields` SET `alias`='registerdate',`path`='default/registerdate',`edit`='0' WHERE `id`=10"; + $db->setQuery($query); + $db->execute(); + $query ="UPDATE `#__jsn_fields` SET `edit`='0' WHERE `id`=11"; + $db->setQuery($query); + $db->execute(); + } + catch (Exception $e) { } + + // Add Column for versions 1.2.x to 1.3.x + try { + $query ="ALTER TABLE `#__jsn_fields` ADD `accessview` int(10) unsigned NOT NULL DEFAULT '0'"; + $db->setQuery($query); + $db->execute(); + $query ="UPDATE `#__jsn_fields` SET `accessview`=1;"; + $db->setQuery($query); + $db->execute(); + } + catch (Exception $e) { } + + // Remove Old Broken Package reference + try { + $query ="DELETE FROM `#__extensions` WHERE `element` = 'pkg_pkg_jsn'"; + $db->setQuery($query); + $db->execute(); + } + catch (Exception $e) { } + + // Add Column Instagram_id for versions 2.0.x to 2.1.x + try { + $query ="ALTER TABLE `#__jsn_users` MODIFY COLUMN `facebook_id` varchar(200) NOT NULL"; + $db->setQuery($query); + $db->execute(); + $query ="ALTER TABLE `#__jsn_users` ADD `instagram_id` varchar(50) NOT NULL"; + $db->setQuery($query); + $db->execute(); + } + catch (Exception $e) { } + + // Fix root record in #__jsn_fields table + try { + $query ="UPDATE `#__jsn_fields` SET `published` = 1 WHERE `id` = 1"; + $db->setQuery($query); + $db->execute(); + } + catch (Exception $e) { } + + // Firstname and Lastname need to be required also in backend + try { + $query ="UPDATE `#__jsn_fields` SET `required` = 2 WHERE `id` IN (4,6)"; + $db->setQuery($query); + $db->execute(); + } + catch (Exception $e) { } + + // Add Column Conditions for versions 2.3+ + try { + + $query ="ALTER TABLE `#__jsn_fields` ADD `conditions` text NOT NULL"; + $db->setQuery($query); + $db->execute(); + + // Convert old conditions to new system + $query = 'SELECT * FROM #__jsn_fields'; + $db->setQuery($query); + $fields = $db->loadObjectList('alias'); + foreach($fields as $field) + { + if(empty($field->params)) continue; + + $params=json_decode($field->params); + if(!isset($params->condition_operator)) continue; + + $conditions=array(); + // Condition 0 + if($params->condition_operator > 0){ + if(!empty($params->condition_hide)){ + $c = new stdClass(); + $c->operator = $params->condition_operator; + $c->to = $params->condition_field; + $c->custom_value = $params->condition_custom; + $c->action = ($params->condition_action=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide; + $c->two_ways = $params->condition_twoways; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups)){ + $c = new stdClass(); + $c->operator = $params->condition_operator; + $c->to = $params->condition_field; + $c->custom_value = $params->condition_custom; + $c->action = ($params->condition_ugaction=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups; + $c->two_ways = $params->condition_twoways; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 1 + if($params->condition_operator1 > 0){ + if(!empty($params->condition_hide1)){ + $c = new stdClass(); + $c->operator = $params->condition_operator1; + $c->to = $params->condition_field1; + $c->custom_value = $params->condition_custom1; + $c->action = ($params->condition_action1=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide1; + $c->two_ways = $params->condition_twoways1; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups1)){ + $c = new stdClass(); + $c->operator = $params->condition_operator1; + $c->to = $params->condition_field1; + $c->custom_value = $params->condition_custom1; + $c->action = ($params->condition_ugaction1=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups1; + $c->two_ways = $params->condition_twoways1; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 2 + if($params->condition_operator2 > 0){ + if(!empty($params->condition_hide2)){ + $c = new stdClass(); + $c->operator = $params->condition_operator2; + $c->to = $params->condition_field2; + $c->custom_value = $params->condition_custom2; + $c->action = ($params->condition_action2=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide2; + $c->two_ways = $params->condition_twoways2; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups2)){ + $c = new stdClass(); + $c->operator = $params->condition_operator2; + $c->to = $params->condition_field2; + $c->custom_value = $params->condition_custom2; + $c->action = ($params->condition_ugaction2=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups2; + $c->two_ways = $params->condition_twoways2; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 3 + if($params->condition_operator3 > 0){ + if(!empty($params->condition_hide3)){ + $c = new stdClass(); + $c->operator = $params->condition_operator3; + $c->to = $params->condition_field3; + $c->custom_value = $params->condition_custom3; + $c->action = ($params->condition_action3=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide3; + $c->two_ways = $params->condition_twoways3; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups3)){ + $c = new stdClass(); + $c->operator = $params->condition_operator3; + $c->to = $params->condition_field3; + $c->custom_value = $params->condition_custom3; + $c->action = ($params->condition_ugaction3=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups3; + $c->two_ways = $params->condition_twoways3; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 4 + if($params->condition_operator4 > 0){ + if(!empty($params->condition_hide4)){ + $c = new stdClass(); + $c->operator = $params->condition_operator4; + $c->to = $params->condition_field4; + $c->custom_value = $params->condition_custom4; + $c->action = ($params->condition_action4=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide4; + $c->two_ways = $params->condition_twoways4; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups4)){ + $c = new stdClass(); + $c->operator = $params->condition_operator4; + $c->to = $params->condition_field4; + $c->custom_value = $params->condition_custom4; + $c->action = ($params->condition_ugaction4=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups4; + $c->two_ways = $params->condition_twoways4; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 5 + if($params->condition_operator5 > 0){ + if(!empty($params->condition_hide5)){ + $c = new stdClass(); + $c->operator = $params->condition_operator5; + $c->to = $params->condition_field5; + $c->custom_value = $params->condition_custom5; + $c->action = ($params->condition_action5=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide5; + $c->two_ways = $params->condition_twoways5; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups5)){ + $c = new stdClass(); + $c->operator = $params->condition_operator5; + $c->to = $params->condition_field5; + $c->custom_value = $params->condition_custom5; + $c->action = ($params->condition_ugaction5=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups5; + $c->two_ways = $params->condition_twoways5; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 6 + if($params->condition_operator6 > 0){ + if(!empty($params->condition_hide6)){ + $c = new stdClass(); + $c->operator = $params->condition_operator6; + $c->to = $params->condition_field6; + $c->custom_value = $params->condition_custom6; + $c->action = ($params->condition_action6=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide6; + $c->two_ways = $params->condition_twoways6; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups6)){ + $c = new stdClass(); + $c->operator = $params->condition_operator6; + $c->to = $params->condition_field6; + $c->custom_value = $params->condition_custom6; + $c->action = ($params->condition_ugaction6=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups6; + $c->two_ways = $params->condition_twoways6; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 7 + if($params->condition_operator7 > 0){ + if(!empty($params->condition_hide7)){ + $c = new stdClass(); + $c->operator = $params->condition_operator7; + $c->to = $params->condition_field7; + $c->custom_value = $params->condition_custom7; + $c->action = ($params->condition_action7=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide7; + $c->two_ways = $params->condition_twoways7; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups7)){ + $c = new stdClass(); + $c->operator = $params->condition_operator7; + $c->to = $params->condition_field7; + $c->custom_value = $params->condition_custom7; + $c->action = ($params->condition_ugaction7=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups7; + $c->two_ways = $params->condition_twoways7; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 8 + if($params->condition_operator8 > 0){ + if(!empty($params->condition_hide8)){ + $c = new stdClass(); + $c->operator = $params->condition_operator8; + $c->to = $params->condition_field8; + $c->custom_value = $params->condition_custom8; + $c->action = ($params->condition_action8=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide8; + $c->two_ways = $params->condition_twoways8; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups8)){ + $c = new stdClass(); + $c->operator = $params->condition_operator8; + $c->to = $params->condition_field8; + $c->custom_value = $params->condition_custom8; + $c->action = ($params->condition_ugaction8=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups8; + $c->two_ways = $params->condition_twoways8; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 9 + if($params->condition_operator9 > 0){ + if(!empty($params->condition_hide9)){ + $c = new stdClass(); + $c->operator = $params->condition_operator9; + $c->to = $params->condition_field9; + $c->custom_value = $params->condition_custom9; + $c->action = ($params->condition_action9=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide9; + $c->two_ways = $params->condition_twoways9; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups9)){ + $c = new stdClass(); + $c->operator = $params->condition_operator9; + $c->to = $params->condition_field9; + $c->custom_value = $params->condition_custom9; + $c->action = ($params->condition_ugaction9=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups9; + $c->two_ways = $params->condition_twoways9; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 10 + if($params->condition_operator10 > 0){ + if(!empty($params->condition_hide10)){ + $c = new stdClass(); + $c->operator = $params->condition_operator10; + $c->to = $params->condition_field10; + $c->custom_value = $params->condition_custom10; + $c->action = ($params->condition_action10=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide10; + $c->two_ways = $params->condition_twoways10; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups10)){ + $c = new stdClass(); + $c->operator = $params->condition_operator10; + $c->to = $params->condition_field10; + $c->custom_value = $params->condition_custom10; + $c->action = ($params->condition_ugaction10=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups10; + $c->two_ways = $params->condition_twoways10; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 11 + if($params->condition_operator11 > 0){ + if(!empty($params->condition_hide11)){ + $c = new stdClass(); + $c->operator = $params->condition_operator11; + $c->to = $params->condition_field11; + $c->custom_value = $params->condition_custom11; + $c->action = ($params->condition_action11=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide11; + $c->two_ways = $params->condition_twoways11; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups11)){ + $c = new stdClass(); + $c->operator = $params->condition_operator11; + $c->to = $params->condition_field11; + $c->custom_value = $params->condition_custom11; + $c->action = ($params->condition_ugaction11=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups11; + $c->two_ways = $params->condition_twoways11; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 12 + if($params->condition_operator12 > 0){ + if(!empty($params->condition_hide12)){ + $c = new stdClass(); + $c->operator = $params->condition_operator12; + $c->to = $params->condition_field12; + $c->custom_value = $params->condition_custom12; + $c->action = ($params->condition_action12=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide12; + $c->two_ways = $params->condition_twoways12; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups12)){ + $c = new stdClass(); + $c->operator = $params->condition_operator12; + $c->to = $params->condition_field12; + $c->custom_value = $params->condition_custom12; + $c->action = ($params->condition_ugaction12=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups12; + $c->two_ways = $params->condition_twoways12; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 13 + if($params->condition_operator13 > 0){ + if(!empty($params->condition_hide13)){ + $c = new stdClass(); + $c->operator = $params->condition_operator13; + $c->to = $params->condition_field13; + $c->custom_value = $params->condition_custom13; + $c->action = ($params->condition_action13=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide13; + $c->two_ways = $params->condition_twoways13; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups13)){ + $c = new stdClass(); + $c->operator = $params->condition_operator13; + $c->to = $params->condition_field13; + $c->custom_value = $params->condition_custom13; + $c->action = ($params->condition_ugaction13=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups13; + $c->two_ways = $params->condition_twoways13; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 14 + if($params->condition_operator14 > 0){ + if(!empty($params->condition_hide14)){ + $c = new stdClass(); + $c->operator = $params->condition_operator14; + $c->to = $params->condition_field14; + $c->custom_value = $params->condition_custom14; + $c->action = ($params->condition_action14=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide14; + $c->two_ways = $params->condition_twoways14; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups14)){ + $c = new stdClass(); + $c->operator = $params->condition_operator14; + $c->to = $params->condition_field14; + $c->custom_value = $params->condition_custom14; + $c->action = ($params->condition_ugaction14=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups14; + $c->two_ways = $params->condition_twoways14; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 15 + if($params->condition_operator15 > 0){ + if(!empty($params->condition_hide15)){ + $c = new stdClass(); + $c->operator = $params->condition_operator15; + $c->to = $params->condition_field15; + $c->custom_value = $params->condition_custom15; + $c->action = ($params->condition_action15=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide15; + $c->two_ways = $params->condition_twoways15; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups15)){ + $c = new stdClass(); + $c->operator = $params->condition_operator15; + $c->to = $params->condition_field15; + $c->custom_value = $params->condition_custom15; + $c->action = ($params->condition_ugaction15=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups15; + $c->two_ways = $params->condition_twoways15; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 16 + if($params->condition_operator16 > 0){ + if(!empty($params->condition_hide16)){ + $c = new stdClass(); + $c->operator = $params->condition_operator16; + $c->to = $params->condition_field16; + $c->custom_value = $params->condition_custom16; + $c->action = ($params->condition_action16=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide16; + $c->two_ways = $params->condition_twoways16; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups16)){ + $c = new stdClass(); + $c->operator = $params->condition_operator16; + $c->to = $params->condition_field16; + $c->custom_value = $params->condition_custom16; + $c->action = ($params->condition_ugaction16=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups16; + $c->two_ways = $params->condition_twoways16; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 17 + if($params->condition_operator17 > 0){ + if(!empty($params->condition_hide17)){ + $c = new stdClass(); + $c->operator = $params->condition_operator17; + $c->to = $params->condition_field17; + $c->custom_value = $params->condition_custom17; + $c->action = ($params->condition_action17=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide17; + $c->two_ways = $params->condition_twoways17; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups17)){ + $c = new stdClass(); + $c->operator = $params->condition_operator17; + $c->to = $params->condition_field17; + $c->custom_value = $params->condition_custom17; + $c->action = ($params->condition_ugaction17=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups17; + $c->two_ways = $params->condition_twoways17; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 18 + if($params->condition_operator18 > 0){ + if(!empty($params->condition_hide18)){ + $c = new stdClass(); + $c->operator = $params->condition_operator18; + $c->to = $params->condition_field18; + $c->custom_value = $params->condition_custom18; + $c->action = ($params->condition_action18=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide18; + $c->two_ways = $params->condition_twoways18; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups18)){ + $c = new stdClass(); + $c->operator = $params->condition_operator18; + $c->to = $params->condition_field18; + $c->custom_value = $params->condition_custom18; + $c->action = ($params->condition_ugaction18=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups18; + $c->two_ways = $params->condition_twoways18; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + // Condition 19 + if($params->condition_operator19 > 0){ + if(!empty($params->condition_hide19)){ + $c = new stdClass(); + $c->operator = $params->condition_operator19; + $c->to = $params->condition_field19; + $c->custom_value = $params->condition_custom19; + $c->action = ($params->condition_action19=='hide' ? 'fields_hide' : 'fields_show'); + $c->fields_target = $params->condition_hide19; + $c->two_ways = $params->condition_twoways19; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + if(!empty($params->condition_usergroups19)){ + $c = new stdClass(); + $c->operator = $params->condition_operator19; + $c->to = $params->condition_field19; + $c->custom_value = $params->condition_custom19; + $c->action = ($params->condition_ugaction19=='add' ? 'usergroups_add' : 'usergroups_remove'); + $c->usergroups_target = $params->condition_usergroups19; + $c->two_ways = $params->condition_twoways19; + if(empty($c->to)) $c->to = ''; + if(empty($c->custom_value)) $c->custom_value = ''; + if(empty($c->fields_target)) $c->fields_target = ''; + if(empty($c->two_ways)) $c->two_ways = 1; + $conditions[]=$c; + } + } + + if(count($conditions)){ + $conditions = json_encode($conditions); + $query ="UPDATE `#__jsn_fields` SET `conditions` = ".$db->quote($conditions)." WHERE id=".$field->id; + $db->setQuery($query); + $db->execute(); + } + } + } + catch (Exception $e) { } + + // Change Collation + try { + $query ="ALTER TABLE #__jsn_users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"; + $db->setQuery($query); + $db->execute(); + $query ="ALTER TABLE #__jsn_fields CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"; + $db->setQuery($query); + $db->execute(); + } + catch (Exception $e) { } + + // Joomla updater + /*$query=$db->getQuery(true); + $query->select('location')->from('#__update_sites')->where('`name`="Easy Profile"'); + $db->setQuery($query); + $updaterSiteId=$db->loadResult(); + + if($updaterSiteId==false) + { + $query='INSERT INTO #__update_sites(`name`,`type`,`location`,`enabled`) VALUES ("Easy Profile","extension","https://www.easy-profile.com/extension.xml",1)'; + $db->setQuery($query); + $db->execute(); + $updaterSiteId = $db->insertid(); + } + + $query=$db->getQuery(true); + $query->select('extension_id')->from('#__extensions')->where('`name`="com_jsn"'); + $db->setQuery($query); + $updaterExtensionId= $db->loadResult(); + + try { + $query='INSERT INTO #__update_sites_extensions(`update_site_id`,`extension_id`) VALUES ('.$updaterSiteId.','.$updaterExtensionId.')'; + $db->setQuery($query); + $db->execute(); + } + catch (Exception $e) { }*/ + + // Plugin enable + $query=$db->getQuery(true); + $query->update('#__extensions')->set($db->quoteName('enabled').'=1') + ->where($db->quoteName('element').' IN ('. + $db->quote('jsn_author').','. + $db->quote('jsn_auth').','. + $db->quote('jsn_system').','. + $db->quote('jsn_content').','. + $db->quote('jsn_users').','. + $db->quote('usergroups').','. + $db->quote('ajaxuserlist').','. + $db->quote('socialconnect').')'); + $db->setQuery($query); + + $result = $db->query(); + + $lang = JFactory::getLanguage(); + $lang->load('com_jsn'); + + $message='


    '; + + if($type=='install') $message.='Successfully installed'; + else $message.='Successfully updated'; + + $message.='

    Support Docs

    '; + + JFactory::getApplication()->enqueueMessage($message); + + //$app->redirect('index.php?option=com_jsn&task='.$type); + } +} +?> diff --git a/deployed/jsn/administrator/components/com_jsn/jsn.php b/deployed/jsn/administrator/components/com_jsn/jsn.php new file mode 100644 index 00000000..23c25563 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/jsn.php @@ -0,0 +1,47 @@ +RELEASE=='3.0'){ + JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/j30/html'); + JFormHelper::addRulePath(JPATH_COMPONENT.'/helpers/j30/rule'); + define('JSNPREFIX','j30'); +} +else define('JSNPREFIX',''); + +$input = JFactory::getApplication()->input; + +if (!JFactory::getUser()->authorise('core.manage', 'com_jsn') && $input->get('view','fields')!='opField' && $input->get('view','fields')!='users') +{ + return JFactory::getApplication()->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR')); +} +if (!JFactory::getUser()->authorise('core.manage', 'com_users') && $input->get('view','fields')=='users') +{ + return JFactory::getApplication()->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR')); +} + +$lang = JFactory::getLanguage(); +$lang->load('com_users'); +$lang->load('com_jsn',JPATH_SITE); +JLoader::register('UsersHelper', __DIR__ . '/../com_users/helpers/users.php'); + +$task = $input->get('task'); + +$controller = JControllerLegacy::getInstance('Jsn'); +$controller->execute($input->get('task')); +$controller->redirect(); diff --git a/deployed/jsn/administrator/components/com_jsn/jsn.xml b/deployed/jsn/administrator/components/com_jsn/jsn.xml new file mode 100644 index 00000000..d4f02376 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/jsn.xml @@ -0,0 +1,83 @@ + + + com_jsn + JSN Project + December 2013 + (C) 2005 - 2013 Open Source Matters. All rights reserved. + http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + fiorino.desanto@gmail.com + www.joomla.org + 2.5.6 + COM_JSN_XML_DESCRIPTION + + install.jsn.php + + + + sql/install.mysql.utf8.sql + + + + + sql/uninstall.mysql.utf8.sql + + + + + sql/updates + + + + + jsn.php + router.php + controller.php + helpers + models + views + assets + + + languages/site/it-IT/it-IT.com_jsn.ini + languages/site/en-GB/en-GB.com_jsn.ini + languages/site/de-DE/de-DE.com_jsn.ini + languages/site/es-ES/es-ES.com_jsn.ini + + + + + jsn.php + access.xml + config.xml + + controller.php + defines.php + controllers + helpers + models + views + sql + tables + assets + + + languages/admin/it-IT/it-IT.com_jsn.ini + languages/admin/it-IT/it-IT.com_jsn.sys.ini + languages/admin/en-GB/en-GB.com_jsn.ini + languages/admin/en-GB/en-GB.com_jsn.sys.ini + languages/admin/de-DE/de-DE.com_jsn.ini + languages/admin/de-DE/de-DE.com_jsn.sys.ini + languages/admin/es-ES/es-ES.com_jsn.ini + languages/admin/es-ES/es-ES.com_jsn.sys.ini + + com_jsn + + + + + https://www.easy-profile.com/update.php?p=easy-profile&file=extension.xml + + + + + diff --git a/deployed/jsn/administrator/components/com_jsn/models/field.php b/deployed/jsn/administrator/components/com_jsn/models/field.php new file mode 100644 index 00000000..ded42616 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/field.php @@ -0,0 +1,696 @@ +id)) + { + if ($record->published != -2) + { + return; + } + $user = JFactory::getUser(); + + return parent::canDelete($record); + } + } + + /** + * Method to test whether a record can have its state changed. + * + * @param object $record A record object. + * + * @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component. + * + * @since 3.1 + */ + protected function canEditState($record,$nameField = null) + { + $user = JFactory::getUser(); + + // Prevent Delete and Unpublish Core Fields + if(($record->core && $nameField!='profile' && $nameField!='search') && !($record->alias=='avatar' && ($nameField=='edit' || $nameField=='required' || $nameField=='register')) && !($record->alias=='secondname' && $nameField=='required')) + { + JFactory::getApplication()->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED').' - '.JText::_('COM_JSN_VIEWCONFIG')); + return false; + } + + return parent::canEditState($record); + } + + /** + * Method to get a table object, load it if necessary. + * + * @param string $type The table name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A JTable object + * + * @since 3.1 + */ + public function getTable($type = 'Field', $prefix = 'JsnTable', $config = array()) + { + return JTable::getInstance($type, $prefix, $config); + } + + /** + * Auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @return void + * + * @since 3.1 + */ + protected function populateState() + { + $app = JFactory::getApplication('administrator'); + + $parentId = $app->input->getInt('parent_id'); + $this->setState('field.parent_id', $parentId); + + // Load the User state. + $pk = $app->input->getInt('id'); + $this->setState($this->getName() . '.id', $pk); + + // Load the parameters. + $params = JComponentHelper::getParams('com_jsn'); + $this->setState('params', $params); + } + + /** + * Method to get a field. + * + * @param integer $pk An optional id of the object to get, otherwise the id from the model state is used. + * + * @return mixed Field data object on success, false on failure. + * + * @since 3.1 + */ + public function getItem($pk = null) + { + if ($result = parent::getItem($pk)) + { + + // Prime required properties. + if (empty($result->id)) + { + $result->parent_id = $this->getState('field.parent_id'); + } + + // Convert the metadata field to an array. + $registry = new JRegistry; + $registry->loadString($result->metadata); + $result->metadata = $registry->toArray(); + + // Convert the images field to an array. + $registry = new JRegistry; + $registry->loadString($result->images); + $result->images = $registry->toArray(); + + // Convert the created and modified dates to local user time for display in the form. + $tz = new DateTimeZone(JFactory::getApplication()->getCfg('offset')); + + if ((int) $result->created_time) + { + $date = new JDate($result->created_time); + $date->setTimezone($tz); + $result->created_time = $date->toSql(true); + } + else + { + $result->created_time = null; + } + + if ((int) $result->modified_time) + { + $date = new JDate($result->modified_time); + $date->setTimezone($tz); + $result->modified_time = $date->toSql(true); + } + else + { + $result->modified_time = null; + } + } + + return $result; + } + + /** + * Method to get the row form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * + * @return mixed A JForm object on success, false on failure + * + * @since 3.1 + */ + public function getForm($data = array(), $loadData = true) + { + $extension = $this->getState('field'); + $jinput = JFactory::getApplication()->input; + + // Get the form. + $form = $this->loadForm('com_jsn.field', 'field', array('control' => 'jform', 'load_data' => $loadData)); + + if (empty($form)) + { + return false; + } + + $user = JFactory::getUser(); + if (!$user->authorise('core.edit.state', 'com_jsn' . $jinput->get('id'))) + { + // Disable fields for display. + $form->setFieldAttribute('ordering', 'disabled', 'true'); + $form->setFieldAttribute('published', 'disabled', 'true'); + + // Disable fields while saving. + // The controller has already verified this is a record you can edit. + $form->setFieldAttribute('ordering', 'filter', 'unset'); + $form->setFieldAttribute('published', 'filter', 'unset'); + } + + // Load Fields Params + foreach (glob(JPATH_ADMINISTRATOR . '/components/com_jsn/helpers/fields/*.xml') as $filename) + { + $form->loadFile($filename); + } + + return $form; + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since 3.1 + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = JFactory::getApplication()->getUserState('com_jsn.edit.field.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + } + + $version=new JVersion(); + if($version->RELEASE=='3.0') $this->preprocessDataJ30('com_jsn.field', $data); + else $this->preprocessData('com_jsn.field', $data); + + return $data; + } + + /** + * Method to preprocess the form. + * + * @param JForm $form A JForm object. + * @param mixed $data The data expected for the form. + * @param string $group The name of the plugin group to import. + * + * @return void + * + * @see JFormField + * @since 3.1 + * @throws Exception if there is an error in the form event. + */ + protected function preprocessForm(JForm $form, $data, $group = 'content') + { + // Trigger the default form events. + parent::preprocessForm($form, $data, $group); + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success. + * + * @since 3.1 + */ + public function save($data) + { + $dispatcher = JEventDispatcher::getInstance(); + $table = $this->getTable(); + $input = JFactory::getApplication()->input; + $pk = (!empty($data['id'])) ? $data['id'] : (int) $this->getState($this->getName() . '.id'); + $isNew = true; + + // Include the content plugins for the on save events. + JPluginHelper::importPlugin('content'); + + // Load the row if saving an existing field. + if ($pk > 0) + { + $table->load($pk); + $isNew = false; + } + + // Set the new parent id if parent id not matched OR while New/Save as Copy . + if ($table->parent_id != $data['parent_id'] || $data['id'] == 0) + { + $table->setLocation($data['parent_id'], 'last-child'); + } + + if (isset($data['images']) && is_array($data['images'])) + { + $registry = new JRegistry; + $registry->loadArray($data['images']); + $data['images'] = (string) $registry; + } + + // Alter the title for save as copy + if ($input->get('task') == 'save2copy') + { + list($title, $alias) = $this->generateNewTitle($data['parent_id'], $data['alias'], $data['title']); + $data['title'] = $title; + $data['alias'] = $alias; + } + + // Remove Search flag for some field type + $removeSearch = array('filetype','image','delimeter'); + if($isNew && in_array($data['type'],$removeSearch)) + { + $data['search'] = 0; + } + + // Block Modify of Alias, Type and Core / Block Modify of core parameter + if(!$isNew) + { + unset($data['type']); + unset($data['alias']); + unset($data['core']); + if($table->core && $table->alias != 'avatar' && $table->alias != 'secondname'){ + unset($data['required']); + //unset($data['profile']); + unset($data['register']); + unset($data['edit']); + } + } + + // Set Tos + /*if($data['type']=='tos') + { + $data['required']=1; + $data['register']=1; + $data['profile']=0; + }*/ + + // Block Reserved Alias + $reserved=array('id','name','email1','email2','password1','password2','params','privacy','facebook_id','google_id','twitter_id','linkedin_id','instagram_id','search'); + if($isNew && in_array( strtolower($data['alias']) , $reserved )) + { + $data['alias']='jsn_'.$data['alias']; + } + + // Bind the data. + if (!$table->bind($data)) + { + $this->setError($table->getError()); + return false; + } + + // Bind the rules. + if (isset($data['rules'])) + { + $rules = new JAccessRules($data['rules']); + $table->setRules($rules); + } + + // Check the data. + if (!$table->check()) + { + $this->setError($table->getError()); + return false; + } + + // Trigger the onContentBeforeSave event. + $result = $dispatcher->trigger($this->event_before_save, array($this->option . '.' . $this->name, &$table, $isNew)); + if (in_array(false, $result, true)) + { + $this->setError($table->getError()); + return false; + } + + // Store the data. + if (!$table->store()) + { + $this->setError($table->getError()); + return false; + } + + // Trigger the onContentAfterSave event. + $dispatcher->trigger($this->event_after_save, array($this->option . '.' . $this->name, &$table, $isNew)); + + // Create function for field + if($isNew && $table->level==2){ + $class='Jsn'.ucfirst($table->type).'FieldHelper'; + if(class_exists($class)) $class::create($table->alias); + } + + // Rebuild the path for the field: + if (!$table->rebuildPath($table->id)) + { + $this->setError($table->getError()); + return false; + } + + // Rebuild the paths of the field's children: + if (!$table->rebuild($table->id, $table->lft, $table->level, $table->path)) + { + $this->setError($table->getError()); + + return false; + } + + $this->setState($this->getName() . '.id', $table->id); + + // Clear the cache + $this->cleanCache(); + + return true; + } + + public function delete(&$pks){ + foreach($pks as $pk){ + $item=$this->getItem($pk); + if($item->level==2){ + try{ + $class='Jsn'.ucfirst($item->type).'FieldHelper'; + if(class_exists($class)) $class::delete($item->alias); + } + catch (Exception $e) {} + } + } + return parent::delete($pks); + } + + /** + * Method rebuild the entire nested set tree. + * + * @return boolean False on failure or error, true otherwise. + * + * @since 3.1 + */ + public function rebuild() + { + // Get an instance of the table object. + $table = $this->getTable(); + + if (!$table->rebuild()) + { + $this->setError($table->getError()); + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to save the reordered nested set tree. + * First we save the new order values in the lft values of the changed ids. + * Then we invoke the table rebuild to implement the new ordering. + * + * @param array $idArray An array of primary key ids. + * @param integer $lft_array The lft value + * + * @return boolean False on failure or error, True otherwise + * + * @since 3.1 + */ + public function saveorder($idArray = null, $lft_array = null) + { + // Get an instance of the table object. + $table = $this->getTable(); + + if (!$table->saveorder($idArray, $lft_array)) + { + $this->setError($table->getError()); + return false; + } + + // Clear the cache + $this->cleanCache(); + + return true; + } + + /** + * Method to change the title & alias. + * + * @param integer $parent_id The id of the parent. + * @param string $alias The alias. + * @param string $title The title. + * + * @return array Contains the modified title and alias. + * + * @since 3.1 + */ + protected function generateNewTitle($parent_id, $alias, $title) + { + // Alter the title & alias + $table = $this->getTable(); + while ($table->load(array('alias' => $alias, 'parent_id' => $parent_id))) + { + $title = ($table->title != $title) ? $title : JString::increment($title); + $alias = JString::increment($alias, 'dash'); + } + + return array($title, $alias); + } + + + public function toggle(&$pks, $value = 1, $nameField) + { + $user = JFactory::getUser(); + $table = $this->getTable(); + $pks = (array) $pks; + + // Access checks. + foreach ($pks as $i => $pk) + { + if ($table->load($pk)) + { + + if (!$this->canEditState($table,$nameField)) + { + // Prune items that you can't change. + unset($pks[$i]); + JFactory::getApplication()->enqueueMessage(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED').' - '.JText::_('COM_JSN_VIEWCONFIG')); + return false; + } + } + } + + // Attempt to change the state of the records. + if (!$table->toggle($pks, $value, $user->get('id'),$nameField)) + { + $this->setError($table->getError()); + return false; + } + + return true; + } + + protected function preprocessDataJ30($context, &$data) + { + // Get the dispatcher and load the users plugins. + $dispatcher = JEventDispatcher::getInstance(); + JPluginHelper::importPlugin('content'); + + // Trigger the data preparation event. + $results = $dispatcher->trigger('onContentPrepareData', array($context, $data)); + + // Check for errors encountered while preparing the data. + if (count($results) > 0 && in_array(false, $results, true)) + { + $this->setError($dispatcher->getError()); + } + } + + protected function batchAccess($value, $pks, $contexts) + { + $new_pk=array(); + foreach($pks as $key => $pk) + { + // Remove Core Fields + if($pk>11) $new_pk[]=$pk; + } + parent::batchAccess($value, $new_pk, $contexts); + return true; + } + + public function batch($commands, $pks, $contexts) + { + parent::batch($commands, $pks, $contexts); + if (!empty($commands['assetgroupview_id'])) + { + if (!$this->batchAccessView($commands['assetgroupview_id'], $pks, $contexts)) + { + return false; + } + + $done = true; + } + if (!empty($commands['fieldgroup_id'])) + { + if (!$this->batchFieldGroup($commands['fieldgroup_id'], $pks, $contexts)) + { + return false; + } + + $done = true; + } + return true; + } + + protected function batchAccessView($value, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + } + + foreach ($pks as $pk) + { + if ($this->user->authorise('core.edit', $contexts[$pk])) + { + $this->table->reset(); + $this->table->load($pk); + $this->table->accessview = (int) $value; + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + else + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } + + protected function batchFieldGroup($value, $pks, $contexts) + { + if (empty($this->batchSet)) + { + // Set some needed variables. + $this->user = JFactory::getUser(); + $this->table = $this->getTable(); + $this->tableClassName = get_class($this->table); + $this->contentType = new JUcmType; + $this->type = $this->contentType->getTypeByTable($this->tableClassName); + } + + foreach ($pks as $pk) + { + if ($this->user->authorise('core.edit', $contexts[$pk])) + { + $this->table->reset(); + $this->table->load($pk); + $this->table->parent_id = (int) $value; + $this->table->lft = 1000; + $this->table->rgt = 1000; + + if (!empty($this->type)) + { + $this->createTagsHelper($this->tagsObserver, $this->type, $pk, $this->typeAlias, $this->table); + } + + if (!$this->table->store()) + { + $this->setError($this->table->getError()); + + return false; + } + } + else + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + + return false; + } + } + + $this->rebuild(); + + // Clean the cache + $this->cleanCache(); + + return true; + } + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/fields.php b/deployed/jsn/administrator/components/com_jsn/models/fields.php new file mode 100644 index 00000000..d0752e3d --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/fields.php @@ -0,0 +1,311 @@ +context; + + $search = $this->getUserStateFromRequest($context . '.search', 'filter_search'); + $this->setState('filter.search', $search); + + $level = $this->getUserStateFromRequest($context . '.filter.level', 'filter_level', 0, 'int'); + $this->setState('filter.level', $level); + + $access = $this->getUserStateFromRequest($context . '.filter.access', 'filter_access', 0, 'int'); + $this->setState('filter.access', $access); + + $published = $this->getUserStateFromRequest($context . '.filter.published', 'filter_published', ''); + $this->setState('filter.published', $published); + + $language = $this->getUserStateFromRequest($context . '.filter.language', 'filter_language', ''); + $this->setState('filter.language', $language); + + // Load the parameters. + $params = JComponentHelper::getParams('com_jsn'); + $this->setState('params', $params); + + // List state information. + parent::populateState('a.lft', 'asc'); + } + + /** + * Method to get a store id based on model configuration state. + * + * This is necessary because the model is used by the component and + * different modules that might need different sets of data or different + * ordering requirements. + * + * @param string $id A prefix for the store id. + * + * @return string A store id. + * @since 3.1 + */ + protected function getStoreId($id = '') + { + // Compile the store id. + $id .= ':' . $this->getState('filter.search'); + $id .= ':' . $this->getState('filter.published'); + $id .= ':' . $this->getState('filter.language'); + + return parent::getStoreId($id); + } + + /** + * Method to create a query for a list of items. + * + * @return string + * + * @since 3.1 + */ + protected function getListQuery() + { + // Create a new query object. + $db = $this->getDbo(); + $query = $db->getQuery(true); + $user = JFactory::getUser(); + $app = JFactory::getApplication(); + + // Select the required fields from the table. + $query->select( + $this->getState( + 'list.select', + 'a.id, a.title, a.alias, a.note, a.published, a.access, a.accessview,a.params' . + ', a.checked_out, a.checked_out_time, a.created_user_id' . + ', a.path, a.parent_id, a.level, a.conditions, a.lft, a.rgt, a.type, a.core, a.required, a.edit, a.profile, a.register, a.search' . + ', a.language' + ) + ); + $query->from('#__jsn_fields AS a') + ->where('a.alias <> ' . $db->quote('root')); + + // Join over the language + //$query->select('l.title AS language_title') + // ->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language'); + + // Join over the users for the checked out user. + $query->select('uc.name AS editor') + ->join('LEFT', '#__users AS uc ON uc.id=a.checked_out'); + + // Join over the users for the author. + $query->select('ua.name AS author_name') + ->join('LEFT', '#__users AS ua ON ua.id = a.created_user_id'); + + $query->select('ug.title AS access_title') + ->join('LEFT', '#__viewlevels AS ug on ug.id = a.access'); + + $query->select('ugv.title AS accessview_title') + ->join('LEFT', '#__viewlevels AS ugv on ugv.id = a.accessview'); + + // Filter on the level. + if ($level = $this->getState('filter.level')) + { + $query->where('a.level <= ' . (int) $level); + } + + // Filter by access level. + if ($access = $this->getState('filter.access')) + { + $query->where('a.access = ' . (int) $access); + } + + // Implement View Level Access + if (!$user->authorise('core.admin')) + { + $groups = implode(',', $user->getAuthorisedViewLevels()); + //$query->where('a.access IN (' . $groups . ')'); + } + + // Filter by published state + $published = $this->getState('filter.published'); + if (is_numeric($published)) + { + $query->where('a.published = ' . (int) $published); + } + elseif ($published === '') + { + $query->where('(a.published IN (0, 1))'); + } + + // Filter by search in title + $search = $this->getState('filter.search'); + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + elseif (stripos($search, 'author:') === 0) + { + $search = $db->quote('%' . $db->escape(substr($search, 7), true) . '%'); + $query->where('(ua.name LIKE ' . $search . ' OR ua.username LIKE ' . $search . ')'); + } + else + { + $search = $db->quote('%' . $db->escape($search, true) . '%'); + $query->where('(a.title LIKE ' . $search . ' OR a.alias LIKE ' . $search . ' OR a.note LIKE ' . $search . ')'); + } + } + + // Filter on the language. + if ($language = $this->getState('filter.language')) + { + $query->where('a.language = ' . $db->quote($language)); + } + + // Add the list ordering clause + $listOrdering = $this->getState('list.ordering', 'a.lft'); + $listDirn = $db->escape($this->getState('list.direction', 'ASC')); + if ($listOrdering == 'a.access') + { + $query->order('a.access ' . $listDirn . ', a.lft ' . $listDirn); + } + else + { + $query->order($db->escape($listOrdering) . ' ' . $listDirn); + } + + //echo nl2br(str_replace('#__','jos_',$query)); + return $query; + } + + /** + * Method override to check-in a record or an array of record + * + * @param mixed $pks The ID of the primary key or an array of IDs + * + * @return mixed Boolean false if there is an error, otherwise the count of records checked in. + * + * @since 12.2 + */ + public function checkin($pks = array()) + { + $pks = (array) $pks; + $table = $this->getTable(); + $count = 0; + + if (empty($pks)) + { + $pks = array((int) $this->getState($this->getName() . '.id')); + } + + // Check in all items. + foreach ($pks as $pk) + { + if ($table->load($pk)) + { + + if ($table->checked_out > 0) + { + // Only attempt to check the row in if it exists. + if ($pk) + { + $user = JFactory::getUser(); + + // Get an instance of the row to checkin. + $table = $this->getTable(); + if (!$table->load($pk)) + { + $this->setError($table->getError()); + return false; + } + + // Check if this is the user having previously checked out the row. + if ($table->checked_out > 0 && $table->checked_out != $user->get('id') && !$user->authorise('core.admin', 'com_checkin')) + { + $this->setError(JText::_('JLIB_APPLICATION_ERROR_CHECKIN_USER_MISMATCH')); + return false; + } + + // Attempt to check the row in. + if (!$table->checkin($pk)) + { + $this->setError($table->getError()); + return false; + } + } + + $count++; + } + } + else + { + $this->setError($table->getError()); + + return false; + } + } + + return $count; + } + + /** + * Method to get a table object, load it if necessary. + * + * @param string $type The table name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A JTable object + * + * @since 3.1 + */ + public function getTable($type = 'Field', $prefix = 'JsnTable', $config = array()) + { + return JTable::getInstance($type, $prefix, $config); + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/fields/checkboxlist.php b/deployed/jsn/administrator/components/com_jsn/models/fields/checkboxlist.php new file mode 100644 index 00000000..207bfd1a --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/fields/checkboxlist.php @@ -0,0 +1,77 @@ +comParams = JComponentHelper::getParams('com_jsn'); + } + + + protected function getInput() + { + if($this->element['optioninline']==1) $inline='inline'; + else $inline=''; + $html=array(); + $version=new JVersion(); + if($version->RELEASE<'3.5'){ + $from=array('','
      ','
    ',''); + $to=array('','','',''); + $html[]=str_replace($from,$to,parent::getInput()); + return implode('', $html); + } + public function getOptions() + { + return parent::getOptions(); + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/fields/registerdate.php b/deployed/jsn/administrator/components/com_jsn/models/fields/registerdate.php new file mode 100644 index 00000000..ef45a25f --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/fields/registerdate.php @@ -0,0 +1,28 @@ +comParams = JComponentHelper::getParams('com_jsn'); + } + + + protected function getInput() + { + JHtml::_('formbehavior.chosen', 'select'); + /* Placeholder for multiple with Javascript */ + if(isset($this->element['hint']) && isset($this->element['multiple']) && $this->element['multiple']=='true') { + $script="jQuery(document).ready(function(){jQuery('#".$this->id."_chzn input').attr('value','".str_replace("'","\\'",$this->element['hint'])."')});"; + $doc=JFactory::getDocument(); + $doc->addScriptDeclaration( $script ); + } + if(is_object($this->value)) $this->value = (array) $this->value; + if(is_array($this->value)) $value=implode(',',$this->value); + else $value=$this->value; + /* Multiple empty fix */ + if(isset($this->element['multiple']) && $this->element['multiple']=='true') + $multiple_fix=''; + else + $multiple_fix=''; + /* --- */ + $script = ''; + if(isset($this->element['dboptfiltercolumn']) && !empty($this->element['dboptfiltercolumn']) && isset($this->element['dboptfiltervalue']) && !empty($this->element['dboptfiltervalue'])) + { + $script = JsnSelectlistFieldHelper::getAjaxScript($this->element['dboptfiltervalue'],$this->element['name']); + } + return str_replace('element['dbopttable']) && !empty($this->element['dbopttable']) && isset($this->element['dboptvalue']) && !empty($this->element['dboptvalue']) && isset($this->element['dbopttext']) && !empty($this->element['dbopttext'])) // set the alias of your field (width this conditions the select type work normally for all field except for this field) + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + $query->select($this->element['dboptvalue'].' AS value, '.$this->element['dbopttext'].' AS text')->from($this->element['dbopttable']); + + if(isset($this->element['dboptfiltercolumn']) && !empty($this->element['dboptfiltercolumn']) && isset($this->element['dboptfiltervalue']) && !empty($this->element['dboptfiltervalue'])) + { + if(empty($this->value)) + { + return parent::getOptions(); + } + elseif(is_array($this->value)) + { + $value=$this->value; + foreach($value as &$val) + $val=$db->quote($val); + $value=implode(',',$value); + $query->where($this->element['dboptvalue'].' IN ('.$value.')'); + } + else{ + $query->where($this->element['dboptvalue'].' = '.$db->quote($this->value)); + } + + } + + elseif(isset($this->element['dboptwhere']) && !empty($this->element['dboptwhere'])) + { + JPluginHelper::importPlugin('content'); + $where= JHtml::_('content.prepare', $this->element['dboptwhere'], 'customwhere', 'com_finder.indexer'); + if(empty($this->value)) + { + $query->where($where); + } + elseif(is_array($this->value)) + { + $value=$this->value; + foreach($value as &$val) + $val=$db->quote($val); + $value=implode(',',$value); + $query->where($where.' OR '.$this->element['dboptvalue'].' IN ('.$value.')'); + } + else{ + $query->where($where.' OR '.$this->element['dboptvalue'].' = '.$db->quote($this->value)); + } + } + + $query->order('text'); + + $db->setQuery($query); + + try + { + $options = $db->loadObjectList(); + } + catch (RuntimeException $e) + { + return false; + } + + foreach($options as &$option) + { + $option->text=JText::_($option->text); + } + + $options = array_merge(parent::getOptions(), $options); // Merge any additional options in the fields params (you can remove this). + + return $options; + } + else + { + return parent::getOptions(); + } + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/fields/textfull.php b/deployed/jsn/administrator/components/com_jsn/models/fields/textfull.php new file mode 100644 index 00000000..44178aa7 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/fields/textfull.php @@ -0,0 +1,41 @@ +element['pattern'])) { + $html = preg_replace('/pattern=/', 'jsn-pattern=', $html, 1); + if(isset($this->element['message-regex'])) $html.= '
    '.$this->element['message-regex'].'
    '; + } + return $html; + } + + + +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/fields/types.php b/deployed/jsn/administrator/components/com_jsn/models/fields/types.php new file mode 100644 index 00000000..e73aceff --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/fields/types.php @@ -0,0 +1,63 @@ +comParams = JComponentHelper::getParams('com_jsn'); + } + + + protected function getOptions() + { + // Include Field Class + foreach (glob(JPATH_ADMINISTRATOR . '/components/com_jsn/helpers/fields/*.php') as $filename) { + require_once $filename; + } + + global $_FIELDTYPES; + $options = $_FIELDTYPES; + + // Translate Options Text + foreach($options as &$value){ + $value=JText::_($value); + } + + // Merge any additional options in the XML definition. + if (!isset($this->element['level'])) $options = array_merge(parent::getOptions(), $options); + + return $options; + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/fields/video.php b/deployed/jsn/administrator/components/com_jsn/models/fields/video.php new file mode 100644 index 00000000..092df4e1 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/fields/video.php @@ -0,0 +1,28 @@ + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    +
    + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + + + + + +
    + +
    + + +
    + + + + + + + + + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deployed/jsn/administrator/components/com_jsn/models/forms/filter_users.xml b/deployed/jsn/administrator/components/com_jsn/models/forms/filter_users.xml new file mode 100644 index 00000000..991e94cf --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/forms/filter_users.xml @@ -0,0 +1,94 @@ + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/deployed/jsn/administrator/components/com_jsn/models/rule/filetype.php b/deployed/jsn/administrator/components/com_jsn/models/rule/filetype.php new file mode 100644 index 00000000..c6344473 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/rule/filetype.php @@ -0,0 +1,72 @@ + tag for the form field object. + * @param mixed $value The form field value to validate. + * @param string $group The field name group control value. This acts as as an array container for the field. + * For example if the field has name="foo" and the group value is set to "bar" then the + * full field name would end up being "bar[foo]". + * @param JRegistry $input An optional JRegistry object with the entire data set to validate against the entire form. + * @param JForm $form The form object for which the field is being tested. + * + * @return boolean True if the value is valid, false otherwise. + * + * @since 11.1 + * @link http://www.w3.org/Addressing/URL/url-spec.txt + * @see JString + */ + public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null) + { + // If the field is empty and not required, the field is valid. + $required = ((string) $element['requiredfile'] == 'true' || (string) $element['requiredfile'] == 'required'); + + $validate=false; + + $jform=JFactory::getApplication()->input->files->get('jform',null,'array'); + if(isset($jform['upload_'. (string) $element['name']]))$jform_file=$jform['upload_'. (string) $element['name']]; + if(isset($jform_file['name']) && strlen($jform_file['name'])>4) + { + $filename=$jform_file['name']; + $ext = strtolower($filename[strlen($filename)-4].$filename[strlen($filename)-3].$filename[strlen($filename)-2].$filename[strlen($filename)-1]); + if ($ext[0] == '.') $ext = substr($ext, 1, 3); + if (!in_array($ext, explode('|', (string) $element['mime']) )) return false; + $validate=true; + } + + if(!$required) return true; + + $form=JFactory::getApplication()->input->get('jform',false,'array'); + if($form && isset($form['id'])) + { + $db=JFactory::getDbo(); + $query=$db->getQuery(true); + $query->select($db->quoteName((string) $element['id']))->from('#__jsn_users')->where('id = '. (int) $form['id']); + $db->setQuery($query); + $checkValue=$db->loadResult(); + if(!empty($checkValue)) $validate=true; + } + + if($validate) return true; + else return false; + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/rule/image.php b/deployed/jsn/administrator/components/com_jsn/models/rule/image.php new file mode 100644 index 00000000..54337f1a --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/rule/image.php @@ -0,0 +1,66 @@ + tag for the form field object. + * @param mixed $value The form field value to validate. + * @param string $group The field name group control value. This acts as as an array container for the field. + * For example if the field has name="foo" and the group value is set to "bar" then the + * full field name would end up being "bar[foo]". + * @param JRegistry $input An optional JRegistry object with the entire data set to validate against the entire form. + * @param JForm $form The form object for which the field is being tested. + * + * @return boolean True if the value is valid, false otherwise. + * + * @since 11.1 + * @link http://www.w3.org/Addressing/URL/url-spec.txt + * @see JString + */ + public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null) + { + // If the field is empty and not required, the field is valid. + $required = ((string) $element['requiredfile'] == 'true' || (string) $element['requiredfile'] == 'required'); + + $validate=false; + + $jform=JFactory::getApplication()->input->files->get('jform',null,'raw'); + if(isset($jform['upload_'. (string) $element['name']]))$jform_file=$jform['upload_'. (string) $element['name']]; + if(isset($jform_file['name']) && strlen($jform_file['name'])>4) + { + $filename=$jform_file['name']; + $ext = strtolower($filename[strlen($filename)-4].$filename[strlen($filename)-3].$filename[strlen($filename)-2].$filename[strlen($filename)-1]); + if ($ext[0] == '.') $ext = substr($ext, 1, 3); + if (!in_array($ext, explode('|', 'jpg|png|jpeg|gif|bmp') )) return false; + $validate=true; + } + else{ + $form=JFactory::getApplication()->input->get('jform',null,'raw'); + $value=$form[(string) $element['name']]; + if(!empty($value)) $validate=true; + } + + if(!$required) return true; + + if($validate) return true; + else return false; + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/rule/link.php b/deployed/jsn/administrator/components/com_jsn/models/rule/link.php new file mode 100644 index 00000000..3142eacd --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/rule/link.php @@ -0,0 +1,98 @@ + tag for the form field object. + * @param mixed $value The form field value to validate. + * @param string $group The field name group control value. This acts as as an array container for the field. + * For example if the field has name="foo" and the group value is set to "bar" then the + * full field name would end up being "bar[foo]". + * @param JRegistry $input An optional JRegistry object with the entire data set to validate against the entire form. + * @param JForm $form The form object for which the field is being tested. + * + * @return boolean True if the value is valid, false otherwise. + * + * @since 11.1 + * @link http://www.w3.org/Addressing/URL/url-spec.txt + * @see JString + */ + public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null) + { + // If the field is empty and not required, the field is valid. + $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required'); + if (!$required && empty($value)) + { + return true; + } + $urlParts = JString::parse_url($value); + + // See http://www.w3.org/Addressing/URL/url-spec.txt + // Use the full list or optionally specify a list of permitted schemes. + if ($element['schemes'] == '') + { + $scheme = array('http', 'https', 'ftp', 'ftps', 'gopher', 'mailto', 'news', 'prospero', 'telnet', 'rlogin', 'tn3270', 'wais', 'url', + 'mid', 'cid', 'nntp', 'tel', 'urn', 'ldap', 'file', 'fax', 'modem', 'git'); + } + else + { + $scheme = explode(',', $element['schemes']); + } + + /* + * This rule is only for full URLs with schemes because parse_url does not parse + * accurately without a scheme. + * @see http://php.net/manual/en/function.parse-url.php + */ + if ($urlParts && !array_key_exists('scheme', $urlParts)) + { + return false; + } + $urlScheme = (string) $urlParts['scheme']; + $urlScheme = strtolower($urlScheme); + if (in_array($urlScheme, $scheme) == false) + { + return false; + } + // For some schemes here must be two slashes. + if (($urlScheme == 'http' || $urlScheme == 'https' || $urlScheme == 'ftp' || $urlScheme == 'sftp' || $urlScheme == 'gopher' + || $urlScheme == 'wais' || $urlScheme == 'gopher' || $urlScheme == 'prospero' || $urlScheme == 'telnet' || $urlScheme == 'git') + && ((substr($value, strlen($urlScheme), 3)) !== '://')) + { + return false; + } + // The best we can do for the rest is make sure that the strings are valid UTF-8 + // and the port is an integer. + if (array_key_exists('host', $urlParts) && !JString::valid((string) $urlParts['host'])) + { + return false; + } + if (array_key_exists('port', $urlParts) && !is_int((int) $urlParts['port'])) + { + return false; + } + if (array_key_exists('path', $urlParts) && !JString::valid((string) $urlParts['path'])) + { + return false; + } + return true; + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/rule/numeric.php b/deployed/jsn/administrator/components/com_jsn/models/rule/numeric.php new file mode 100644 index 00000000..5096808f --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/rule/numeric.php @@ -0,0 +1,45 @@ +$element['max']) + { + return false; + } + if ($value<$element['min']) + { + return false; + } + + return true; + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/rule/phone.php b/deployed/jsn/administrator/components/com_jsn/models/rule/phone.php new file mode 100644 index 00000000..a07fd7fb --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/rule/phone.php @@ -0,0 +1,105 @@ + tag for the form field object. + * @param mixed $value The form field value to validate. + * @param string $group The field name group control value. This acts as as an array container for the field. + * For example if the field has name="foo" and the group value is set to "bar" then the + * full field name would end up being "bar[foo]". + * @param JRegistry $input An optional JRegistry object with the entire data set to validate against the entire form. + * @param JForm $form The form object for which the field is being tested. + * + * @return boolean True if the value is valid, false otherwise. + * + * @since 11.1 + */ + public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null) + { + // If the field is empty and not required, the field is valid. + $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required'); + if (!$required && empty($value)) + { + return true; + } + + /* + * @see http://www.nanpa.com/ + * @see http://tools.ietf.org/html/rfc4933 + * @see http://www.itu.int/rec/T-REC-E.164/en + * + * Regex by Steve Levithan + * @see http://blog.stevenlevithan.com/archives/validate-phone-number + * @note that valid ITU-T and EPP must begin with +. + */ + $regexarray = array('NANP' => '/^(?:\+?1[-. ]?)?\(?([2-9][0-8][0-9])\)?[-. ]?([2-9][0-9]{2})[-. ]?([0-9]{4})$/', + 'ITU-T' => '/^\+(?:[0-9] ?){6,14}[0-9]$/', 'EPP' => '/^\+[0-9]{1,3}\.[0-9]{4,14}(?:x.+)?$/'); + if (isset($element['plan'])) + { + + $plan = (string) $element['plan']; + if ($plan == 'northamerica' || $plan == 'us') + { + $plan = 'NANP'; + } + elseif ($plan == 'International' || $plan == 'int' || $plan == 'missdn' || !$plan) + { + $plan = 'ITU-T'; + } + elseif ($plan == 'IETF') + { + $plan = 'EPP'; + } + + $regex = $regexarray[$plan]; + + // Test the value against the regular expression. + if (preg_match($regex, $value) == false) + { + + return false; + } + } + else + { + /* + * If the rule is set but no plan is selected just check that there are between + * 7 and 15 digits inclusive and no illegal characters (but common number separators + * are allowed). + */ + $cleanvalue = preg_replace('/[+. \-(\)]/', '', $value); + $regex = '/^[0-9]{7,15}?$/'; + if (preg_match($regex, $cleanvalue) == true) + { + + return true; + } + else + { + + return false; + } + } + + return true; + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/rule/regex.php b/deployed/jsn/administrator/components/com_jsn/models/rule/regex.php new file mode 100644 index 00000000..6014e845 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/rule/regex.php @@ -0,0 +1,46 @@ + tag for the form field object. + * @param mixed $value The form field value to validate. + * @param string $group The field name group control value. This acts as as an array container for the field. + * For example if the field has name="foo" and the group value is set to "bar" then the + * full field name would end up being "bar[foo]". + * @param JRegistry $input An optional JRegistry object with the entire data set to validate against the entire form. + * @param JForm $form The form object for which the field is being tested. + * + * @return boolean True if the value is valid, false otherwise. + * + * @since 11.1 + * @link http://www.w3.org/Addressing/URL/url-spec.txt + * @see JString + */ + public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null) + { + // If the field is empty and not required, the field is valid. + $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required'); + if (!$required && empty($value)) + { + return true; + } + $urlParts = JString::parse_url($value); + + // See http://www.w3.org/Addressing/URL/url-spec.txt + // Use the full list or optionally specify a list of permitted schemes. + if ($element['schemes'] == '') + { + $scheme = array('http', 'https', 'ftp', 'ftps', 'gopher', 'mailto', 'news', 'prospero', 'telnet', 'rlogin', 'tn3270', 'wais', 'url', + 'mid', 'cid', 'nntp', 'tel', 'urn', 'ldap', 'file', 'fax', 'modem', 'git'); + } + else + { + $scheme = explode(',', $element['schemes']); + } + + /* + * This rule is only for full URLs with schemes because parse_url does not parse + * accurately without a scheme. + * @see http://php.net/manual/en/function.parse-url.php + */ + if ($urlParts && !array_key_exists('scheme', $urlParts)) + { + return false; + } + $urlScheme = (string) $urlParts['scheme']; + $urlScheme = strtolower($urlScheme); + if (in_array($urlScheme, $scheme) == false) + { + return false; + } + // For some schemes here must be two slashes. + if (($urlScheme == 'http' || $urlScheme == 'https' || $urlScheme == 'ftp' || $urlScheme == 'sftp' || $urlScheme == 'gopher' + || $urlScheme == 'wais' || $urlScheme == 'gopher' || $urlScheme == 'prospero' || $urlScheme == 'telnet' || $urlScheme == 'git') + && ((substr($value, strlen($urlScheme), 3)) !== '://')) + { + return false; + } + // The best we can do for the rest is make sure that the strings are valid UTF-8 + // and the port is an integer. + if (array_key_exists('host', $urlParts) && !JString::valid((string) $urlParts['host'])) + { + return false; + } + if (array_key_exists('port', $urlParts) && !is_int((int) $urlParts['port'])) + { + return false; + } + if (array_key_exists('path', $urlParts) && !JString::valid((string) $urlParts['path'])) + { + return false; + } + // Video + if(!(strpos(' '.$value,'https://www.youtube.com/watch?v=')==1 || strpos(' '.$value,'http://www.youtube.com/watch?v=')==1 || strpos(' '.$value,'https://m.youtube.com/watch?v=')==1 || strpos(' '.$value,'http://www.youtube.com/watch?v=')==1 || strpos(' '.$value,'http://youtu.be/')==1 || strpos(' '.$value,'http://vimeo.com/')==1 || strpos(' '.$value,'https://vimeo.com/')==1)) return false; + return true; + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/models/user.php b/deployed/jsn/administrator/components/com_jsn/models/user.php new file mode 100644 index 00000000..c340ddf7 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/models/user.php @@ -0,0 +1,22 @@ +getDbo(); + $query = $db->getQuery(true); + + // Select the required fields from the table. + $query->select( + $this->getState( + 'list.select', + 'a.*' + ) + ); + + $query->from($db->quoteName('#__users') . ' AS a'); + + // If the model is set to check item state, add to the query. + $state = $this->getState('filter.state'); + + if (is_numeric($state)) + { + $query->where('a.block = ' . (int) $state); + } + + // If the model is set to check the activated state, add to the query. + $active = $this->getState('filter.active'); + + if (is_numeric($active)) + { + if ($active == '0') + { + $query->where('a.activation IN (' . $db->quote('') . ', ' . $db->quote('0') . ')'); + } + elseif ($active == '1') + { + $query->where($query->length('a.activation') . ' > 1'); + } + } + + // Filter the items over the group id if set. + $groupId = $this->getState('filter.group_id'); + $groups = $this->getState('filter.groups'); + + if ($groupId || isset($groups)) + { + $query->join('LEFT', '#__user_usergroup_map AS map2 ON map2.user_id = a.id') + ->group( + $db->quoteName( + array( + 'a.id', + 'a.name', + 'a.username', + 'a.password', + 'a.block', + 'a.sendEmail', + 'a.registerDate', + 'a.lastvisitDate', + 'a.activation', + 'a.params', + 'a.email' + ) + ) + ); + + if ($groupId) + { + $query->where('map2.group_id = ' . (int) $groupId); + } + + if (isset($groups)) + { + $query->where('map2.group_id IN (' . implode(',', $groups) . ')'); + } + } + + // Filter the items over the search string if set. + $search = $this->getState('filter.search'); + + if (!empty($search)) + { + if (stripos($search, 'id:') === 0) + { + $query->where('a.id = ' . (int) substr($search, 3)); + } + elseif (stripos($search, 'username:') === 0) + { + $search = $db->quote('%' . $db->escape(substr($search, 9), true) . '%'); + $query->where('a.username LIKE ' . $search); + } + else + { + // Escape the search token. + $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%')); + + // Compile the different search clauses. + $searches = array(); + $searches[] = 'a.name LIKE ' . $search; + $searches[] = 'a.username LIKE ' . $search; + $searches[] = 'a.email LIKE ' . $search; + + // Add the clauses to the query. + $query->where('(' . implode(' OR ', $searches) . ')'); + } + } + + // Add filter for registration ranges select list + $range = $this->getState('filter.range'); + + // Apply the range filter. + if ($range) + { + $dates = $this->buildDateRange($range); + + if ($dates['dNow'] === false) + { + $query->where( + $db->qn('a.registerDate') . ' < ' . $db->quote($dates['dStart']->format('Y-m-d H:i:s')) + ); + } + else + { + $query->where( + $db->qn('a.registerDate') . ' >= ' . $db->quote($dates['dStart']->format('Y-m-d H:i:s')) . + ' AND ' . $db->qn('a.registerDate') . ' <= ' . $db->quote($dates['dNow']->format('Y-m-d H:i:s')) + ); + } + } + + // Add filter for registration ranges select list + $lastvisitrange = $this->getState('filter.lastvisitrange'); + + // Apply the range filter. + if ($lastvisitrange) + { + $dates = $this->buildDateRange($lastvisitrange); + + if (is_string($dates['dStart'])) + { + $query->where( + $db->qn('a.lastvisitDate') . ' = ' . $db->quote($dates['dStart']) + ); + } + elseif ($dates['dNow'] === false) + { + $query->where( + $db->qn('a.lastvisitDate') . ' < ' . $db->quote($dates['dStart']->format('Y-m-d H:i:s')) + ); + } + else + { + $query->where( + $db->qn('a.lastvisitDate') . ' >= ' . $db->quote($dates['dStart']->format('Y-m-d H:i:s')) . + ' AND ' . $db->qn('a.lastvisitDate') . ' <= ' . $db->quote($dates['dNow']->format('Y-m-d H:i:s')) + ); + } + } + + // Filter by excluded users + $excluded = $this->getState('filter.excluded'); + //$excluded= array('0) AND id IN (113,112'); + + if (!empty($excluded)) + { + $query->where('id NOT IN (' . implode(',', $excluded) . ')'); + } + + // Add the list ordering clause. + $query->order($db->qn($db->escape($this->getState('list.ordering', 'a.name'))) . ' ' . $db->escape($this->getState('list.direction', 'ASC'))); + + if($this->filter) + { + $session = JFactory::getSession(); + $itemid=JFactory::getApplication()->input->get('Itemid','admin'); + if(count(JFactory::getApplication()->input->post->getArray())) + $session->set('jsn_search_'.$itemid,JFactory::getApplication()->input->post->getArray()); + elseif($session->get('jsn_search_'.$itemid,null)){ + foreach($session->get('jsn_search_'.$itemid) as $key=>$value){ + JFactory::getApplication()->input->set($key,$value); + } + + } + } + + $query->join('left','#__jsn_users as b ON a.id=b.id'); + + if($this->filter) { + // Load Fields + $queryField = $db->getQuery(true); + $queryField->select('a.*')->from('#__jsn_fields AS a')->where('a.level = 2')->where('a.search = 1')->where('a.published = 1'); + $db->setQuery( $queryField ); + $fields = $db->loadObjectList(); + + foreach (glob(JPATH_ADMINISTRATOR . '/components/com_jsn/helpers/fields/*.php') as $filename) { + require_once $filename; + } + + foreach($fields as $field) + { + if(JFactory::getApplication()->input->get($field->alias,'','raw')!=''){ + + // Load Field Registry + $registry = new JRegistry; + $registry->loadString($field->params); + $field->params = $registry; + + $class='Jsn'.ucfirst($field->type).'FieldHelper'; + + if(class_exists($class)) $class::getSearchQuery($field,$query); + } + } + } + + return $query; + } + public $filter=true; + + private function buildDateRange($range) + { + // Get UTC for now. + $dNow = new JDate; + $dStart = clone $dNow; + + switch ($range) + { + case 'past_week': + $dStart->modify('-7 day'); + break; + + case 'past_1month': + $dStart->modify('-1 month'); + break; + + case 'past_3month': + $dStart->modify('-3 month'); + break; + + case 'past_6month': + $dStart->modify('-6 month'); + break; + + case 'post_year': + $dNow = false; + case 'past_year': + $dStart->modify('-1 year'); + break; + + case 'today': + // Ranges that need to align with local 'days' need special treatment. + $app = JFactory::getApplication(); + $offset = $app->get('offset'); + + // Reset the start time to be the beginning of today, local time. + $dStart = new JDate('now', $offset); + $dStart->setTime(0, 0, 0); + + // Now change the timezone back to UTC. + $tz = new DateTimeZone('GMT'); + $dStart->setTimezone($tz); + break; + case 'never': + $dNow = false; + $dStart = $this->_db->getNullDate(); + break; + } + + return array('dNow' => $dNow, 'dStart' => $dStart); + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/sql/install.mysql.utf8.sql b/deployed/jsn/administrator/components/com_jsn/sql/install.mysql.utf8.sql new file mode 100644 index 00000000..127a1386 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/sql/install.mysql.utf8.sql @@ -0,0 +1,77 @@ + +CREATE TABLE IF NOT EXISTS `#__jsn_fields` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `parent_id` int(10) unsigned NOT NULL DEFAULT '0', + `lft` int(11) NOT NULL DEFAULT '0', + `rgt` int(11) NOT NULL DEFAULT '0', + `level` int(10) unsigned NOT NULL DEFAULT '0', + `path` varchar(255) NOT NULL DEFAULT '', + `title` varchar(255) NOT NULL, + `alias` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `note` varchar(255) NOT NULL DEFAULT '', + `description` mediumtext NOT NULL, + `published` tinyint(1) NOT NULL DEFAULT '0', + + `type` varchar(255) NOT NULL, + `core` tinyint(1) NOT NULL DEFAULT '0', + `required` tinyint(1) NOT NULL DEFAULT '0', + `profile` tinyint(1) NOT NULL DEFAULT '0', + `edit` tinyint(1) NOT NULL DEFAULT '0', + `register` tinyint(1) NOT NULL DEFAULT '0', + `search` tinyint(1) NOT NULL DEFAULT '0', + + `checked_out` int(11) unsigned NOT NULL DEFAULT '0', + `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `access` int(10) unsigned NOT NULL DEFAULT '0', + `accessview` int(10) unsigned NOT NULL DEFAULT '0', + `params` text NOT NULL, + `conditions` text NOT NULL, + `metadesc` varchar(1024) NOT NULL COMMENT 'The meta description for the page.', + `metakey` varchar(1024) NOT NULL COMMENT 'The meta keywords for the page.', + `metadata` varchar(2048) NOT NULL COMMENT 'JSON encoded metadata properties.', + `created_user_id` int(10) unsigned NOT NULL DEFAULT '0', + `created_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `created_by_alias` varchar(255) NOT NULL DEFAULT '', + `modified_user_id` int(10) unsigned NOT NULL DEFAULT '0', + `modified_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `images` text NOT NULL, + `urls` text NOT NULL, + `hits` int(10) unsigned NOT NULL DEFAULT '0', + `language` char(7) NOT NULL, + `version` int(10) unsigned NOT NULL DEFAULT '1', + `publish_up` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `publish_down` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + + +CREATE TABLE IF NOT EXISTS `#__jsn_users` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `privacy` TEXT NOT NULL, + `firstname` varchar(255) NOT NULL, + `secondname` varchar(255) NOT NULL, + `lastname` varchar(255) NOT NULL, + `avatar` varchar(255) NOT NULL, + `params` TEXT NOT NULL, + `facebook_id` varchar(255) NOT NULL, + `twitter_id` varchar(255) NOT NULL, + `google_id` varchar(255) NOT NULL, + `linkedin_id` varchar(255) NOT NULL, + `instagram_id` varchar(255) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +INSERT IGNORE INTO #__jsn_fields(`id`,`parent_id`,`level`,`title`,`alias`,`path`,`type`,`published`,`core`,`required`,`profile`,`register`,`lft`,`rgt`,`access`,`params`,`edit`,`accessview`) VALUES + (1,0,0,'ROOT','root','','',1,0,0,0,0, 0,21,1, '', 0,1), + (2,1,1,'DETAILS','default','default','',1,1,0,0,0, 1,20,1, '', 0,1), + (3,2,2,'USERNAME','username','default/username','username',1,1,1,1,1, 2,3,1, '', 1,1), + (4,2,2,'NAME','firstname','default/firstname','text',1,1,2,1,1, 4,5,1, '', 1,1), + (5,2,2,'SECONDNAME','secondname','default/secondname','text',0,1,0,1,1, 6,7,1, '', 1,1), + (6,2,2,'LASTNAME','lastname','default/lastname','text',1,1,2,1,1, 8,9,1, '', 1,1), + (7,2,2,'EMAIL','email','default/email','usermail',1,1,1,1,1, 10,11,1, '', 1,1), + (8,2,2,'PASSWORD','password','default/password','password',1,1,1,1,1, 12,13,1, '', 1,1), + (9,2,2,'AVATAR','avatar','default/avatar','image',1,1,0,1,1, 14,15,1,'{"image_width":500,"image_height":500,"image_thumbwidth":100,"image_thumbheight":100,"image_alt":"Avatar","image_class":""}', 1,1), + (10,2,2,'REGISTEREDDATE','registerdate','default/registerdate','registerdate',1,1,0,1,0, 16,17,1, '', 0,1), + (11,2,2,'LASTVISITDATE','lastvisitdate','default/lastvisitdate','lastvisitdate',1,1,0,1,0, 18,19,1, '', 0,1); + +UPDATE #__extensions SET ordering=1 WHERE name LIKE 'plg_authentication_joomla' OR name LIKE 'plg_user_profile'; diff --git a/deployed/jsn/administrator/components/com_jsn/sql/test.install.mysql.utf8.sql b/deployed/jsn/administrator/components/com_jsn/sql/test.install.mysql.utf8.sql new file mode 100644 index 00000000..af6e86f8 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/sql/test.install.mysql.utf8.sql @@ -0,0 +1,122 @@ +-- DROP TABLE IF EXISTS `#__jsn_fields`; +DROP TABLE IF EXISTS `#__jsn_usertypes`; +-- DROP TABLE IF EXISTS `#__jsn_users`; + +CREATE TABLE IF NOT EXISTS `#__jsn_fields` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `parent_id` int(10) unsigned NOT NULL DEFAULT '0', + `lft` int(11) NOT NULL DEFAULT '0', + `rgt` int(11) NOT NULL DEFAULT '0', + `level` int(10) unsigned NOT NULL DEFAULT '0', + `path` varchar(255) NOT NULL DEFAULT '', + `title` varchar(255) NOT NULL, + `alias` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `note` varchar(255) NOT NULL DEFAULT '', + `description` mediumtext NOT NULL, + `published` tinyint(1) NOT NULL DEFAULT '0', + + `type` varchar(255) NOT NULL, + `core` tinyint(1) NOT NULL DEFAULT '0', + `required` tinyint(1) NOT NULL DEFAULT '0', + `profile` tinyint(1) NOT NULL DEFAULT '0', + `register` tinyint(1) NOT NULL DEFAULT '0', + + `checked_out` int(11) unsigned NOT NULL DEFAULT '0', + `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `access` int(10) unsigned NOT NULL DEFAULT '0', + `params` text NOT NULL, + `metadesc` varchar(1024) NOT NULL COMMENT 'The meta description for the page.', + `metakey` varchar(1024) NOT NULL COMMENT 'The meta keywords for the page.', + `metadata` varchar(2048) NOT NULL COMMENT 'JSON encoded metadata properties.', + `created_user_id` int(10) unsigned NOT NULL DEFAULT '0', + `created_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `created_by_alias` varchar(255) NOT NULL DEFAULT '', + `modified_user_id` int(10) unsigned NOT NULL DEFAULT '0', + `modified_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `images` text NOT NULL, + `urls` text NOT NULL, + `hits` int(10) unsigned NOT NULL DEFAULT '0', + `language` char(7) NOT NULL, + `version` int(10) unsigned NOT NULL DEFAULT '1', + `publish_up` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `publish_down` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`), + KEY `field_idx` (`published`,`access`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_path` (`path`), + KEY `idx_left_right` (`lft`,`rgt`), + KEY `idx_alias` (`alias`), + KEY `idx_language` (`language`) +) DEFAULT CHARSET=utf8; + +/*CREATE TABLE IF NOT EXISTS `#__jsn_usertypes` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `parent_id` int(10) unsigned NOT NULL DEFAULT '0', + `lft` int(11) NOT NULL DEFAULT '0', + `rgt` int(11) NOT NULL DEFAULT '0', + `level` int(10) unsigned NOT NULL DEFAULT '0', + `path` varchar(255) NOT NULL DEFAULT '', + `title` varchar(255) NOT NULL, + `alias` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `note` varchar(255) NOT NULL DEFAULT '', + `description` mediumtext NOT NULL, + `published` tinyint(1) NOT NULL DEFAULT '0', + `checked_out` int(11) unsigned NOT NULL DEFAULT '0', + `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `access` int(10) unsigned NOT NULL DEFAULT '0', + `params` text NOT NULL, + `metadesc` varchar(1024) NOT NULL COMMENT 'The meta description for the page.', + `metakey` varchar(1024) NOT NULL COMMENT 'The meta keywords for the page.', + `metadata` varchar(2048) NOT NULL COMMENT 'JSON encoded metadata properties.', + `created_user_id` int(10) unsigned NOT NULL DEFAULT '0', + `created_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `created_by_alias` varchar(255) NOT NULL DEFAULT '', + `modified_user_id` int(10) unsigned NOT NULL DEFAULT '0', + `modified_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `images` text NOT NULL, + `urls` text NOT NULL, + `hits` int(10) unsigned NOT NULL DEFAULT '0', + `language` char(7) NOT NULL, + `version` int(10) unsigned NOT NULL DEFAULT '1', + `publish_up` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `publish_down` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`), + KEY `usertype_idx` (`published`,`access`), + KEY `idx_access` (`access`), + KEY `idx_checkout` (`checked_out`), + KEY `idx_path` (`path`), + KEY `idx_left_right` (`lft`,`rgt`), + KEY `idx_alias` (`alias`), + KEY `idx_language` (`language`) +) DEFAULT CHARSET=utf8;*/ + +CREATE TABLE IF NOT EXISTS `#__jsn_users` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `privacy` TEXT NOT NULL DEFAULT '', + `firstname` varchar(255) NOT NULL, + `secondname` varchar(255) NOT NULL, + `lastname` varchar(255) NOT NULL, + `avatar` varchar(255) NOT NULL, + `params` TEXT NOT NULL DEFAULT '', + `facebook_id` varchar(255) NOT NULL, + `twitter_id` varchar(255) NOT NULL, + `google_id` varchar(255) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; + +INSERT IGNORE INTO #__jsn_fields(`id`,`parent_id`,`level`,`title`,`alias`,`path`,`type`,`published`,`core`,`required`,`profile`,`register`,`lft`,`rgt`,`access`,`params`) VALUES + (1,0,0,'ROOT','root','','',0,0,0,0,0, 0,21,1, ''), + (2,1,1,'DETAILS','default','default','',1,1,0,0,0, 1,20,1, ''), + (3,2,2,'USERNAME','username','default/username','username',1,1,1,1,1, 2,3,1, ''), + (4,2,2,'NAME','firstname','default/firstname','text',1,1,1,1,1, 4,5,1, ''), + (5,2,2,'SECONDNAME','secondname','default/secondname','text',0,1,0,1,1, 6,7,1, ''), + (6,2,2,'LASTNAME','lastname','default/lastname','text',1,1,1,1,1, 8,9,1, ''), + (7,2,2,'EMAIL','email','default/email','usermail',1,1,1,1,1, 10,11,1, ''), + (8,2,2,'PASSWORD','password','default/password','password',1,1,1,1,1, 12,13,1, ''), + (9,2,2,'AVATAR','avatar','default/avatar','image',1,1,0,1,1, 14,15,1,'{"image_width":200,"image_height":200,"image_thumbwidth":50,"image_thumbheight":50,"image_alt":"Avatar","image_class":"img-circle"}'), + (10,2,2,'REGISTEREDDATE','registereddate','default/registereddate','registerdate',1,1,0,1,0, 16,17,1, ''), + (11,2,2,'LASTVISITDATE','lastvisitdate','default/lastvisitdate','lastvisitdate',1,1,0,1,0, 18,19,1, ''); + +/*INSERT IGNORE INTO #__jsn_usertypes(`id`,`parent_id`,`level`,`title`,`alias`,`path`,`published`,`lft`,`rgt`,`access`) VALUES + (1,0,0,'ROOT','root','',0, 0,21,1);*/ diff --git a/deployed/jsn/administrator/components/com_jsn/sql/uninstall.mysql.utf8.sql b/deployed/jsn/administrator/components/com_jsn/sql/uninstall.mysql.utf8.sql new file mode 100644 index 00000000..e69de29b diff --git a/deployed/jsn/administrator/components/com_jsn/sql/updates/1.0.0.sql b/deployed/jsn/administrator/components/com_jsn/sql/updates/1.0.0.sql new file mode 100644 index 00000000..e69de29b diff --git a/deployed/jsn/administrator/components/com_jsn/sql/updates/1.2.0.sql b/deployed/jsn/administrator/components/com_jsn/sql/updates/1.2.0.sql new file mode 100644 index 00000000..e69de29b diff --git a/deployed/jsn/administrator/components/com_jsn/sql/updates/1.3.0.sql b/deployed/jsn/administrator/components/com_jsn/sql/updates/1.3.0.sql new file mode 100644 index 00000000..e69de29b diff --git a/deployed/jsn/administrator/components/com_jsn/tables/field.php b/deployed/jsn/administrator/components/com_jsn/tables/field.php new file mode 100644 index 00000000..e113200f --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/tables/field.php @@ -0,0 +1,253 @@ +loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + if (isset($array['images']) && is_array($array['images'])) + { + $registry = new JRegistry; + $registry->loadArray($array['images']); + $array['images'] = (string) $registry; + } + + return parent::bind($array, $ignore); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + * + * @since 3.1 + * @throws UnexpectedValueException + */ + public function check() + { + // Check for valid name. + if (trim($this->title) == '') + { + throw new UnexpectedValueException(sprintf('The title is empty')); + } + + if (empty($this->alias)) + { + $this->alias = $this->title; + } + if($this->id==0) + { + if(strlen($this->alias)>40) $this->alias=substr($this->alias,0,40); + + $this->alias = str_replace('-','_',JApplication::stringURLSafe($this->alias)); + if (trim(str_replace('-', '', $this->alias)) == '' || preg_match('/^[a-zA-Z0-9_]*$/', $this->alias) == false || is_numeric($this->alias)) + { + $this->alias = 'field_'.JDate::getInstance()->format("YmdHis"); + } + } + + + + // Check the publish down date is not earlier than publish up. + if ((int) $this->publish_down > 0 && $this->publish_down < $this->publish_up) + { + throw new UnexpectedValueException(sprintf('End publish date is before start publish date.')); + } + + // Clean up keywords -- eliminate extra spaces between phrases + // and cr (\r) and lf (\n) characters from string + if (!empty($this->metakey)) + { + // Only process if not empty + // Define array of characters to remove + $bad_characters = array("\n", "\r", "\"", "<", ">"); + // Remove bad characters + $after_clean = JString::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter + $keys = explode(',', $after_clean); + $clean_keys = array(); + foreach($keys as $key) + { + if (trim($key)) + { + // Ignore blank keywords + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = JString::str_ireplace($bad_characters, "", $this->metadesc); + } + + return true; + } + + /** + * Overriden JTable::store to set modified data and user id. + * + * @param boolean $updateNulls True to update fields even if they are null. + * + * @return boolean True on success. + * + * @since 3.1 + */ + public function store($updateNulls = false) + { + $date = JDate::getInstance(); + $user = JFactory::getUser(); + if ($this->id) { + // Existing item + $this->modified_time = $date->toSql(); + $this->modified_user_id = $user->get('id'); + } + else + { + // New field. A field created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created_time) { + $this->created_time = $date->toSql(); + } + if (empty($this->created_user_id)) { + $this->created_user_id = $user->get('id'); + } + } + + // Verify that the alias is unique + $table = JTable::getInstance('Field', 'JsnTable'); + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_JSN_ERROR_UNIQUE_ALIAS')); + return false; + } + return parent::store($updateNulls); + } + + /** + * Method to delete a node and, optionally, its child nodes from the table. + * + * @param integer $pk The primary key of the node to delete. + * @param boolean $children True to delete child nodes, false to move them up a level. + * + * @return boolean True on success. + * + * @since 3.1 + * @see http://docs.joomla.org/JTableNested/delete + */ + public function delete($pk = null, $children = false) + { + return parent::delete($pk, $children); + $helper = new JHelperFields; + $helper->fieldDeleteInstances($pk); + } + + + + public function toggle($pks = null, $state = 1, $userId = 0, $nameField) + { + $k = $this->_tbl_key; + + // Sanitize input. + JArrayHelper::toInteger($pks); + $userId = (int) $userId; + $state = (int) $state; + + // If there are no primary keys set check to see if the instance key is set. + if (empty($pks)) + { + if ($this->$k) + { + $pks = array($this->$k); + } + // Nothing to set publishing state on, return false. + else { + $this->setError(JText::_('JLIB_DATABASE_ERROR_NO_ROWS_SELECTED')); + return false; + } + } + + // Get an instance of the table + $table = JTable::getInstance('Field', 'JsnTable'); + + // For all keys + foreach ($pks as $pk) + { + // Load the banner + if (!$table->load($pk)) + { + $this->setError($table->getError()); + } + + // Verify checkout + if ($table->checked_out == 0 || $table->checked_out == $userId) + { + // Change the state + $table->$nameField = $state; + $table->checked_out = 0; + $table->checked_out_time = $this->_db->getNullDate(); + + // Check the row + $table->check(); + + // Store the row + if (!$table->store()) + { + $this->setError($table->getError()); + } + } + } + return count($this->getErrors()) == 0; + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/tables/usertype.php b/deployed/jsn/administrator/components/com_jsn/tables/usertype.php new file mode 100644 index 00000000..f69f1694 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/tables/usertype.php @@ -0,0 +1,195 @@ +loadArray($array['params']); + $array['params'] = (string) $registry; + } + + if (isset($array['metadata']) && is_array($array['metadata'])) + { + $registry = new JRegistry; + $registry->loadArray($array['metadata']); + $array['metadata'] = (string) $registry; + } + + if (isset($array['urls']) && $array['urls']) + { + $registry = new JRegistry; + $registry->loadArray($array['urls']); + $array['urls'] = (string) $registry; + } + + if (isset($array['images']) && is_array($array['images'])) + { + $registry = new JRegistry; + $registry->loadArray($array['images']); + $array['images'] = (string) $registry; + } + + return parent::bind($array, $ignore); + } + + /** + * Overloaded check method to ensure data integrity. + * + * @return boolean True on success. + * + * @since 3.1 + * @throws UnexpectedValueException + */ + public function check() + { + // Check for valid name. + if (trim($this->title) == '') + { + throw new UnexpectedValueException(sprintf('The title is empty')); + } + + if (empty($this->alias)) + { + $this->alias = $this->title; + } + $this->alias = JApplication::stringURLSafe($this->alias); + if (trim(str_replace('-', '', $this->alias)) == '') + { + $this->alias = JDate::getInstance()->format("Y-m-d-H-i-s"); + } + + // Check the publish down date is not earlier than publish up. + if ((int) $this->publish_down > 0 && $this->publish_down < $this->publish_up) + { + throw new UnexpectedValueException(sprintf('End publish date is before start publish date.')); + } + + // Clean up keywords -- eliminate extra spaces between phrases + // and cr (\r) and lf (\n) characters from string + if (!empty($this->metakey)) + { + // Only process if not empty + // Define array of characters to remove + $bad_characters = array("\n", "\r", "\"", "<", ">"); + // Remove bad characters + $after_clean = JString::str_ireplace($bad_characters, "", $this->metakey); + + // Create array using commas as delimiter + $keys = explode(',', $after_clean); + $clean_keys = array(); + foreach($keys as $key) + { + if (trim($key)) + { + // Ignore blank keywords + $clean_keys[] = trim($key); + } + } + + // Put array back together delimited by ", " + $this->metakey = implode(", ", $clean_keys); + } + + // Clean up description -- eliminate quotes and <> brackets + if (!empty($this->metadesc)) { + // Only process if not empty + $bad_characters = array("\"", "<", ">"); + $this->metadesc = JString::str_ireplace($bad_characters, "", $this->metadesc); + } + + return true; + } + + /** + * Overriden JTable::store to set modified data and user id. + * + * @param boolean $updateNulls True to update fields even if they are null. + * + * @return boolean True on success. + * + * @since 3.1 + */ + public function store($updateNulls = false) + { + $date = JDate::getInstance(); + $user = JFactory::getUser(); + if ($this->id) { + // Existing item + $this->modified_time = $date->toSql(); + $this->modified_user_id = $user->get('id'); + } + else + { + // New tag. A tag created and created_by field can be set by the user, + // so we don't touch either of these if they are set. + if (!(int) $this->created_time) { + $this->created_time = $date->toSql(); + } + if (empty($this->created_user_id)) { + $this->created_user_id = $user->get('id'); + } + } + + // Verify that the alias is unique + $table = JTable::getInstance('Usertype', 'JsnTable'); + if ($table->load(array('alias' => $this->alias)) && ($table->id != $this->id || $this->id == 0)) + { + $this->setError(JText::_('COM_JSN_ERROR_UNIQUE_ALIAS')); + return false; + } + return parent::store($updateNulls); + } + + /** + * Method to delete a node and, optionally, its child nodes from the table. + * + * @param integer $pk The primary key of the node to delete. + * @param boolean $children True to delete child nodes, false to move them up a level. + * + * @return boolean True on success. + * + * @since 3.1 + * @see http://docs.joomla.org/JTableNested/delete + */ + public function delete($pk = null, $children = false) + { + return parent::delete($pk, $children); + //$helper = new JHelperTags; + //$helper->tagDeleteInstances($pk); + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit.php b/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit.php new file mode 100644 index 00000000..e2989931 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit.php @@ -0,0 +1,224 @@ +input; + +// Load the tooltip behavior. +JHtml::_('behavior.tooltip'); +JHtml::_('behavior.formvalidation'); +JHtml::_('behavior.keepalive'); +JHtml::_('formbehavior.chosen', 'select'); + +$doc = JFactory::getDocument(); +$doc->addStylesheet(JURI::root().'components/com_jsn/assets/css/jquery.sortable.css'); +$doc->addScript(JURI::root().'components/com_jsn/assets/js/jquery.sortable.min.js'); + +$user=JFactory::getUser(); + +// Create shortcut to parameters. +$params = $this->state->get('params'); +$params = $params->toArray(); + +if($input->get('id')>0) { + $this->form->setFieldAttribute('alias','readonly','true'); + $this->form->setFieldAttribute('type','readonly','true'); +} + +// Populate Fields Params +$this->form->setValue('params',null,(object)$this->item->params); + +?> + + + + + + +
    +
    + +
    + 'general')); ?> + + +
    +
    + form->getLabel('title'); ?> form->getInput('title'); ?> form->getLabel('catid'); ?> form->getInput('catid'); ?> +
    +
    + form->getLabel('alias'); ?> form->getInput('alias'); ?> +
    +
    + form->getLabel('type'); ?> item->type,array('username','usermail','password','registerdate','lastvisitdate'))) echo (''.$this->item->type.''); else echo $this->form->getInput('type'); ?> +
    + form->getInput('description'); ?> +
    + + + + loadTemplate('conditions'); ?> + loadTemplate('fieldoptions'); ?> + +
    + + +
    + + +
    +

    +
    +
    +
    +
    + form->getValue('title')); ?> +
    +
    +
    + form->getLabel('parent_id')); ?> +
    + form->getInput('parent_id'); ?> +
    +
    +
    + form->getLabel('published')); ?> +
    + item->core || !$user->authorise('core.edit.state', 'com_jsn')) $this->form->setFieldAttribute('published','disabled','true'); echo $this->form->getInput('published'); ?> +
    +
    +
    + form->getLabel('required')); ?> +
    + item->core && $this->item->alias!='avatar' && $this->item->alias!='secondname') $this->form->setFieldAttribute('required','disabled','true'); echo $this->form->getInput('required'); ?> +
    +
    +
    + form->getLabel('profile')); ?> +
    + item->core) $this->form->setFieldAttribute('profile','disabled','true');*/ echo $this->form->getInput('profile'); ?> +
    +
    +
    + form->getLabel('edit')); ?> +
    + item->core && $this->item->alias!='avatar') $this->form->setFieldAttribute('edit','disabled','true'); echo $this->form->getInput('edit'); ?> +
    +
    +
    + form->getLabel('register')); ?> +
    + item->core && $this->item->alias!='avatar') $this->form->setFieldAttribute('register','disabled','true'); echo $this->form->getInput('register'); ?> +
    +
    + item->type!='image' && $this->item->type!='delimeter' && $this->item->type!='password' && $this->item->type!='filetype') : ?> +
    + form->getLabel('search')); ?> +
    + item->core) $this->form->setFieldAttribute('profile','disabled','true');*/ echo $this->form->getInput('search'); ?> +
    +
    + +
    + form->getLabel('access')); ?> +
    + item->core) $this->form->setFieldAttribute('access','disabled','true');echo $this->form->getInput('access'); ?> +
    +
    +
    + form->getLabel('accessview')); ?> +
    + form->getInput('accessview'); ?> +
    +
    + +
    +
    + + +
    diff --git a/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_conditions.php b/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_conditions.php new file mode 100644 index 00000000..19fc7045 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_conditions.php @@ -0,0 +1,24 @@ + + + +
    +
    +
    form->getLabel('conditions'); ?>
    +
    form->getInput('conditions'); ?>
    +
    +
    + + + \ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_fieldoptions.php b/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_fieldoptions.php new file mode 100644 index 00000000..fc71e998 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_fieldoptions.php @@ -0,0 +1,56 @@ + + 'collapse0')); + $fieldSets = $this->form->getFieldsets('params'); + $i = 0; + + foreach ($fieldSets as $name => $fieldSet) : + if($name=='groups') continue; + $label = !empty($fieldSet->label) ? JText::_($fieldSet->label) : JText::_('COM_JSN_'.$name.'_FIELDSET_LABEL'); + echo JHtml::_('bootstrap'.JSNPREFIX.'.addTab', 'myTab', $name, $label); + if (isset($fieldSet->description) && trim($fieldSet->description)) : + echo '

    '.$this->escape(JText::_($fieldSet->description)).'

    '; + endif; + $field_class='Jsn'.ucfirst($name).'FieldHelper'; + if(class_exists($field_class) && method_exists($field_class, 'editScript')) echo $field_class::editScript(); + ?> + form->getFieldset($name) as $field) : ?> +
    +
    + label; ?> +
    +
    + input; ?> +
    +
    + + diff --git a/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_metadata.php b/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_metadata.php new file mode 100644 index 00000000..caff0f75 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_metadata.php @@ -0,0 +1,35 @@ + +
    + form->getLabel('metadesc'); ?> +
    + form->getInput('metadesc'); ?> +
    +
    +
    + form->getLabel('metakey'); ?> +
    + form->getInput('metakey'); ?> +
    +
    +form->getGroup('metadata') as $field): ?> +
    + hidden): ?> + label; ?> + +
    + input; ?> +
    +
    + diff --git a/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_options.php b/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_options.php new file mode 100644 index 00000000..08996135 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/field/tmpl/edit_options.php @@ -0,0 +1,65 @@ + + 'collapse0')); + $fieldSets = $this->form->getFieldsets('options'); + $i = 0; + + foreach ($fieldSets as $name => $fieldSet) : + $label = !empty($fieldSet->label) ? $fieldSet->label : 'COM_JSN_'.$name.'_FIELDSET_LABEL'; + echo JHtml::_('bootstrap.addSlide', 'categoryOptions', JText::_($label), 'collapse' . $i++); + if (isset($fieldSet->description) && trim($fieldSet->description)) : + echo '

    '.$this->escape(JText::_($fieldSet->description)).'

    '; + endif; + ?> + form->getFieldset($name) as $field) : ?> +
    +
    + label; ?> +
    +
    + input; ?> +
    +
    + + + +
    +
    + form->getLabel('note'); ?> +
    +
    + form->getInput('note'); ?> +
    +
    +
    +
    + form->getLabel('field_layout'); ?> +
    +
    + form->getInput('field_layout'); ?> +
    +
    +
    +
    + form->getLabel('field_link_class'); ?> +
    +
    + form->getInput('field_link_class'); ?> +
    +
    + input; + +// Load the tooltip behavior. +JHtml::_('behavior.tooltip'); +JHtml::_('behavior.formvalidation'); +JHtml::_('behavior.keepalive'); +JHtml::_('formbehavior.chosen', 'select'); + +// Create shortcut to parameters. +$params = $this->state->get('params'); +$params = $params->toArray(); + +?> + + + +
    +
    + +
    + 'general')); ?> + + +
    +
    + form->getLabel('title'); ?> form->getInput('title'); ?> form->getLabel('catid'); ?> form->getInput('catid'); ?> +
    +
    + form->getLabel('alias'); ?> form->getInput('alias'); ?> +
    + form->getFieldset('groups') as $field) : ?> +
    +
    + label; ?> +
    +
    + input; ?> +
    +
    + +
    + + + +
    + + +
    + + +
    +

    +
    +
    +
    +
    + form->getValue('title')); ?> +
    +
    + + +
    + form->getLabel('published'); ?> +
    + item->core) $this->form->setFieldAttribute('published','disabled','true'); echo $this->form->getInput('published'); ?> +
    +
    + +
    + form->getLabel('access'); ?> +
    + item->core) $this->form->setFieldAttribute('access','disabled','true'); echo $this->form->getInput('access'); ?> +
    +
    +
    + form->getLabel('accessview'); ?> +
    + form->getInput('accessview'); ?> +
    +
    + +
    +
    + + +
    diff --git a/deployed/jsn/administrator/components/com_jsn/views/field/view.html.php b/deployed/jsn/administrator/components/com_jsn/views/field/view.html.php new file mode 100644 index 00000000..20a215c2 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/field/view.html.php @@ -0,0 +1,112 @@ +form = $this->get('Form'); + $this->item = $this->get('Item'); + $this->state = $this->get('State'); + + $this->canDo = JsnHelperAdmin::getActions($this->state->get('fields.component')); + $input = JFactory::getApplication()->input; + + // Check for errors. + if (count($errors = $this->get('Errors'))) { + JFactory::getApplication()->enqueueMessage(implode("\n", $errors)); + return false; + } + + $input->set('hidemainmenu', true); + $this->addToolbar(); + + parent::display($tpl); + } + + /** + * Add the page title and toolbar. + * + * @since 3.1 + */ + protected function addToolbar() + { + $input = JFactory::getApplication()->input; + $user = JFactory::getUser(); + $userId = $user->get('id'); + + $isNew = ($this->item->id == 0); + $checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $userId); + + // Need to load the menu language file as mod_menu hasn't been loaded yet. + $lang = JFactory::getLanguage(); + $lang->load('com_jsn', JPATH_BASE, null, false, false) + || $lang->load('com_jsn', JPATH_ADMINISTRATOR.'/components/com_jsn', null, false, false) + || $lang->load('com_jsn', JPATH_BASE, $lang->getDefault(), false, false) + || $lang->load('com_jsn', JPATH_ADMINISTRATOR.'/components/com_jsn', $lang->getDefault(), false, false); + + // Load the fields helper. + require_once JPATH_COMPONENT.'/helpers/jsn.php'; + + // Get the results for each action. + $canDo = JsnHelperAdmin::getActions('com_jsn', $this->item->id); + + if($input->get('layout')=='edit') + $title = JText::_('COM_JSN_FIELD_'.($isNew?'ADD':'EDIT').'_TITLE'); + else + $title = JText::_('COM_JSN_FIELDGROUP_'.($isNew?'ADD':'EDIT').'_TITLE'); + + // Prepare the toolbar. + JToolbarHelper::title($title, 'field-'.($isNew?'add':'edit').($isNew?'add':'edit')); + + // For new records, check the create permission. + if ($isNew) + { + JToolbarHelper::apply('field.apply'); + JToolbarHelper::save('field.save'); + JToolbarHelper::save2new('field.save2new'); + } + + // If not checked out, can save the item. + elseif (!$checkedOut && ($canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_user_id == $userId))) { + JToolbarHelper::apply('field.apply'); + JToolbarHelper::save('field.save'); + if ($canDo->get('core.create')) { + JToolbarHelper::save2new('field.save2new'); + } + } + + // If an existing item, can save to a copy. + if (!$isNew && $canDo->get('core.create')) { + JToolbarHelper::save2copy('field.save2copy'); + } + + if (empty($this->item->id)) { + JToolbarHelper::cancel('field.cancel'); + } + else { + JToolbarHelper::cancel('field.cancel', 'JTOOLBAR_CLOSE'); + } + //JToolbarHelper::help('JHELP_COMPONENTS_FIELDS_MANAGER_EDIT'); + JToolbarHelper::divider(); + + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/views/fields/tmpl/default.php b/deployed/jsn/administrator/components/com_jsn/views/fields/tmpl/default.php new file mode 100644 index 00000000..91665a49 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/fields/tmpl/default.php @@ -0,0 +1,352 @@ +get('id'); +$listOrder = $this->escape($this->state->get('list.ordering')); +$listDirn = $this->escape($this->state->get('list.direction')); +$ordering = ($listOrder == 'a.lft'); +$canOrder = $user->authorise('core.edit.state', 'com_jsn'); +$saveOrder = ($listOrder == 'a.lft' && $listDirn == 'asc'); +if ($saveOrder) +{ + $saveOrderingUrl = 'index.php?option=com_jsn&task=fields.saveOrderAjax'; + JHtml::_('sortablelist.sortable', 'categoryList', 'adminForm', strtolower($listDirn), $saveOrderingUrl, false, true); +} +$sortFields = $this->getSortFields(); +?> + + +
    +sidebar)): ?> +
    + sidebar; ?> + authorise('core.admin', 'com_jsn')) : + $xml = JFactory::getXML(JPATH_ADMINISTRATOR .'/components/com_jsn/jsn.xml'); + $version = (string)$xml->version; + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + $query->select('version')->from('#__updates')->where('element = "com_jsn"'); + try { + $db->setQuery($query); + if($latest = $db->loadResult()) $update = '
    Installed version is outdated!'; + else $update = ''; + } + catch (Exception $e) { + $update = ''; + } + if(JSN_TYPE == 'free') $free_message = '

    This is a free version, go to Easy Profile Website to see our plan.'; + else $free_message = ''; + ?> +
    Easy Profile
    + +
    +
    + +
    + +
    + +
    + + +
    +
    + + pagination->getLimitBox(); ?> +
    +
    + + +
    +
    + + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + items as $i => $item) : + $orderkey = array_search($item->id, $this->ordering[$item->parent_id]); + $canCreate = $user->authorise('core.create', 'com_jsn'); + $canEdit = $user->authorise('core.edit', 'com_jsn'); + $canCheckin = $user->authorise('core.manage', 'com_checkin') || $item->checked_out == $user->get('id')|| $item->checked_out == 0; + $canChange = $user->authorise('core.edit.state', 'com_jsn') && $canCheckin; + // Get the parents of item for sorting + if ($item->level > 1) + { + $parentsStr = ""; + $_currentParentId = $item->parent_id; + $parentsStr = " ".$_currentParentId; + for ($j = 0; $j < $item->level; $j++) + { + foreach ($this->ordering as $k => $v) + { + $v = implode("-", $v); + $v = "-" . $v . "-"; + if (strpos($v, "-" . $_currentParentId . "-") !== false) + { + $parentsStr .= " " . $k; + $_currentParentId = $k; + break; + } + } + } + } + else + { + $parentsStr = ""; + } + ?> + level==1) echo('style="background:#f9f9f9"'); ?> > + + + + + + + + + + + + + + + + + + + + + + +
    + ', 'a.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING'); ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + pagination->getListFooter(); ?> +
    + + + + + + + + + + + + + id); ?> + + published, $i, 'fields.', ($item->core ? false : $canChange) );?> + + level > 0): ?> + —', $item->level - 1) ?> + + checked_out) : ?> + editor, $item->checked_out_time, 'fields.', $canCheckin); ?> + + level==1) : ?> + + escape($item->title)); ?> + + type!='delimeter' && !$item->core && !in_array($item->alias,$this->columns)) echo(' '); ?> + + escape($item->title)); ?> + + escape($item->title)); ?> + + + note)) : ?> + escape($item->alias));?> + + escape($item->alias), $this->escape($item->note));?> + + + + level==2) + { + if(!empty($item->conditions)) $conditions=json_decode($item->conditions); + else $conditions = array(); + $hasConditions = false; + $conditionsDisplay = '
      '; + foreach($conditions as $condition) + { + $hasConditions = true; + if(empty($condition->title)) $condition->title = 'Condition Description'; + $conditionsDisplay .= '
    • '.$condition->title.'
    • '; + } + $conditionsDisplay .= '
    '; + if($hasConditions) echo ''; + $privacy=$item->params->get('privacy',0); + $privacy_defaults=array(0 => 'COM_JSN_PUBLIC', 1 => 'COM_JSN_REGISTERED', 99 => 'COM_JSN_PRIVATE'); + $privacy_default=JText::_($privacy_defaults[$item->params->get('privacy_default',0)]); + if($privacy) echo ''; + $default_value=$item->params->get(str_replace(array('list_','usermail_'),array('_','mail_'),$item->type.'_defaultvalue'),''); + if($default_value!='') echo ''; + $custom_title_profile=$item->params->get('titleprofile',''); + $custom_title_search=$item->params->get('titlesearch',''); + $hide_profile_title=$item->params->get('hidetitle',0); + $hide_editprofile_title=$item->params->get('hidetitleedit',0); + + if($custom_title_profile!='' || $custom_title_search!='' || $hide_profile_title || $hide_editprofile_title) + { + $extra_message=array(); + if($custom_title_profile!='' && !$hide_profile_title) $extra_message[]=JText::_('COM_JSN_TITLEPROFILE').': '.$custom_title_profile; + if($custom_title_search!='') $extra_message[]=JText::_('COM_JSN_TITLESEARCH').': '.$custom_title_profile; + if($hide_profile_title) $extra_message[]=JText::_('COM_JSN_HIDETITLEPROFILE').': '.JText::_('JYES'); + if($hide_editprofile_title) $extra_message[]=JText::_('COM_JSN_HIDETITLEFORM').': '.JText::_('JYES'); + echo ''; + } + } + ?> +
    + core, $i, false);?> + + level==2) echo JHtml::_('field.required', $item->required, $i, ($item->core && $item->alias!='avatar' && $item->alias!='secondname' ? false : $canChange) );?> + + level==2) echo JHtml::_('field.profile', $item->profile, $i,$canChange );?> + + level==2) echo JHtml::_('field.edit', $item->edit, $i, ($item->core && $item->alias!='avatar' ? false : $canChange) );?> + + level==2) echo JHtml::_('field.register', $item->register, $i, ($item->core && $item->alias!='avatar' ? false : $canChange) );?> + + level==2 && $item->type!='image' && $item->type!='delimeter' && $item->type!='password' && $item->type!='filetype') echo JHtml::_('field.search', $item->search, $i, $canChange );?> + + level==2) echo $item->type; ?> + + escape($item->access_title); ?> + + escape($item->accessview_title); ?> + + + id; ?> +
    + + loadTemplate('batch'); ?> + + + + + + + +
    + diff --git a/deployed/jsn/administrator/components/com_jsn/views/fields/tmpl/default_batch.php b/deployed/jsn/administrator/components/com_jsn/views/fields/tmpl/default_batch.php new file mode 100644 index 00000000..5ae12d84 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/fields/tmpl/default_batch.php @@ -0,0 +1,53 @@ +state->get('filter.published'); +?> + diff --git a/deployed/jsn/administrator/components/com_jsn/views/fields/view.html.php b/deployed/jsn/administrator/components/com_jsn/views/fields/view.html.php new file mode 100644 index 00000000..111f2b2c --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/fields/view.html.php @@ -0,0 +1,218 @@ +checklist(); + $this->state = $this->get('State'); + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + + foreach($this->items as $item) + { + $registry = new JRegistry; + $registry->loadString($item->params); + $item->params = $registry; + } + + $db=JFactory::getDbo(); + $query = $db->getQuery(true); + $query = "SHOW COLUMNS FROM #__jsn_users"; + $db->setQuery( $query ); + $result=$db->loadObjectList(); + $columns=array(); + foreach($result as $column) + { + $columns[]=$column->Field; + } + $this->columns=$columns; + + JsnHelperAdmin::addSubmenu('fields'); + + // Check for errors. + if (count($errors = $this->get('Errors'))) { + JFactory::getApplication()->enqueueMessage(implode("\n", $errors)); + return false; + } + // Preprocess the list of items to find ordering divisions. + foreach ($this->items as &$item) + { + $this->ordering[$item->parent_id][] = $item->id; + } + + // Levels filter. + $options = array(); + $options[] = JHtml::_('select.option', '1', JText::_('J1')); + $options[] = JHtml::_('select.option', '2', JText::_('J2')); + $options[] = JHtml::_('select.option', '3', JText::_('J3')); + $options[] = JHtml::_('select.option', '4', JText::_('J4')); + $options[] = JHtml::_('select.option', '5', JText::_('J5')); + $options[] = JHtml::_('select.option', '6', JText::_('J6')); + $options[] = JHtml::_('select.option', '7', JText::_('J7')); + $options[] = JHtml::_('select.option', '8', JText::_('J8')); + $options[] = JHtml::_('select.option', '9', JText::_('J9')); + $options[] = JHtml::_('select.option', '10', JText::_('J10')); + + $this->f_levels = $options; + + $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + parent::display($tpl); + } + + /** + * Add the page title and toolbar. + * + * @since 3.1 + */ + protected function addToolbar() + { + $state = $this->get('State'); + $canDo = JsnHelperAdmin::getActions($state->get('filter.parent_id')); + $user = JFactory::getUser(); + // Get the toolbar object instance + $bar = JToolBar::getInstance('toolbar'); + + JToolbarHelper::title(JText::_('COM_JSN_MANAGER_FIELDS'), 'modules.png'); + + if ($canDo->get('core.create')) + { + JToolbarHelper::custom('field.addgroup','new','new',JText::_('COM_JSN_NEW_FIELDGROUP'),false,false); + JToolbarHelper::addNew('field.add',JText::_('COM_JSN_NEW_FIELD')); + } + + if ($canDo->get('core.edit')) + { + //JToolbarHelper::editList('field.edit'); Not work with fieldgroups + } + + if ($canDo->get('core.edit.state')) + { + JToolbarHelper::publish('fields.publish', 'JTOOLBAR_PUBLISH', true); + JToolbarHelper::unpublish('fields.unpublish', 'JTOOLBAR_UNPUBLISH', true); + JToolbarHelper::archiveList('fields.archive'); + } + if ($canDo->get('core.admin')) + { + JToolbarHelper::checkin('fields.checkin'); + } + if ($state->get('filter.published') == -2 && $canDo->get('core.delete')) + { + JToolbarHelper::deleteList('', 'fields.delete', 'JTOOLBAR_EMPTY_TRASH'); + } + elseif ($canDo->get('core.edit.state')) + { + JToolbarHelper::trash('fields.trash'); + } + // Add a batch button + if ($user->authorise('core.edit')) + { + JHtml::_('bootstrap.modal', 'collapseModal'); + $title = JText::_('JTOOLBAR_BATCH'); + $dhtml = ""; + $bar->appendButton('Custom', $dhtml, 'batch'); + } + if ($canDo->get('core.admin')) + { + JToolbarHelper::custom('syncuser','refresh','','Sync User',false); + } + if ($canDo->get('core.admin')) + { + JToolbarHelper::preferences('com_jsn'); + } + //JToolbarHelper::help('JHELP_COMPONENTS_FIELDS_MANAGER'); + + JHtmlSidebar::setAction('index.php?option=com_jsn&view=fields'); + + JHtmlSidebar::addFilter( + JText::_('JOPTION_SELECT_PUBLISHED'), + 'filter_published', + JHtml::_('select.options', JHtml::_('jgrid.publishedOptions'), 'value', 'text', $this->state->get('filter.published'), true) + ); + + JHtmlSidebar::addFilter( + JText::_('JOPTION_SELECT_ACCESS'), + 'filter_access', + JHtml::_('select.options', JHtml::_('access.assetgroups'), 'value', 'text', $this->state->get('filter.access')) + ); + + /*JHtmlSidebar::addFilter( + JText::_('JOPTION_SELECT_LANGUAGE'), + 'filter_language', + JHtml::_('select.options', JHtml::_('contentlanguage.existing', true, true), 'value', 'text', $this->state->get('filter.language')) + );*/ + } + + /** + * Returns an array of fields the table can be sorted by + * + * @return array Array containing the field name to sort by as the key and display text as value + * + * @since 3.0 + */ + protected function getSortFields() + { + return array( + 'a.lft' => JText::_('JGRID_HEADING_ORDERING'), + 'a.state' => JText::_('JSTATUS'), + 'a.title' => JText::_('JGLOBAL_TITLE'), + 'a.access' => JText::_('JGRID_HEADING_ACCESS'), + 'language' => JText::_('JGRID_HEADING_LANGUAGE'), + 'a.id' => JText::_('JGRID_HEADING_ID') + ); + } + + protected function checklist() + { + $app=JFactory::getApplication(); + $db=JFactory::getDbo(); + $query=$db->getQuery(true); + $query->select('id')->from('#__menu')->where('link = "index.php?option=com_jsn&view=profile" AND published = 1'); + $db->setQuery($query); + if(!$db->loadResult()) $app->enqueueMessage(JText::_('COM_JSN_CHECKLIST_ALERT_EASYPROFILE_MENU_ITEM'),'notice'); + $query=$db->getQuery(true); + $query->select('id')->from('#__jsn_fields')->where('published = 1 AND parent_id = 2 AND edit = 1 AND register = 1'); + $db->setQuery($query); + if(!$db->loadResult()) $app->enqueueMessage(JText::_('COM_JSN_CHECKLIST_ALERT_DEFAULT_FIELDGROUP'),'error'); + $query=$db->getQuery(true); + $query->select('id')->from('#__menu')->where('link = "index.php?option=com_users&view=registration" AND published = 1 AND access = 1'); + $db->setQuery($query); + if($db->loadResult()) $app->enqueueMessage(JText::_('COM_JSN_CHECKLIST_ALERT_REGISTRATION_MENU_ITEM'),'error'); + + $jsnConfig=JComponentHelper::getParams('com_jsn'); + if($jsnConfig->get('googlemaps_apikey','')=='') + { + $query=$db->getQuery(true); + $query->select('id')->from('#__jsn_fields')->where('published = 1 AND type = "gmap"'); + $db->setQuery($query); + if($db->loadResult()) $app->enqueueMessage(JText::_('COM_JSN_CHECKLIST_ALERT_GOOGLEMAPS_KEY'),'error'); + } + if($jsnConfig->get('download_id','')=='') + { + $app->enqueueMessage(JText::_('COM_JSN_CHECKLIST_ALERT_DOWNLOADID'),'notice'); + } + + } +} diff --git a/deployed/jsn/administrator/components/com_jsn/views/import/tmpl/default.php b/deployed/jsn/administrator/components/com_jsn/views/import/tmpl/default.php new file mode 100644 index 00000000..e4ce6ddd --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/import/tmpl/default.php @@ -0,0 +1,368 @@ +authorise('core.admin.import', 'com_jsn')) { + die('No access'); +} + +// Include the component HTML helpers. +JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); + +$app = JFactory::getApplication(); +$user = JFactory::getUser(); +$userId = $user->get('id'); + +if (!empty( $this->sidebar)): ?> +
    + sidebar; ?> +
    +
    + +
    +init(); + +class UserImportAdmin +{ + //private $filecontent; + private $csv; + private $j_fields = array('id','name','username','email','password','password_clear','block','sendEmail','registerDate','lastvisitDate','activation','params','lastResetTime','resetCount','otpKey','otep','requireReset','groups'); + private $jsn_fields; + private $jsn_fields_multiple; + //private $fields; + public function __construct() + { + $this->filecontent=''; + } + + public static function getInstance() + { + static $cache=null; + if (!isset($cache)) + { + $cache=new UserImportAdmin(); + } + return $cache; + } + + public function init() + { + if(JFactory::getApplication()->input->getVar('goimport',false)) + { + if(isset($_FILES['filecsv']) && !empty($_FILES['filecsv']['name'])) + { + //require_once(JPATH_SITE.'/components/com_jsn/helpers/helper.php'); + require_once(JPATH_SITE.'/components/com_jsn/helpers/parsecsv.lib.php'); + $this->csv=new parseCSV(); + /* TODO ENCODING */ + $content = file_get_contents($_FILES['filecsv']['tmp_name']); + $firstline = strtok($content, "\n"); + $firstline = preg_replace('/[^A-Za-z0-9\-,;_\r"]/', '', $firstline); + $content=$firstline."\n".preg_replace('/^.+\n/', '', $content); + $this->csv->auto($content); + $this->check(); + } + else + { + $app=JFactory::getApplication(); + $app->enqueueMessage('No file selected','error'); + $this->getForm(); + } + } + else + { + $this->getForm(); + } + } + + private function getForm() + { + $plugin = JPluginHelper::getPlugin('user','joomla'); + $db=JFactory::getDbo(); + $query=$db->getQuery(true); + $query->select('extension_id')->from('#__extensions')->where('name = '.$db->quote('plg_user_joomla')); + $db->setQuery($query); + $pluginId = $db->loadResult(); + $params = new JRegistry($plugin->params); + echo(' + +
    + RULES AND NOTE +
      +
    • Fields that should never miss: email, and name or firstname
    • +
    • Import only from CSV files (Comma Separated Values)
    • +
    • The first row of CSV file determines the columns (alias of field)
    • +
    • Existing user are identified by email
    • +
    • If missing password or password_clear column, new password will be generated for new users
    • +
    • If missing username column, it will be generated for new users
    • +
    • "password" column set the hash of password (useful when import from a old Joomla installation)
    • +
    • "password_clear" column set the password
    • +
    • "groups" column set Joomla usergroups, default registration usergroup (Registered) will be always assigned +
    + Some Examples: +
    username,email,password_clear,firstname,lastname,interests
    +john,john@test.it,passwordofjohn,John,Doe,"music,art"
    +mark,mark@test.com,passwordofmark,Mark,White,art
    +
    email;password_clear;firstname;lastname;gender
    +john@test.it;passwordofjohn;John;Doe;male
    +mark@test.com;passwordofmark;Mark;White;male
    +
    email,name,gender,groups
    +"john@test.it","John Doe","male","Author,Manager"
    +"mark@test.com","Mark White","male","Publisher"
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + '); + } + + private function check() + { + $error=false; + $errorField=array(); + + // Check required fields + if(!in_array('email',$this->csv->titles)) + { + $error=true; + $errorField[]='Email'; + } + /*if(!in_array('name',$this->csv->titles) && !in_array('firstname',$this->csv->titles)) + { + $error=true; + $errorField[]='Name or Firstname'; + }*/ + if($error) + { + $app=JFactory::getApplication(); + $app->enqueueMessage('Missing some required fields: '.implode(', ',$errorField),'error'); + $this->getForm(); + return; + } + + // Check known fields + $db=JFactory::getDbo(); + $query=$db->getQuery(true); + $query->select('alias')->from('#__jsn_fields')->where($db->quoteName('level').' = 2')->where($db->quoteName('type').' != '.$db->quote('delimeter')); + $db->setQuery($query); + $this->jsn_fields=$db->loadColumn(); + foreach($this->csv->titles as $field) + { + $from=array('_lat','_lng'); + $to=array('',''); + $field=str_replace($from,$to,$field); + if(!in_array($field,$this->j_fields) && !in_array($field,$this->jsn_fields)) + { + $error=true; + $errorField[]=$field; + } + } + if($error) + { + $app=JFactory::getApplication(); + if(count($errorField)==1) $app->enqueueMessage(implode(', ',$errorField).' column is unknown and will be skipped','warning'); + else $app->enqueueMessage(implode(', ',$errorField).' columns are unknown and will be skipped','warning'); + + } + + $this->import(); + + + } + + private function import() + { + $app=JFactory::getApplication(); + $db=JFactory::getDbo(); + $log_error=array(); + $log_new=0; + $log_updated=0; + $counter=0; + + $query=$db->getQuery(true); + $query->select('alias')->from('#__jsn_fields')->where($db->quoteName('level').' = 2') + ->where('('.$db->quoteName('type').' = '.$db->quote('checkboxlist').' OR ('. $db->quoteName('type').' = '.$db->quote('selectlist').' AND '.$db->quoteName('params').' LIKE '.$db->quote('%"select_multiple":"1"%').'))'); + $db->setQuery($query); + $this->jsn_fields_multiple=$db->loadColumn(); + + $query=$db->getQuery(true); + $query->select('id,title')->from('#__usergroups'); + $db->setQuery($query); + $usergroups=$db->loadAssocList('title'); + + foreach($this->csv->data as $userRow) + { + $counter+=1; + + // Check Correct Email Address + if (!filter_var($userRow['email'], FILTER_VALIDATE_EMAIL)) { + $log_error[]='- Email not valid in row '.($counter+1); + continue; + } + + // Compose Name + if(!empty($userRow['name']) && empty($userRow['firstname'])) + { + $userRow['firstname']=$userRow['name']; // TODO split name based on JSN config + } + elseif(empty($userRow['name']) && !empty($userRow['firstname'])) + { + $userRow['name']=$userRow['firstname']; + if(!empty($userRow['secondname'])) $userRow['name'].=' '.$userRow['secondname']; + if(!empty($userRow['lastname'])) $userRow['name'].=' '.$userRow['lastname']; + } + + // Check if user already exists + $query=$db->getQuery(true); + $query->select('id')->from('#__users')->where($db->quoteName('email').' = '.$db->quote($userRow['email'])); + $db->setQuery($query); + $exist=$db->loadResult(); + + // Check if name is available and not empty (only for new users) + if(empty($userRow['name']) && !$exist) + { + $log_error[]='- Missing name or firstname in row '.($counter+1); + continue; + } + + // UserGroup to Array + $jUserConfig = JComponentHelper::getParams('com_users'); + $defaultGroup=$jUserConfig->get('new_usertype',2); + if(!empty($userRow['groups'])) + { + foreach ($usergroups as $k => $v) + { + $userRow['groups'] = str_ireplace($k,$v['id'],$userRow['groups']); + } + $userRow['groups']=explode(',',$userRow['groups']); + if(!in_array($defaultGroup,$userRow['groups'])) $userRow['groups'][]=$defaultGroup; + } + else{ + if(!$exist) $userRow['groups']=array($defaultGroup); + else unset($userRow['groups']); + } + + if(!$exist) + { + // Add User + $user=new JUser(); + + // If missing password_clear and password assign Random Password + if(empty($userRow['password']) && empty($userRow['password_clear'])) + { + $userRow['password_clear']=JUserHelper::genRandomPassword(); + } + if(empty($userRow['password'])) + { + $salt=JUserHelper::getSalt(); + $userRow['password']=JUserHelper::getCryptedPassword($userRow['password_clear'],$salt); + } + // If missing username assign Username based on Name + $jsnConfig = JComponentHelper::getParams('com_jsn'); + if(empty($userRow['username']) && $jsnConfig->get('logintype', 'USERNAME')!='MAIL') + { + $username=JApplication::stringURLSafe($userRow['name']); + if( ! trim($username,'-_ ') ){ + $username='user_'.date('YmdHis').rand(0,2000); + } + else $username .= '_'.rand(0,2000); + $userRow['username']=$username; + } + elseif(empty($userRow['username'])){ + $userRow['username']=$userRow['email']; + } + + $log_new+=1; + } + else + { + // Update User if requested + if(!JFactory::getApplication()->input->getVar('overwrite',false)) continue; + + // Load User + $user=JFactory::getUser($exist); + + // Remove Name if empty + if(empty($userRow['name'])) { + unset($userRow['name']); + unset($userRow['firstname']); + unset($userRow['secondname']); + unset($userRow['lastname']); + } + + // Remove Username if empty + if(empty($userRow['username'])) unset($userRow['username']); + + // Update password if available password_clear + if(!empty($userRow['password_clear'])) + { + $salt=JUserHelper::getSalt(); + $userRow['password']=JUserHelper::getCryptedPassword($userRow['password_clear'],$salt); + } + + $log_updated+=1; + } + + foreach($userRow as $k => $v) + { + $from=array('_lat','_lng'); + $to=array('',''); + $field=str_replace($from,$to,$k); + if($field!='id' && (in_array($field,$this->j_fields) || in_array($field,$this->jsn_fields))) + { + if(in_array($k, $this->jsn_fields_multiple)) + { + $v=explode(',',$v); + } + $user->set($k,$v); + } + } + + $user->save((boolean)$exist); + + } + $app->enqueueMessage( 'New imported users: '.$log_new.'','notice'); + $app->enqueueMessage('Updated users: '.$log_updated.'','notice'); + if(count($log_error)) + { + $app->enqueueMessage( 'Errors: '.count($log_error).'
    '.implode('
    ', $log_error ),'error'); + } + + } +} +?>
    + \ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/views/import/view.html.php b/deployed/jsn/administrator/components/com_jsn/views/import/view.html.php new file mode 100644 index 00000000..bd0451c9 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/import/view.html.php @@ -0,0 +1,38 @@ +get('Errors'))) { + JFactory::getApplication()->enqueueMessage(implode("\n", $errors)); + return false; + } + JToolbarHelper::title(JText::_('COM_JSN_IMPORT_USERS'), 'modules.png'); + JsnHelperAdmin::addSubmenu('fields'); + $this->sidebar = JHtmlSidebar::render(); + parent::display($tpl); + } + +} diff --git a/deployed/jsn/administrator/components/com_jsn/views/users/tmpl/default.php b/deployed/jsn/administrator/components/com_jsn/views/users/tmpl/default.php new file mode 100644 index 00000000..018c4d77 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/users/tmpl/default.php @@ -0,0 +1,81 @@ +input->get('export','false') == 'true') {echo $this->loadTemplate('export');} + +$doc = JFactory::getDocument(); +$doc->addStylesheet(JURI::root().'components/com_jsn/assets/css/style.min.css'); +$module = new stdClass(); +$module->id='_admin'; + +$db = JFactory::getDbo(); +$query = $db->getQuery(true); +$query->select('id')->from('#__jsn_fields')->where('search = 1'); +$column = $db->setQuery($query)->loadColumn(); + +if(file_exists(JPATH_ADMINISTRATOR .'/templates/isis/html/com_users/users/default.php' ) ) include(JPATH_ADMINISTRATOR .'/templates/isis/html/com_users/users/default.php' ); +else include(JPATH_COMPONENT . '/../com_users/views/users/tmpl/default.php'); + +if(count($column)) { + $params = new JRegistry(); + $params->set('search_fields',$column); + + include(JPATH_SITE . '/modules/mod_jsnsearch/helper.php'); + + ModJsnSearch::getJavascript($module,$params); + + include(JPATH_SITE . '/modules/mod_jsnsearch/tmpl/default.php'); +?> + + + + + + \ No newline at end of file diff --git a/deployed/jsn/administrator/components/com_jsn/views/users/tmpl/default_batch.php b/deployed/jsn/administrator/components/com_jsn/views/users/tmpl/default_batch.php new file mode 100644 index 00000000..91a312a6 --- /dev/null +++ b/deployed/jsn/administrator/components/com_jsn/views/users/tmpl/default_batch.php @@ -0,0 +1,12 @@ + div { + display: none; + min-width: 220px; +} +.jsndatepicker table { + width: 100%; + margin: 0; +} +.jsndatepicker td, +.jsndatepicker th { + text-align: center; + width: 20px; + height: 20px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.jsndatepicker td.day:hover { + background: #eeeeee; + cursor: pointer; +} +.jsndatepicker td.day.disabled { + color: #eeeeee; +} +.jsndatepicker td.old, +.jsndatepicker td.new { + color: #999999; +} +.jsndatepicker td.active, +.jsndatepicker td.active:hover { + color: #ffffff; + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #0044cc; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.jsndatepicker td.active:hover, +.jsndatepicker td.active:hover:hover, +.jsndatepicker td.active:focus, +.jsndatepicker td.active:hover:focus, +.jsndatepicker td.active:active, +.jsndatepicker td.active:hover:active, +.jsndatepicker td.active.active, +.jsndatepicker td.active:hover.active, +.jsndatepicker td.active.disabled, +.jsndatepicker td.active:hover.disabled, +.jsndatepicker td.active[disabled], +.jsndatepicker td.active:hover[disabled] { + color: #ffffff; + background-color: #0044cc; + *background-color: #003bb3; +} +.jsndatepicker td.active:active, +.jsndatepicker td.active:hover:active, +.jsndatepicker td.active.active, +.jsndatepicker td.active:hover.active { + background-color: #003399 \9; +} +.jsndatepicker td span { + display: block; + width: 47px; + height: 54px; + line-height: 54px; + float: left; + margin: 2px; + cursor: pointer; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.jsndatepicker td span:hover { + background: #eeeeee; +} +.jsndatepicker td span.active { + color: #ffffff; + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #0044cc; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.jsndatepicker td span.active:hover, +.jsndatepicker td span.active:focus, +.jsndatepicker td span.active:active, +.jsndatepicker td span.active.active, +.jsndatepicker td span.active.disabled, +.jsndatepicker td span.active[disabled] { + color: #ffffff; + background-color: #0044cc; + *background-color: #003bb3; +} +.jsndatepicker td span.active:active, +.jsndatepicker td span.active.active { + background-color: #003399 \9; +} +.jsndatepicker td span.old { + color: #999999; +} +.jsndatepicker th.switch { + width: 145px; +} +.jsndatepicker th.next, +.jsndatepicker th.prev { + font-size: 21px; +} +.jsndatepicker thead tr:first-child th { + cursor: pointer; +} +.jsndatepicker thead tr:first-child th:hover { + background: #eeeeee; +} +.input-append.date .add-on i, +.input-prepend.date .add-on i { + display: block; + cursor: pointer; + width: 16px; + height: 16px; +} diff --git a/deployed/jsn/components/com_jsn/assets/css/datepicker.min.css b/deployed/jsn/components/com_jsn/assets/css/datepicker.min.css new file mode 100644 index 00000000..36c197ff --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/datepicker.min.css @@ -0,0 +1 @@ +.jsndatepicker{top:0;left:0;padding:4px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.jsndatepicker:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute;top:-7px;left:6px}.jsndatepicker:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:7px}.jsndatepicker > div{display:none;min-width: 220px}.jsndatepicker table{width:100%;margin:0}.jsndatepicker td,.jsndatepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.jsndatepicker td.day:hover{background:#eee;cursor:pointer}.jsndatepicker td.day.disabled{color:#eee}.jsndatepicker td.old,.jsndatepicker td.new{color:#999}.jsndatepicker td.active,.jsndatepicker td.active:hover{color:#fff;background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#04c;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.jsndatepicker td.active:hover,.jsndatepicker td.active:hover:hover,.jsndatepicker td.active:focus,.jsndatepicker td.active:hover:focus,.jsndatepicker td.active:active,.jsndatepicker td.active:hover:active,.jsndatepicker td.active.active,.jsndatepicker td.active:hover.active,.jsndatepicker td.active.disabled,.jsndatepicker td.active:hover.disabled,.jsndatepicker td.active[disabled],.jsndatepicker td.active:hover[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.jsndatepicker td.active:active,.jsndatepicker td.active:hover:active,.jsndatepicker td.active.active,.jsndatepicker td.active:hover.active{background-color:#039 \9}.jsndatepicker td span{display:block;width:47px;height:54px;line-height:54px;float:left;margin:2px;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.jsndatepicker td span:hover{background:#eee}.jsndatepicker td span.active{color:#fff;background-color:#006dcc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#04c;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.jsndatepicker td span.active:hover,.jsndatepicker td span.active:focus,.jsndatepicker td span.active:active,.jsndatepicker td span.active.active,.jsndatepicker td span.active.disabled,.jsndatepicker td span.active[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.jsndatepicker td span.active:active,.jsndatepicker td span.active.active{background-color:#039 \9}.jsndatepicker td span.old{color:#999}.jsndatepicker th.switch{width:145px}.jsndatepicker th.next,.jsndatepicker th.prev{font-size:21px}.jsndatepicker thead tr:first-child th{cursor:pointer}.jsndatepicker thead tr:first-child th:hover{background:#eee}.input-append.date .add-on i,.input-prepend.date .add-on i{display:block;cursor:pointer;width:16px;height:16px} \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/css/icons.css b/deployed/jsn/components/com_jsn/assets/css/icons.css new file mode 100644 index 00000000..da0d3636 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/icons.css @@ -0,0 +1,111 @@ +@font-face { + font-family: 'jsn-icons'; + src: url('../fonts/jsn-icons.eot?eca0j6'); + src: url('../fonts/jsn-icons.eot?eca0j6#iefix') format('embedded-opentype'), + url('../fonts/jsn-icons.ttf?eca0j6') format('truetype'), + url('../fonts/jsn-icons.woff?eca0j6') format('woff'), + url('../fonts/jsn-icons.svg?eca0j6#jsn-icons') format('svg'); + font-weight: normal; + font-style: normal; +} + +.jsn-icon { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'jsn-icons' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.jsn-icon.jsn-icon-user:before { + content: "\f007"; +} +.jsn-icon.jsn-icon-close:before { + content: "\f00d"; +} +.jsn-icon.jsn-icon-remove:before { + content: "\f00d"; +} +.jsn-icon.jsn-icon-times:before { + content: "\f00d"; +} +.jsn-icon.jsn-icon-cog:before { + content: "\f013"; +} +.jsn-icon.jsn-icon-gear:before { + content: "\f013"; +} +.jsn-icon.jsn-icon-clock-o:before { + content: "\f017"; +} +.jsn-icon.jsn-icon-pencil:before { + content: "\f040"; +} +.jsn-icon.jsn-icon-map-marker:before { + content: "\f041"; +} +.jsn-icon.jsn-icon-check-circle-o:before { + content: "\f05d"; +} +.jsn-icon.jsn-icon-mail-forward:before { + content: "\f064"; +} +.jsn-icon.jsn-icon-share:before { + content: "\f064"; +} +.jsn-icon.jsn-icon-eye:before { + content: "\f06e"; +} +.jsn-icon.jsn-icon-eye-slash:before { + content: "\f070"; +} +.jsn-icon.jsn-icon-calendar:before { + content: "\f073"; +} +.jsn-icon.jsn-icon-twitter:before { + content: "\f099"; +} +.jsn-icon.jsn-icon-facebook:before { + content: "\f09a"; +} +.jsn-icon.jsn-icon-facebook-f:before { + content: "\f09a"; +} +.jsn-icon-globe:before { + content: "\f0ac"; +} +.jsn-icon.jsn-icon-group:before { + content: "\f0c0"; +} +.jsn-icon.jsn-icon-users:before { + content: "\f0c0"; +} +.jsn-icon.jsn-icon-google-plus:before { + content: "\f0d5"; +} +.jsn-icon.jsn-icon-linkedin:before { + content: "\f0e1"; +} +.jsn-icon.jsn-icon-shield:before { + content: "\f132"; +} +.jsn-icon-instagram:before { + content: "\f16d"; +} +.jsn-icon.jsn-icon-paper-plane:before { + content: "\f1d8"; +} +.jsn-icon.jsn-icon-send:before { + content: "\f1d8"; +} +.jsn-icon.jsn-icon-user-secret:before { + content: "\f21b"; +} + diff --git a/deployed/jsn/components/com_jsn/assets/css/icons.min.css b/deployed/jsn/components/com_jsn/assets/css/icons.min.css new file mode 100644 index 00000000..8d7ec6f4 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/icons.min.css @@ -0,0 +1 @@ +@font-face{font-family:'jsn-icons';src:url(../fonts/jsn-icons.eot?eca0j6);src:url(../fonts/jsn-icons.eot?eca0j6#iefix) format("embedded-opentype"),url(../fonts/jsn-icons.ttf?eca0j6) format("truetype"),url(../fonts/jsn-icons.woff?eca0j6) format("woff"),url(../fonts/jsn-icons.svg?eca0j6#jsn-icons) format("svg");font-weight:400;font-style:normal}.jsn-icon{font-family:'jsn-icons'!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.jsn-icon.jsn-icon-user:before{content:"\f007"}.jsn-icon.jsn-icon-close:before{content:"\f00d"}.jsn-icon.jsn-icon-remove:before{content:"\f00d"}.jsn-icon.jsn-icon-times:before{content:"\f00d"}.jsn-icon.jsn-icon-cog:before{content:"\f013"}.jsn-icon.jsn-icon-gear:before{content:"\f013"}.jsn-icon.jsn-icon-clock-o:before{content:"\f017"}.jsn-icon.jsn-icon-pencil:before{content:"\f040"}.jsn-icon.jsn-icon-map-marker:before{content:"\f041"}.jsn-icon.jsn-icon-check-circle-o:before{content:"\f05d"}.jsn-icon.jsn-icon-mail-forward:before{content:"\f064"}.jsn-icon.jsn-icon-share:before{content:"\f064"}.jsn-icon.jsn-icon-eye:before{content:"\f06e"}.jsn-icon.jsn-icon-eye-slash:before{content:"\f070"}.jsn-icon.jsn-icon-calendar:before{content:"\f073"}.jsn-icon.jsn-icon-twitter:before{content:"\f099"}.jsn-icon.jsn-icon-facebook:before{content:"\f09a"}.jsn-icon.jsn-icon-facebook-f:before{content:"\f09a"}.jsn-icon-globe:before{content:"\f0ac"}.jsn-icon.jsn-icon-group:before{content:"\f0c0"}.jsn-icon.jsn-icon-users:before{content:"\f0c0"}.jsn-icon.jsn-icon-google-plus:before{content:"\f0d5"}.jsn-icon.jsn-icon-linkedin:before{content:"\f0e1"}.jsn-icon.jsn-icon-shield:before{content:"\f132"}.jsn-icon-instagram:before{content:"\f16d"}.jsn-icon.jsn-icon-paper-plane:before{content:"\f1d8"}.jsn-icon.jsn-icon-send:before{content:"\f1d8"}.jsn-icon.jsn-icon-user-secret:before{content:"\f21b"} \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/css/imgpicker.css b/deployed/jsn/components/com_jsn/assets/css/imgpicker.css new file mode 100644 index 00000000..168b456f --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/imgpicker.css @@ -0,0 +1,170 @@ +.ip-modal { + display: none; + overflow: auto; + overflow-y: scroll; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 99999; + -webkit-overflow-scrolling: touch; + background: rgba(0, 0, 0, 0.5); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#807f7f7f', endColorstr='#b3000000', GradientType=1)"; +} +.ip-modal-dialog { + position: relative; + width: 500px; + margin: 30px auto; +} +@media all and (max-width: 568px) { + .ip-modal-dialog { + width: auto; + margin: 5px; + } +} +.ip-modal-content { + background-color: #fff; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); + border-top: 5px solid #000; +} +.ip-modal-header { + padding: 10px 15px; + border-bottom: 1px solid #e5e5e5; +} +.ip-modal-title { + margin: 0; + line-height: 1.42857143; + font-size: 18px; +} +.ip-modal-header .ip-close, +.ip-alert .dismiss { + float: right; + font-size: 24px; + font-weight: 700; + line-height: 1.2; + color: #000; + opacity: .2; + filter: alpha(opacity=20); + cursor: pointer; +} +.ip-modal-header .ip-close:hover, +.ip-alert .dismiss:hover { + opacity: .5; + filter: alpha(opacity=50); + text-decoration: none; + color: #000 +} +.ip-alert .dismiss { + font-size: 18px; + line-height: 1; +} +.ip-modal-body { + padding: 10px 15px 15px; +} +.ip-modal-footer { + padding: 10px 15px 10px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.ip-modal-footer .ip-actions { + float: left; +} +.ip-upload { + display: inline-block; + position: relative; + overflow: hidden; +} +.ip-upload .ip-file { + position: absolute; + top: 0; + right: 0; + margin: 0; + padding: 0; + font-size: 20px; + cursor: pointer; + opacity: 0; + filter: alpha(opacity=0); +} +body .ip-preview, body .ip-save, body .ip-capture, body .ip-edit, body .ip-delete, +body .ip-cancel, body .ip-progress, body .ip-alert, body .ip-rotate, body .ip-info, +body .ip-preview.btn, body .ip-save.btn, body .ip-capture.btn, body .ip-edit.btn, body .ip-delete.btn, +body .ip-cancel.btn, body .ip-progress.btn, body .ip-alert.btn, body .ip-rotate.btn, body .ip-info.btn { + display: none; +} +.ip-preview video { + width: 100% !important; + height: auto !important; + max-width: 470px; +} +.ip-progress .text { + font-size: 13px; + padding-bottom: 2px; +} +.ip-preview, .ip-alert, .ip-progress { + margin-top: 10px; +} +.ip-preview > img { + max-width: 100%; + height: auto; + max-height: 400px; + display: block; + margin: 0 auto; +} +.ip-info { + font-size: 12px; + padding: 10px 0 0; +} +.ip-rotate { + text-align: center; + margin: 5px 0 -10px; +} +.ip-rotate .btn { + padding: 4px 7px 0px 7px; +} +.icon-cw, +.icon-ccw { + height: 18px !important; + width: 18px !important; + display: inline-block !important; +} +.icon-cw { + background: url('../img/icon-cw.png') !important; +} +.icon-ccw { + background: url('../img/icon-ccw.png') !important; +} + +/* + * jQuery Jcrop + * http://deepliquid.com/content/Jcrop.html + */ +.jcrop-holder{direction:ltr;text-align:left;margin:0 auto;} +.jcrop-vline,.jcrop-hline{background:#000;opacity:1!important;font-size:0;position:absolute;} +.jcrop-vline{height:100%;width:1px!important;} +.jcrop-vline.right{right:0;} +.jcrop-hline{height:1px!important;width:100%;} +.jcrop-hline.bottom{bottom:0;} +.jcrop-tracker{-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;-webkit-user-select:none;height:100%;width:100%;} +.jcrop-handle{background-color:#fff;opacity:1!important;border:1px #333 solid;font-size:1px;height:7px;width:7px;} +.jcrop-handle.ord-n{left:50%;margin-left:-4px;margin-top:-4px;top:0;} +.jcrop-handle.ord-s{bottom:0;left:50%;margin-bottom:-4px;margin-left:-4px;} +.jcrop-handle.ord-e{margin-right:-4px;margin-top:-4px;right:0;top:50%;} +.jcrop-handle.ord-w{left:0;margin-left:-4px;margin-top:-4px;top:50%;} +.jcrop-handle.ord-nw{left:0;margin-left:-4px;margin-top:-4px;top:0;} +.jcrop-handle.ord-ne{margin-right:-4px;margin-top:-4px;right:0;top:0;} +.jcrop-handle.ord-se{bottom:0;margin-bottom:-4px;margin-right:-4px;right:0;} +.jcrop-handle.ord-sw{bottom:0;left:0;margin-bottom:-4px;margin-left:-4px;} +.jcrop-dragbar.ord-n,.jcrop-dragbar.ord-s{height:7px;width:100%;} +.jcrop-dragbar.ord-e,.jcrop-dragbar.ord-w{height:100%;width:7px;} +.jcrop-dragbar.ord-n{margin-top:-4px;} +.jcrop-dragbar.ord-s{bottom:0;margin-bottom:-4px;} +.jcrop-dragbar.ord-e{margin-right:-4px;right:0;} +.jcrop-dragbar.ord-w{margin-left:-4px;} +.jcrop-light .jcrop-vline,.jcrop-light .jcrop-hline{background:#FFF;filter:alpha(opacity=70)!important;opacity:.70!important;} +.jcrop-light .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#000;border-color:#FFF;border-radius:3px;} +.jcrop-dark .jcrop-vline,.jcrop-dark .jcrop-hline{background:#000;filter:alpha(opacity=70)!important;opacity:.7!important;} +.jcrop-dark .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#FFF;border-color:#000;border-radius:3px;} +.solid-line .jcrop-vline,.solid-line .jcrop-hline{background:#FFF;} +.jcrop-keymgr {display:none;} +.jcrop-holder img,img.jcrop-preview {max-width:none;} diff --git a/deployed/jsn/components/com_jsn/assets/css/imgpicker.min.css b/deployed/jsn/components/com_jsn/assets/css/imgpicker.min.css new file mode 100644 index 00000000..4ff5e329 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/imgpicker.min.css @@ -0,0 +1 @@ +.ip-modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:99999;-webkit-overflow-scrolling:touch;background:rgba(0,0,0,0.5);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr='#807f7f7f',endColorstr='#b3000000',GradientType=1)"}.ip-modal-dialog{position:relative;width:500px;margin:30px auto}@media all and (max-width: 568px){.ip-modal-dialog{width:auto;margin:5px}}.ip-modal-content{background-color:#fff;box-shadow:0 0 10px rgba(0,0,0,0.4);border-top:5px solid #000}.ip-modal-header{padding:10px 15px;border-bottom:1px solid #e5e5e5}.ip-modal-title{margin:0;line-height:1.42857143;font-size:18px}.ip-modal-header .ip-close,.ip-alert .dismiss{float:right;font-size:24px;font-weight:700;line-height:1.2;color:#000;opacity:.2;filter:alpha(opacity=20);cursor:pointer}.ip-modal-header .ip-close:hover,.ip-alert .dismiss:hover{opacity:.5;filter:alpha(opacity=50);text-decoration:none;color:#000}.ip-alert .dismiss{font-size:18px;line-height:1}.ip-modal-body{padding:10px 15px 15px}.ip-modal-footer{padding:10px 15px;text-align:right;border-top:1px solid #e5e5e5}.ip-modal-footer .ip-actions{float:left}.ip-upload{display:inline-block;position:relative;overflow:hidden}.ip-upload .ip-file{position:absolute;top:0;right:0;margin:0;padding:0;font-size:20px;cursor:pointer;opacity:0;filter:alpha(opacity=0)}body .ip-preview,body .ip-save,body .ip-capture,body .ip-edit,body .ip-delete,body .ip-cancel,body .ip-progress,body .ip-alert,body .ip-rotate,body .ip-info,body .ip-preview.btn,body .ip-save.btn,body .ip-capture.btn,body .ip-edit.btn,body .ip-delete.btn,body .ip-cancel.btn,body .ip-progress.btn,body .ip-alert.btn,body .ip-rotate.btn,body .ip-info.btn{display:none}.ip-preview video{width:100%!important;height:auto!important;max-width:470px}.ip-progress .text{font-size:13px;padding-bottom:2px}.ip-preview,.ip-alert,.ip-progress{margin-top:10px}.ip-preview > img{max-width:100%;height:auto;max-height:400px;display:block;margin:0 auto}.ip-info{font-size:12px;padding:10px 0 0}.ip-rotate{text-align:center;margin:5px 0 -10px}.ip-rotate .btn{padding:4px 7px 0}.icon-cw,.icon-ccw{height:18px!important;width:18px!important;display:inline-block!important}.icon-cw{background:url(../img/icon-cw.png)!important}.icon-ccw{background:url(../img/icon-ccw.png)!important}.jcrop-holder{direction:ltr;text-align:left;margin:0 auto}.jcrop-vline,.jcrop-hline{background:#000;opacity:1!important;font-size:0;position:absolute}.jcrop-vline{height:100%;width:1px!important}.jcrop-vline.right{right:0}.jcrop-hline{height:1px!important;width:100%}.jcrop-hline.bottom{bottom:0}.jcrop-tracker{-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;-webkit-user-select:none;height:100%;width:100%}.jcrop-handle{background-color:#fff;opacity:1!important;border:1px #333 solid;font-size:1px;height:7px;width:7px}.jcrop-handle.ord-n{left:50%;margin-left:-4px;margin-top:-4px;top:0}.jcrop-handle.ord-s{bottom:0;left:50%;margin-bottom:-4px;margin-left:-4px}.jcrop-handle.ord-e{margin-right:-4px;margin-top:-4px;right:0;top:50%}.jcrop-handle.ord-w{left:0;margin-left:-4px;margin-top:-4px;top:50%}.jcrop-handle.ord-nw{left:0;margin-left:-4px;margin-top:-4px;top:0}.jcrop-handle.ord-ne{margin-right:-4px;margin-top:-4px;right:0;top:0}.jcrop-handle.ord-se{bottom:0;margin-bottom:-4px;margin-right:-4px;right:0}.jcrop-handle.ord-sw{bottom:0;left:0;margin-bottom:-4px;margin-left:-4px}.jcrop-dragbar.ord-n,.jcrop-dragbar.ord-s{height:7px;width:100%}.jcrop-dragbar.ord-e,.jcrop-dragbar.ord-w{height:100%;width:7px}.jcrop-dragbar.ord-n{margin-top:-4px}.jcrop-dragbar.ord-s{bottom:0;margin-bottom:-4px}.jcrop-dragbar.ord-e{margin-right:-4px;right:0}.jcrop-dragbar.ord-w{margin-left:-4px}.jcrop-light .jcrop-vline,.jcrop-light .jcrop-hline{background:#FFF;filter:alpha(opacity=70)!important;opacity:.7!important}.jcrop-light .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#000;border-color:#FFF;border-radius:3px}.jcrop-dark .jcrop-vline,.jcrop-dark .jcrop-hline{background:#000;filter:alpha(opacity=70)!important;opacity:.7!important}.jcrop-dark .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#FFF;border-color:#000;border-radius:3px}.solid-line .jcrop-vline,.solid-line .jcrop-hline{background:#FFF}.jcrop-keymgr{display:none}.jcrop-holder img,img.jcrop-preview{max-width:none} \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/css/jquery.sortable.css b/deployed/jsn/components/com_jsn/assets/css/jquery.sortable.css new file mode 100644 index 00000000..fe9cef49 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/jquery.sortable.css @@ -0,0 +1,395 @@ +/** + * @license Copyright © 2016 Mateusz Zawartka + * @version 1.0.0 + */ +.dd { + position: relative; + display: inline-block; + margin: 0; + padding: 0; + width: 60%; + list-style: none; + font-family: 'Helvetica Neue', Arial, sans-serif; + font-size: 13px; + line-height: 20px; +} + +/*.dd-edit-box input, + /*.dd-edit-box select,*/ +/*.dd-edit-box textarea { + border: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + background: transparent; + text-overflow: ellipsis; + outline: none; + font-size: 13px; + color: #444; + text-shadow: 0 1px 0 #fff; + width: 30%; +} + +.dd-edit-box input::selection, +.dd-edit-box textarea::selection { + color: #fff; + background: #0e90d2; +} + +.dd-edit-box input:focus, +.dd-edit-box textarea:focus { + text-shadow: none; +} +.dd-button-container .custom-button-example { + color: #000; + text-align: center; + padding: 1px 4px; +} + +.dd-edit-box select { + width: 30%; +} +*/ +.dd-edit-box > * { + vertical-align: top; +} + +.dd-edit-box input, .dd-edit-box select, .dd-edit-box textarea { + margin-bottom: 0; +} + +.dd-edit-box { + position: relative; +} + +.dd-edit-box i { + right: 0; + overflow: hidden; + cursor: pointer; + position: absolute; + font-style: normal; +} + +.dd-item-blueprint { + display: none; +} + +.dd > .dd-list { + min-height: 80px; +} + +.dd-list { + display: block; + position: relative; + margin: 0; + padding: 0; + list-style: none; +} + +.dd-list .dd-list { + left: 30px; + margin-right: 30px; +} + +.dd-collapsed .dd-list { + display: none; +} + +.dd-item, +.dd-empty, +.dd-placeholder { + text-shadow: 0 1px 0 #fff; + display: block; + position: relative; + margin: 0; + padding: 0; + min-height: 20px; + font-size: 13px; + line-height: 20px; +} + +.dd-handle { + cursor: move; + display: block; + margin: 5px 0; + padding: 5px 10px; + color: #333; + text-decoration: none; + font-weight: bold; + border: 1px solid #aaa; + background: #c8c8c8; + background: -webkit-linear-gradient(top, #c8c8c8 0%, #8c8c8c 100%); + background: -moz-linear-gradient(top, #c8c8c8 0%, #8c8c8c 100%); + background: linear-gradient(top, #c8c8c8 0%, #8c8c8c 100%); + -webkit-border-radius: 3px; + border-radius: 3px; + box-sizing: border-box; + -moz-box-sizing: border-box; +} + +.dd-handle:hover { + color: #2ea8e5; + background: #fff; +} + +.dd-item > button { + display: inline-block; + position: relative; + cursor: pointer; + float: left; + width: 24px; + height: 20px; + margin: 5px 5px 5px 30px; + padding: 0; + white-space: nowrap; + overflow: hidden; + border: 0; + background: transparent; + font-size: 12px; + line-height: 1; + text-align: center; + font-weight: bold; + color: black; +} + +.dd.sortable .dd-new-item { + background: transparent; + border: 3px dotted #8F8F8F; + border-radius: 11px; + width: 100%; + height: 35px; + font-size: 29px; + color: #8F8F8F; + outline: none; +} + +/* @since > 0.13.29 */ +.dd-item .item-remove, +.dd-item .item-remove-confirm, +.dd-item .item-add { + outline: none; +} + +.dd-item .dd-button-container button { + background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.51), rgba(0, 0, 0, 0.14)); + border: 1px solid #898989; + border-radius: 2px; + font: normal 12px/18px Helvetica, Lato, Arial sans-serif; + cursor: pointer; +} + +.dd-item .dd-button-container .item-add { + background-color: #55b3ff; + border-color: #376f9c; + color: #ffffff; + text-shadow: 0 1px 0 #2b77b5; + box-shadow: inset 0 1px 0 #cfe9ff; +} + +.dd-item .dd-button-container .item-add:active { + box-shadow: inset 0 1px 3px #376f9c; +} + +.dd-item .dd-button-container .item-remove { + background-color: #ff5555; + border-color: #a54b4b; + color: #5a1111; + text-shadow: 0 1px 0 #ffc0c0; + box-shadow: inset 0 1px 0 #ffc0c0; + transition: background-color 0.35s; +} + +.dd-item .dd-button-container .item-remove:active { + + box-shadow: inset 0 1px 5px #a54b4b; +} + +.dd-item .dd-button-container .item-remove-confirm { + + background-color: #ffa155; + + transition: background-color 0.35s; + + border-color: #ad7232; +} + +.dd-item .dd-button-container .item-remove-confirm:active { + +} + +.item-remove-confirm { + background: #ffce66; +} + +.dd-item .dd-button-container { + position: absolute; + height: 19px; + padding: 0 5px; + top: 4px; + overflow: visible; + display: none; + right: 0; +} + +/* end @since > 0.13.29 */ + +.dd3-item > button:first-child { + margin-left: 30px; +} + +.dd-item > button:before { + display: block; + position: absolute; + width: 100%; + text-align: center; + text-indent: 0; +} + +.dd-placeholder, +.dd-empty { + margin: 5px 0; + padding: 0; + min-height: 30px; + background: #D6F2FF; + border: 1px dashed #6C9AB1; + box-sizing: border-box; + -moz-box-sizing: border-box; +} + +.dd-placeholder.max-depth { + background: #ffb3b7; + border: 1px dashed #b14444; +} + +.dd-empty { + border: 1px dashed #bbb; + min-height: 100px; + background-color: #e5e5e5; + background-image: -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), + -webkit-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); + background-image: -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), + -moz-linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); + background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), + linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff); + background-size: 60px 60px; + background-position: 0 0, 30px 30px; +} + +.dd-dragel { + height: 60px; + position: absolute; + pointer-events: none; + z-index: 9999; +} + +.dd-dragel > .dd-item .dd-handle { + margin-top: 0; +} + +.dd-dragel .dd-handle { + -webkit-box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, .1); + box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, .1); +} + +/** + * Sortable Draggable Handles + */ +.dd3-content { + display: block; + height: 100%; + margin: 5px 0; + padding: 5px 10px 5px 40px; + color: #333; + text-decoration: none; + font-weight: bold; + border: 1px solid #ccc; + border: 1px solid #898989; + background: #fafafa; + background: -webkit-linear-gradient(top, #f4f4f4 10%, #c9c9c9 100%); + background: -moz-linear-gradient(top, #f4f4f4 10%, #c9c9c9 100%); + background: linear-gradient(top, #f4f4f4 10%, #c9c9c9 100%); + -webkit-border-radius: 3px; + border-radius: 3px; + box-sizing: border-box; + -moz-box-sizing: border-box; +} + +.dd3-content:hover { + color: #2ea8e5; + background: #c8c8c8; + background: -webkit-linear-gradient(top, #e5e5e5 10%, #ffffff 100%); + background: -moz-linear-gradient(top, #e5e5e5 10%, #ffffff 100%); + background: linear-gradient(top, #e5e5e5 10%, #ffffff 100%); +} + +.dd-dragel > .dd3-item > .dd3-content { + margin: 0; +} + +.dd3-handle { + position: absolute; + margin: 0; + left: 0; + top: 0; + cursor: move; + width: 30px; + text-indent: 100%; + white-space: nowrap; + overflow: hidden; + border: 1px solid #807b7b; + text-shadow: 0 1px 0 #807b7b; + background: #c8c8c8; + background: -webkit-linear-gradient(top, #c8c8c8 0%, #8c8c8c 100%); + background: -moz-linear-gradient(top, #c8c8c8 0%, #8c8c8c 100%); + background: linear-gradient(top, #c8c8c8 0%, #8c8c8c 100%); + border-top-right-radius: 0; + border-bottom-right-radius: 0; + font-size:0; +} + +.dd3-handle:before { + content: '\2263'; + display: block; + position: absolute; + left: 0; + top: 3px; + width: 100%; + text-align: center; + text-indent: 0; + color: #fff; + font-size: 20px; + font-weight: normal; +} + +.dd3-handle:hover { + background: #c8c8c8; + background: -webkit-linear-gradient(top, #c8c8c8 0%, #8c8c8c 100%); + background: -moz-linear-gradient(top, #c8c8c8 0%, #8c8c8c 100%); + background: linear-gradient(top, #c8c8c8 0%, #8c8c8c 100%); +} + +.dd3-content:hover .dd-button-container { + display: block; + transition: display 2s; +} + +.dd .dd-new-item { + display: block; + text-align: center; + padding: 10px 0; + width: 100%; + border: 2px dashed #BDBDBD; + background: transparent; + border-radius: 3px; + font-size: 21px; + color: #BDBDBD; + cursor: pointer; + transition: border 0.35s ease 0s, color 0.35s ease 0s; + outline: none; +} + +.dd .dd-new-item:hover { + border: 2px dashed #595858; + color: #595858; + transition: border 0.35s ease 0s, color 0.35s ease 0s; +} \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/css/slim.css b/deployed/jsn/components/com_jsn/assets/css/slim.css new file mode 100644 index 00000000..48ae6e17 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/slim.css @@ -0,0 +1,655 @@ +/* + * Slim v4.6.1 - Image Cropping Made Easy + * Copyright (c) 2017 Rik Schennink - http://slimimagecropper.com + */ +.slim-file-hopper { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; } + +.slim-image-editor { + position: relative; + height: 100%; + text-align: left; + z-index: 1; } + .slim-image-editor .slim-container { + position: relative; + height: calc(100% - 8em); + width: 100%; + z-index: 2; + direction: ltr; } + .slim-image-editor .slim-editor-utils-group, + .slim-image-editor .slim-editor-btn-group { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; } + .slim-image-editor .slim-stage { + position: absolute; + line-height: 0; } + .slim-image-editor .slim-wrapper { + position: absolute; + z-index: 2; } + .slim-image-editor .slim-crop-preview { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + line-height: 0; } + .slim-image-editor .slim-stage { + z-index: 4; } + .slim-image-editor .slim-crop-preview { + z-index: 3; + border-radius: 4px; } + .slim-image-editor .slim-crop-preview img, .slim-image-editor .slim-crop-preview::after, + .slim-image-editor .slim-crop-preview canvas { + position: absolute; + display: block; + border-radius: inherit; + left: 0; + top: 0; } + .slim-image-editor .slim-crop-preview .slim-crop { + z-index: 3; } + .slim-image-editor .slim-crop-preview::after { + z-index: 2; + right: 0; + bottom: 0; + content: ''; } + .slim-image-editor .slim-crop-preview .slim-crop-blur { + -webkit-filter: contrast(0.7); + -moz-filter: contrast(0.7); + filter: contrast(0.7); + z-index: 1; } + .slim-image-editor .slim-editor-utils-group { + text-align: center; } + .slim-image-editor .slim-editor-utils-group button { + width: 2.5em; + height: 2.5em; + padding: 0; + font-size: 1em; + cursor: pointer; + outline: none; + box-shadow: inset 0 -1px 2px rgba(0, 0, 0, 0.1), inset 0 1px 0 0 rgba(255, 255, 255, 0.15); + background-color: transparent; + background-size: 50% 50%; + background-position: center center; + background-repeat: no-repeat; } + .slim-image-editor .slim-editor-utils-group button:active { + background-color: rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); } + .slim-image-editor .slim-editor-btn-group { + text-align: center; } + .slim-image-editor .slim-editor-btn-group button { + position: relative; + display: inline-block; + vertical-align: top; + font-size: 1em; + margin: 0 .75em; + padding: .75em 1.5em .875em; + cursor: pointer; + overflow: hidden; + -webkit-transition: color .25s, box-shadow .25s, background-color .25s; + transition: color .25s, box-shadow .25s, background-color .25s; + box-shadow: inset 0 -1px 2px rgba(0, 0, 0, 0.1), inset 0 1px 0 0 rgba(255, 255, 255, 0.15); + background-color: transparent; + outline: none; } + .slim-image-editor .slim-editor-btn-group button:active { + padding: .875em 1.5em .75em; + background-color: rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); } + +.slim-rotation-disabled .slim-container { + height: calc(100% - 4em); } + +.slim-rotation-disabled .slim-editor-utils-group { + display: none; } + +.slim-editor-utils-btn, +.slim-editor-btn { + color: rgba(255, 255, 255, 0.75); + border: 2px solid rgba(0, 0, 0, 0.25); } + .slim-editor-utils-btn:focus, .slim-editor-utils-btn:hover, + .slim-editor-btn:focus, + .slim-editor-btn:hover { + color: rgba(255, 255, 255, 0.9); } + +.slim-editor-utils-btn { + border-radius: .6875em; } + +.slim-editor-btn { + border-radius: .5em; } + +.slim-image-editor-preview::after { + background-color: rgba(244, 250, 255, 0.4); + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07), 0 1px 5px rgba(0, 0, 0, 0.3); } + +.slim-btn-rotate { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='252' height='287' viewBox='0 0 252 287' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M134.762.626v36.15c65.016 4.594 116.34 58.75 116.34 124.936 0 69.198-56.09 125.288-125.29 125.288C56.616 287 .525 230.91.525 161.71c0-30.036 10.592-57.59 28.215-79.17l31.934 31.934C51.03 127.75 45.27 144.04 45.27 161.71c0 44.485 36.06 80.544 80.544 80.544 44.484 0 80.544-36.058 80.544-80.543 0-41.454-31.327-75.56-71.594-80.017v35.272l-62.646-57.89L134.762.625zm-8.95 196.883c-19.77 0-35.796-16.028-35.796-35.798 0-19.77 16.027-35.796 35.797-35.796 19.77 0 35.797 16.026 35.797 35.796s-16.027 35.797-35.797 35.797z' fill='rgba(255,255,255,.8)' fill-rule='evenodd'/%3E%3C/svg%3E"); } + +.slim-editor-utils-group { + padding: 1em 0 0; } + +.slim-editor-btn-group { + padding: 1em 0 0; } + +@media (min-width: 40em) { + .slim-btn-group { + padding-top: 2em; } } + +.slim-crop-area { + position: absolute; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.75), 0 0 0 1px rgba(255, 255, 255, 0.75); } + .slim-crop-area .grid { + overflow: hidden; } + .slim-crop-area .grid::before, .slim-crop-area .grid::after { + position: absolute; + z-index: 2; + content: ''; + opacity: 0; + -webkit-transition: opacity .5s; + transition: opacity .5s; } + .slim-crop-area .grid::before { + top: 33.333%; + bottom: 33.333%; + left: 1px; + right: 1px; + box-shadow: inset 0 -1px 0 0 rgba(255, 255, 255, 0.35), inset 0 1px 0 0 rgba(255, 255, 255, 0.35); } + .slim-crop-area .grid::after { + top: 1px; + bottom: 1px; + left: 33.333%; + right: 33.333%; + box-shadow: inset -1px 0 0 0 rgba(255, 255, 255, 0.35), inset 1px 0 0 0 rgba(255, 255, 255, 0.35); } + .slim-crop-area button { + position: absolute; + background: #fafafa; + box-shadow: inset 0 1px 0 0 #fff, 0 1px 1px rgba(0, 0, 0, 0.15); + border: none; + padding: 0; + margin: 0; + width: 16px; + height: 16px; + margin-top: -8px; + margin-left: -8px; + border-radius: 8px; + z-index: 3; } + .slim-crop-area [class*='n'] { + top: 0; } + .slim-crop-area [class*='s'] { + top: 100%; } + .slim-crop-area [class*='w'] { + left: 0; } + .slim-crop-area [class*='e'] { + left: 100%; } + .slim-crop-area .e, + .slim-crop-area .w { + top: 50%; + cursor: ew-resize; + height: 30px; + margin-top: -15px; } + .slim-crop-area .n, + .slim-crop-area .s { + left: 50%; + cursor: ns-resize; + width: 30px; + margin-left: -15px; } + .slim-crop-area .ne, + .slim-crop-area .sw { + cursor: nesw-resize; } + .slim-crop-area .nw, + .slim-crop-area .se { + cursor: nwse-resize; } + .slim-crop-area .c { + top: 10px; + left: 10px; + width: calc(100% - 20px); + height: calc(100% - 20px); + margin: 0; + border-radius: 0; + border: none; + z-index: 2; + box-shadow: none; + opacity: 0; + cursor: move; } + .slim-crop-area button:not(.c)::after { + content: ''; + position: absolute; + left: -12px; + right: -12px; + top: -12px; + bottom: -12px; } + .slim-crop-area .slim-crop-mask { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + overflow: hidden; + z-index: 1; } + .slim-crop-area .slim-crop-mask img { + position: absolute; + -webkit-transform-origin: 0 0; + transform-origin: 0 0; + -webkit-transform: translateZ(0); + transform: translateZ(0); + margin: 0 !important; + width: auto; + height: auto; + max-width: none; + min-width: initial; } + .slim-crop-area[data-dragging='true'] .grid::before, .slim-crop-area[data-dragging='true'] .grid::after { + opacity: 1; } + +.slim-popover { + -ms-touch-action: none; + touch-action: none; + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + padding: 1em; + font-size: 16px; + background: rgba(25, 27, 29, 0.99); + z-index: 2147483647; + overflow: hidden; } + .slim-popover[data-state='off'] { + left: -100%; } + .slim-popover::after { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + content: ''; + background: -webkit-radial-gradient(center ellipse, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 80%); + background: radial-gradient(ellipse at center, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 80%); } + +@media (min-width: 40em) { + .slim-popover { + padding: 2em; } } + +.slim, +.slim-popover, +.slim-crop-area, +.slim-image-editor { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + box-sizing: border-box; } + .slim button, + .slim-popover button, + .slim-crop-area button, + .slim-image-editor button { + -webkit-highlight: none; + -webkit-tap-highlight-color: transparent; } + .slim *, + .slim-popover *, + .slim-crop-area *, + .slim-image-editor * { + box-sizing: inherit; } + .slim img, + .slim-popover img, + .slim-crop-area img, + .slim-image-editor img { + background-color: #eee; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABG2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+Gkqr6gAAAYBpQ0NQc1JHQiBJRUM2MTk2Ni0yLjEAACiRdZHPK0RRFMc/M4gYERaKxUvDamhQExtlJqEmTWOUwWbmzS81P17vzaTJVtlOUWLj14K/gK2yVopISdlZExv0nGfUSObc7rmf+73nnO49F+yhtJoxat2Qyeb14KRXmQ8vKPWP2OjCQRtKRDW08UDAT1V7u5Fosat+q1b1uH+tKRY3VLA1CI+pmp4XnhL2r+Q1izeFO9RUJCZ8LOzS5YLC15YeLfOTxckyf1ish4I+sLcKK8lfHP3FakrPCMvLcWbSBfXnPtZLHPHs3KysPTK7MQgyiReFaSbw4WGQUfEe+hliQHZUyXd/58+Qk1xVvEYRnWWSpMjjErUg1eOyJkSPy0hTtPr/t69GYnioXN3hhboH03zphfoN+CyZ5vu+aX4eQM09nGUr+bk9GHkVvVTRnLvQsgYn5xUtugWn69B5p0X0yLdUI9OeSMDzETSHof0SGhfLPfs55/AWQqvyVRewvQN9Et+y9AUyt2fOEwKMEgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAC9JREFUOI1jZGBgkGIgDjwjRhETkYYRDUYNHDVwMBjISIJaonLU4PfyqIGjBpIBAPvwAUFW9TOIAAAAAElFTkSuQmCC"); } + +.slim img { + width: 100%; + height: auto; } + +span.slim { + display: block; } + +.slim { + position: relative; + font-size: inherit; + background-color: #eee; + -webkit-transition: background-color .25s; + transition: background-color .25s; + padding-bottom: .025px; } + +@-webkit-keyframes rotate { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes rotate { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + .slim[data-state*='empty']:hover { + background-color: #ddd; } + .slim[data-state*='empty'] .slim-label { + visibility: visible; + opacity: 1; } + .slim[data-state*='busy'] .slim-label { + opacity: 0; } + .slim[data-state*='loading'] .slim-label { + display: none; } + .slim[data-state*='loading'] .slim-label-loading { + opacity: 1; + display: block; } + .slim[data-state*='preview'] .slim-label { + visibility: hidden; } + .slim[data-state*='error'] { + background-color: #e8a69f !important; + color: #702010; } + .slim > img, + .slim > input[type=file] { + display: block !important; + opacity: 0 !important; + width: 0 !important; + height: 0 !important; + padding: 0 !important; + margin-left: 0 !important; + margin-right: 0 !important; + margin-top: 0 !important; + border: 0 !important; } + .slim > img + input[type=file] { + margin-bottom: 0 !important; } + .slim > input[type=file] + img { + margin-bottom: 0 !important; } + .slim > input[type=hidden] { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + opacity: 0; } + .slim .slim-label-loading { + display: none; } + .slim .slim-label { + visibility: hidden; + -webkit-transition: opacity .25s; + transition: opacity .25s; } + .slim .slim-label-loading, + .slim .slim-label, + .slim .slim-error { + max-width: 100%; } + .slim .slim-file-hopper { + z-index: 2; + background: rgba(0, 0, 0, 0.0001); } + .slim .slim-ratio, + .slim .slim-drip, + .slim .slim-status, + .slim .slim-result, + .slim .slim-area { + border-radius: inherit; } + .slim .slim-area { + width: 100%; + color: inherit; + overflow: hidden; } + .slim .slim-area *:only-of-type { + margin: 0; } + .slim .slim-area .slim-loader { + pointer-events: none; + position: absolute; + right: .875em; + top: .875em; + width: 23px; + height: 23px; + z-index: 1; } + .slim .slim-area .slim-loader svg { + display: block; + width: 100%; + height: 100%; + opacity: 0; } + .slim .slim-area .slim-upload-status { + position: absolute; + right: 1em; + top: 1em; + z-index: 1; + opacity: 0; + -webkit-transition: opacity .25s; + transition: opacity .25s; + white-space: nowrap; + line-height: 1.65; + font-weight: normal; } + .slim .slim-area .slim-upload-status-icon { + display: inline-block; + opacity: .9; } + .slim .slim-area .slim-drip, + .slim .slim-area .slim-status, + .slim .slim-area .slim-result { + left: 0; + top: 0; + right: 0; + bottom: 0; } + .slim .slim-area .slim-drip, + .slim .slim-area .slim-result { + position: absolute; } + .slim .slim-area .slim-status { + padding: 3em 1.5em; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + text-align: center; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + pointer-events: none; } + .slim .slim-area .slim-drip { + z-index: 1; + overflow: hidden; } + .slim .slim-area .slim-drip > span { + position: absolute; + left: 0; + top: 0; + opacity: 0; + margin-left: -25%; + margin-top: -25%; + width: 50%; + padding-bottom: 50%; } + .slim .slim-area .slim-drip > span > span { + position: absolute; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.25); + border-radius: 50%; + opacity: .5; + left: 0; + top: 0; } + .slim .slim-area .slim-result { + overflow: hidden; + -webkit-perspective: 1px; } + .slim .slim-area .slim-result img { + display: block; + width: 100%; + position: absolute; + left: 0; + top: 0; } + .slim .slim-area .slim-result img:not([src]), .slim .slim-area .slim-result img[src=''] { + visibility: hidden; } + .slim .slim-btn-group { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 3; + overflow: hidden; + pointer-events: none; } + .slim .slim-btn-group button { + pointer-events: all; + cursor: pointer; } + .slim[data-ratio*=':'] { + min-height: initial; } + .slim[data-ratio*=':'] .slim-status { + position: absolute; + padding: 0 1.5em; } + .slim[data-ratio='16:10'] > input[type=file], + .slim[data-ratio='16:10'] > img { + margin-bottom: 62.5%; } + .slim[data-ratio='10:16'] > input[type=file], + .slim[data-ratio='10:16'] > img { + margin-bottom: 160%; } + .slim[data-ratio='16:9'] > input[type=file], + .slim[data-ratio='16:9'] > img { + margin-bottom: 56.25%; } + .slim[data-ratio='9:16'] > input[type=file], + .slim[data-ratio='9:16'] > img { + margin-bottom: 177.77778%; } + .slim[data-ratio='5:3'] > input[type=file], + .slim[data-ratio='5:3'] > img { + margin-bottom: 60%; } + .slim[data-ratio='3:5'] > input[type=file], + .slim[data-ratio='3:5'] > img { + margin-bottom: 166.66667%; } + .slim[data-ratio='5:4'] > input[type=file], + .slim[data-ratio='5:4'] > img { + margin-bottom: 80%; } + .slim[data-ratio='4:5'] > input[type=file], + .slim[data-ratio='4:5'] > img { + margin-bottom: 125%; } + .slim[data-ratio='4:3'] > input[type=file], + .slim[data-ratio='4:3'] > img { + margin-bottom: 75%; } + .slim[data-ratio='3:4'] > input[type=file], + .slim[data-ratio='3:4'] > img { + margin-bottom: 133.33333%; } + .slim[data-ratio='3:2'] > input[type=file], + .slim[data-ratio='3:2'] > img { + margin-bottom: 66.66667%; } + .slim[data-ratio='2:3'] > input[type=file], + .slim[data-ratio='2:3'] > img { + margin-bottom: 150%; } + .slim[data-ratio='1:1'] > input[type=file], + .slim[data-ratio='1:1'] > img { + margin-bottom: 100%; } + +.slim-btn-group { + padding: 1.5em 0; + text-align: center; } + +.slim-btn { + position: relative; + padding: 0; + margin: 0 7.2px; + font-size: 0; + outline: none; + width: 36px; + height: 36px; + border: none; + color: #fff; + background-color: rgba(0, 0, 0, 0.7); + background-repeat: no-repeat; + background-size: 50% 50%; + background-position: center center; } + .slim-btn { + border-radius: 50%; } + .slim-btn::before { + border-radius: inherit; + position: absolute; + box-sizing: border-box; + left: -3px; + right: -3px; + bottom: -3px; + top: -3px; + border: 3px solid white; + content: ''; + -webkit-transform: scale(0.95); + transform: scale(0.95); + opacity: 0; + -webkit-transition: all .25s; + transition: all .25s; + z-index: -1; + pointer-events: none; } + .slim-btn:focus::before, .slim-btn:hover::before { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); } + .slim-btn * { + pointer-events: none; } + +.slim-btn-remove { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 269 269' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' clip-rule='evenodd' stroke-linejoin='round' stroke-miterlimit='1.414'%3E%3Cpath d='M63.12 250.254s3.998 18.222 24.582 18.222h93.072c20.583 0 24.582-18.222 24.582-18.222l18.374-178.66H44.746l18.373 178.66zM170.034 98.442c0-4.943 4.006-8.95 8.95-8.95 4.942 0 8.95 4.007 8.95 8.95l-8.95 134.238c0 4.943-4.008 8.95-8.95 8.95-4.942 0-8.95-4.008-8.95-8.95l8.95-134.238zm-44.746 0c0-4.943 4.006-8.95 8.948-8.95 4.943 0 8.95 4.007 8.95 8.95V232.68c0 4.943-4.007 8.95-8.95 8.95s-8.95-4.008-8.95-8.95V98.442zm-35.798-8.95c4.943 0 8.95 4.006 8.95 8.95l8.95 134.237c0 4.942-4.008 8.948-8.95 8.948-4.943 0-8.95-4.007-8.95-8.95l-8.95-134.236c0-4.943 4.008-8.95 8.95-8.95zm128.868-53.68h-39.376V17.898c0-13.578-4.39-17.9-17.898-17.9H107.39C95 0 89.492 6 89.492 17.9V35.81H50.116c-7.914 0-14.32 6.007-14.32 13.43 0 7.424 6.406 13.43 14.32 13.43H218.36c7.914 0 14.32-6.006 14.32-13.43 0-7.423-6.406-13.43-14.32-13.43zm-57.274 0H107.39l.002-17.914h53.695V35.81z' fill='%23fff'/%3E%3C/svg%3E"); } + +.slim-btn-download { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 269 269' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' clip-rule='evenodd' stroke-linejoin='round' stroke-miterlimit='1.414'%3E%3Cpath d='M232.943 223.73H35.533c-12.21 0-22.11 10.017-22.11 22.373 0 12.356 9.9 22.373 22.11 22.373h197.41c12.21 0 22.11-10.017 22.11-22.373 0-12.356-9.9-22.373-22.11-22.373zM117.88 199.136c4.035 4.04 9.216 6.147 14.492 6.508.626.053 1.227.188 1.866.188.633 0 1.228-.135 1.847-.186 5.284-.357 10.473-2.464 14.512-6.51l70.763-70.967c8.86-8.876 8.86-23.268 0-32.143-8.86-8.876-23.225-8.876-32.086 0l-32.662 32.756V22.373C156.612 10.017 146.596 0 134.238 0c-12.356 0-22.372 10.017-22.372 22.373v106.41L79.204 96.027c-8.86-8.876-23.226-8.876-32.086 0-8.86 8.875-8.86 23.267 0 32.142l70.763 70.966z' fill='%23fff'/%3E%3C/svg%3E"); } + +.slim-btn-upload { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='243' height='269' viewBox='0 0 243 269' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3EDownload%3C/title%3E%3Cpath d='M219.943 223.73H22.533c-12.21 0-22.11 10.017-22.11 22.373 0 12.356 9.9 22.373 22.11 22.373h197.41c12.21 0 22.11-10.017 22.11-22.373 0-12.356-9.9-22.373-22.11-22.373zM104.88 6.696c4.035-4.04 9.216-6.147 14.492-6.508C119.998.135 120.6 0 121.238 0c.633 0 1.228.135 1.847.186 5.284.357 10.473 2.464 14.512 6.51l70.763 70.967c8.86 8.875 8.86 23.267 0 32.142-8.86 8.876-23.225 8.876-32.086 0L143.612 77.05v106.41c0 12.355-10.016 22.372-22.374 22.372-12.356 0-22.372-10.017-22.372-22.373V77.05l-32.662 32.755c-8.86 8.876-23.226 8.876-32.086 0-8.86-8.875-8.86-23.267 0-32.142L104.88 6.696z' fill='%23FFF' fill-rule='evenodd'/%3E%3C/svg%3E"); } + +.slim-btn-edit { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 269 269' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' clip-rule='evenodd' stroke-linejoin='round' stroke-miterlimit='1.414'%3E%3Cpath d='M161.36 56.337c-7.042-7.05-18.46-7.05-25.5 0l-6.373 6.38-89.243 89.338.023.023-2.812 2.82s-8.968 9.032-29.216 74.4c-.143.456-.284.91-.427 1.373-.36 1.172-.726 2.362-1.094 3.568-.327 1.066-.657 2.154-.988 3.25-.28.922-.556 1.835-.84 2.778-.64 2.14-1.29 4.318-1.954 6.567-1.455 4.937-5.01 16.07-.99 20.1 3.87 3.882 15.12.467 20.043-.993 2.233-.662 4.396-1.31 6.52-1.952.98-.296 1.932-.586 2.89-.878 1.032-.314 2.058-.626 3.063-.935 1.27-.39 2.52-.775 3.75-1.157l1.09-.34c62.193-19.365 73.358-28.453 74.286-29.284l.01-.01.067-.06 2.88-2.886.192.193 89.244-89.336 6.373-6.382c7.04-7.048 7.04-18.476 0-25.525l-50.998-51.05zM103.4 219.782c-.08.053-.185.122-.297.193l-.21.133c-.076.047-.158.098-.245.15l-.243.148c-2.97 1.777-11.682 6.362-32.828 14.017-2.47.894-5.162 1.842-7.98 2.82l-30.06-30.092c.98-2.84 1.928-5.55 2.825-8.04 7.638-21.235 12.22-29.974 13.986-32.94l.12-.2c.063-.1.12-.196.175-.283l.126-.2c.07-.11.14-.217.192-.296l2.2-2.205 54.485 54.542-2.248 2.255zM263.35 56.337l-50.996-51.05c-7.04-7.048-18.456-7.048-25.498 0L174.108 18.05c-7.04 7.048-7.04 18.476 0 25.524l50.996 51.05c7.04 7.048 18.457 7.048 25.498 0l12.75-12.762c7.04-7.05 7.04-18.477 0-25.525z' fill='%23fff'/%3E%3C/svg%3E"); } + +.slim-loader-background { + stroke: rgba(0, 0, 0, 0.15); } + +.slim-loader-foreground { + stroke: rgba(0, 0, 0, 0.65); } + +.slim[data-state*='preview'] .slim-loader-background { + stroke: rgba(255, 255, 255, 0.25); } + +.slim[data-state*='preview'] .slim-loader-foreground { + stroke: #fff; } + +.slim-upload-status { + padding: 0 .5em; + border-radius: .3125em; + font-size: .75em; + box-shadow: 0 0.125em 0.25em rgba(0, 0, 0, 0.25); } + +.slim-upload-status[data-state="success"] { + background-color: #d1ed8f; + color: #323e15; } + .slim-upload-status[data-state="success"] .slim-upload-status-icon { + width: .5em; + height: .75em; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + border: .1875em solid currentColor; + border-left: none; + border-top: none; + margin-right: .325em; + margin-left: .25em; + margin-bottom: .0625em; } + +.slim-upload-status[data-state="error"] { + background: #efd472; + color: #574016; } + .slim-upload-status[data-state="error"] .slim-upload-status-icon { + margin-left: -.125em; + margin-right: .5em; + width: .5625em; + height: 1em; + position: relative; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); } + .slim-upload-status[data-state="error"] .slim-upload-status-icon:after, .slim-upload-status[data-state="error"] .slim-upload-status-icon:before { + content: ''; + position: absolute; + box-sizing: content-box; + width: 0; + height: 0; + border-width: 0.09em; + border-style: solid; + border-color: currentColor; + background-color: currentColor; + -webkit-transform: translate(-50%, -50%) translate(0.5em, 0.5em); + transform: translate(-50%, -50%) translate(0.5em, 0.5em); } + .slim-upload-status[data-state="error"] .slim-upload-status-icon:before { + width: 0.66666666667em; } + .slim-upload-status[data-state="error"] .slim-upload-status-icon:after { + height: 0.66666666667em; } diff --git a/deployed/jsn/components/com_jsn/assets/css/slim.min.css b/deployed/jsn/components/com_jsn/assets/css/slim.min.css new file mode 100644 index 00000000..c038c387 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/slim.min.css @@ -0,0 +1,5 @@ +/* + * Slim v4.6.1 - Image Cropping Made Easy + * Copyright (c) 2017 Rik Schennink - http://slimimagecropper.com + */ +.slim-file-hopper{position:absolute;left:0;top:0;right:0;bottom:0}.slim-image-editor{position:relative;height:100%;text-align:left;z-index:1}.slim-image-editor .slim-container{position:relative;height:calc(100% - 8em);width:100%;z-index:2;direction:ltr}.slim-image-editor .slim-editor-btn-group,.slim-image-editor .slim-editor-utils-group{-ms-flex-negative:0;flex-shrink:0}.slim-image-editor .slim-stage{position:absolute;line-height:0}.slim-image-editor .slim-wrapper{position:absolute;z-index:2}.slim-image-editor .slim-crop-preview{position:absolute;left:0;top:0;right:0;bottom:0;line-height:0}.slim-image-editor .slim-stage{z-index:4}.slim-image-editor .slim-crop-preview{z-index:3;border-radius:4px}.slim-image-editor .slim-crop-preview:after,.slim-image-editor .slim-crop-preview canvas,.slim-image-editor .slim-crop-preview img{position:absolute;display:block;border-radius:inherit;left:0;top:0}.slim-image-editor .slim-crop-preview .slim-crop{z-index:3}.slim-image-editor .slim-crop-preview:after{z-index:2;right:0;bottom:0;content:""}.slim-image-editor .slim-crop-preview .slim-crop-blur{-webkit-filter:contrast(.7);-moz-filter:contrast(.7);filter:contrast(.7);z-index:1}.slim-image-editor .slim-editor-utils-group{text-align:center}.slim-image-editor .slim-editor-utils-group button{width:2.5em;height:2.5em;padding:0;font-size:1em;cursor:pointer;outline:none;box-shadow:inset 0 -1px 2px rgba(0,0,0,.1),inset 0 1px 0 0 hsla(0,0%,100%,.15);background-color:transparent;background-size:50% 50%;background-position:50%;background-repeat:no-repeat}.slim-image-editor .slim-editor-utils-group button:active{background-color:rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.15)}.slim-image-editor .slim-editor-btn-group{text-align:center}.slim-image-editor .slim-editor-btn-group button{position:relative;display:inline-block;vertical-align:top;font-size:1em;margin:0 .75em;padding:.75em 1.5em .875em;cursor:pointer;overflow:hidden;-webkit-transition:color .25s,box-shadow .25s,background-color .25s;transition:color .25s,box-shadow .25s,background-color .25s;box-shadow:inset 0 -1px 2px rgba(0,0,0,.1),inset 0 1px 0 0 hsla(0,0%,100%,.15);background-color:transparent;outline:none}.slim-image-editor .slim-editor-btn-group button:active{padding:.875em 1.5em .75em;background-color:rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.15)}.slim-rotation-disabled .slim-container{height:calc(100% - 4em)}.slim-rotation-disabled .slim-editor-utils-group{display:none}.slim-editor-btn,.slim-editor-utils-btn{color:hsla(0,0%,100%,.75);border:2px solid rgba(0,0,0,.25)}.slim-editor-btn:focus,.slim-editor-btn:hover,.slim-editor-utils-btn:focus,.slim-editor-utils-btn:hover{color:hsla(0,0%,100%,.9)}.slim-editor-utils-btn{border-radius:.6875em}.slim-editor-btn{border-radius:.5em}.slim-image-editor-preview:after{background-color:rgba(244,250,255,.4);box-shadow:inset 0 0 0 1px hsla(0,0%,100%,.07),0 1px 5px rgba(0,0,0,.3)}.slim-btn-rotate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='252' height='287' viewBox='0 0 252 287' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M134.762.626v36.15c65.016 4.594 116.34 58.75 116.34 124.936 0 69.198-56.09 125.288-125.29 125.288C56.616 287 .525 230.91.525 161.71c0-30.036 10.592-57.59 28.215-79.17l31.934 31.934C51.03 127.75 45.27 144.04 45.27 161.71c0 44.485 36.06 80.544 80.544 80.544 44.484 0 80.544-36.058 80.544-80.543 0-41.454-31.327-75.56-71.594-80.017v35.272l-62.646-57.89L134.762.625zm-8.95 196.883c-19.77 0-35.796-16.028-35.796-35.798 0-19.77 16.027-35.796 35.797-35.796 19.77 0 35.797 16.026 35.797 35.796s-16.027 35.797-35.797 35.797z' fill='rgba(255,255,255,.8)' fill-rule='evenodd'/%3E%3C/svg%3E")}.slim-editor-btn-group,.slim-editor-utils-group{padding:1em 0 0}@media (min-width:40em){.slim-btn-group{padding-top:2em}}.slim-crop-area{position:absolute;box-shadow:inset 0 0 0 1px hsla(0,0%,100%,.75),0 0 0 1px hsla(0,0%,100%,.75)}.slim-crop-area .grid{overflow:hidden}.slim-crop-area .grid:after,.slim-crop-area .grid:before{position:absolute;z-index:2;content:"";opacity:0;-webkit-transition:opacity .5s;transition:opacity .5s}.slim-crop-area .grid:before{top:33.333%;bottom:33.333%;left:1px;right:1px;box-shadow:inset 0 -1px 0 0 hsla(0,0%,100%,.35),inset 0 1px 0 0 hsla(0,0%,100%,.35)}.slim-crop-area .grid:after{top:1px;bottom:1px;left:33.333%;right:33.333%;box-shadow:inset -1px 0 0 0 hsla(0,0%,100%,.35),inset 1px 0 0 0 hsla(0,0%,100%,.35)}.slim-crop-area button{position:absolute;background:#fafafa;box-shadow:inset 0 1px 0 0 #fff,0 1px 1px rgba(0,0,0,.15);border:none;padding:0;margin:0;width:16px;height:16px;margin-top:-8px;margin-left:-8px;border-radius:8px;z-index:3}.slim-crop-area [class*=n]{top:0}.slim-crop-area [class*=s]{top:100%}.slim-crop-area [class*=w]{left:0}.slim-crop-area [class*=e]{left:100%}.slim-crop-area .e,.slim-crop-area .w{top:50%;cursor:ew-resize;height:30px;margin-top:-15px}.slim-crop-area .n,.slim-crop-area .s{left:50%;cursor:ns-resize;width:30px;margin-left:-15px}.slim-crop-area .ne,.slim-crop-area .sw{cursor:nesw-resize}.slim-crop-area .nw,.slim-crop-area .se{cursor:nwse-resize}.slim-crop-area .c{top:10px;left:10px;width:calc(100% - 20px);height:calc(100% - 20px);margin:0;border-radius:0;border:none;z-index:2;box-shadow:none;opacity:0;cursor:move}.slim-crop-area button:not(.c):after{content:"";position:absolute;left:-12px;right:-12px;top:-12px;bottom:-12px}.slim-crop-area .slim-crop-mask{position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;z-index:1}.slim-crop-area .slim-crop-mask img{position:absolute;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateZ(0);transform:translateZ(0);margin:0!important;width:auto;height:auto;max-width:none;min-width:0}.slim-crop-area[data-dragging=true] .grid:after,.slim-crop-area[data-dragging=true] .grid:before{opacity:1}.slim-popover{-ms-touch-action:none;touch-action:none;position:fixed;left:0;top:0;width:100%;height:100%;padding:1em;font-size:16px;background:rgba(25,27,29,.99);z-index:2147483647;overflow:hidden}.slim-popover[data-state=off]{left:-100%}.slim-popover:after{position:absolute;left:0;top:0;right:0;bottom:0;content:"";background:-webkit-radial-gradient(center ellipse,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,0) 80%);background:radial-gradient(ellipse at center,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,0) 80%)}@media (min-width:40em){.slim-popover{padding:2em}}.slim,.slim-crop-area,.slim-image-editor,.slim-popover{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:border-box}.slim-crop-area button,.slim-image-editor button,.slim-popover button,.slim button{-webkit-highlight:none;-webkit-tap-highlight-color:transparent}.slim *,.slim-crop-area *,.slim-image-editor *,.slim-popover *{box-sizing:inherit}.slim-crop-area img,.slim-image-editor img,.slim-popover img,.slim img{background-color:#eee;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABG2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+Gkqr6gAAAYBpQ0NQc1JHQiBJRUM2MTk2Ni0yLjEAACiRdZHPK0RRFMc/M4gYERaKxUvDamhQExtlJqEmTWOUwWbmzS81P17vzaTJVtlOUWLj14K/gK2yVopISdlZExv0nGfUSObc7rmf+73nnO49F+yhtJoxat2Qyeb14KRXmQ8vKPWP2OjCQRtKRDW08UDAT1V7u5Fosat+q1b1uH+tKRY3VLA1CI+pmp4XnhL2r+Q1izeFO9RUJCZ8LOzS5YLC15YeLfOTxckyf1ish4I+sLcKK8lfHP3FakrPCMvLcWbSBfXnPtZLHPHs3KysPTK7MQgyiReFaSbw4WGQUfEe+hliQHZUyXd/58+Qk1xVvEYRnWWSpMjjErUg1eOyJkSPy0hTtPr/t69GYnioXN3hhboH03zphfoN+CyZ5vu+aX4eQM09nGUr+bk9GHkVvVTRnLvQsgYn5xUtugWn69B5p0X0yLdUI9OeSMDzETSHof0SGhfLPfs55/AWQqvyVRewvQN9Et+y9AUyt2fOEwKMEgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAC9JREFUOI1jZGBgkGIgDjwjRhETkYYRDUYNHDVwMBjISIJaonLU4PfyqIGjBpIBAPvwAUFW9TOIAAAAAElFTkSuQmCC")}.slim img{width:100%;height:auto}span.slim{display:block}.slim{position:relative;font-size:inherit;background-color:#eee;-webkit-transition:background-color .25s;transition:background-color .25s;padding-bottom:.025px}@-webkit-keyframes rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotate{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.slim[data-state*=empty]:hover{background-color:#ddd}.slim[data-state*=empty] .slim-label{visibility:visible;opacity:1}.slim[data-state*=busy] .slim-label{opacity:0}.slim[data-state*=loading] .slim-label{display:none}.slim[data-state*=loading] .slim-label-loading{opacity:1;display:block}.slim[data-state*=preview] .slim-label{visibility:hidden}.slim[data-state*=error]{background-color:#e8a69f!important;color:#702010}.slim>img,.slim>input[type=file]{display:block!important;opacity:0!important;width:0!important;height:0!important;padding:0!important;margin-left:0!important;margin-right:0!important;margin-top:0!important;border:0!important}.slim>img+input[type=file],.slim>input[type=file]+img{margin-bottom:0!important}.slim>input[type=hidden]{position:absolute;width:1px;height:1px;margin:-1px;opacity:0}.slim .slim-label-loading{display:none}.slim .slim-label{visibility:hidden;-webkit-transition:opacity .25s;transition:opacity .25s}.slim .slim-error,.slim .slim-label,.slim .slim-label-loading{max-width:100%}.slim .slim-file-hopper{z-index:2;background:rgba(0,0,0,.0001)}.slim .slim-area,.slim .slim-drip,.slim .slim-ratio,.slim .slim-result,.slim .slim-status{border-radius:inherit}.slim .slim-area{width:100%;color:inherit;overflow:hidden}.slim .slim-area :only-of-type{margin:0}.slim .slim-area .slim-loader{pointer-events:none;position:absolute;right:.875em;top:.875em;width:23px;height:23px;z-index:1}.slim .slim-area .slim-loader svg{display:block;width:100%;height:100%;opacity:0}.slim .slim-area .slim-upload-status{position:absolute;right:1em;top:1em;z-index:1;opacity:0;-webkit-transition:opacity .25s;transition:opacity .25s;white-space:nowrap;line-height:1.65;font-weight:400}.slim .slim-area .slim-upload-status-icon{display:inline-block;opacity:.9}.slim .slim-area .slim-drip,.slim .slim-area .slim-result,.slim .slim-area .slim-status{left:0;top:0;right:0;bottom:0}.slim .slim-area .slim-drip,.slim .slim-area .slim-result{position:absolute}.slim .slim-area .slim-status{padding:3em 1.5em;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;pointer-events:none}.slim .slim-area .slim-drip{z-index:1;overflow:hidden}.slim .slim-area .slim-drip>span{position:absolute;left:0;top:0;opacity:0;margin-left:-25%;margin-top:-25%;width:50%;padding-bottom:50%}.slim .slim-area .slim-drip>span>span{position:absolute;width:100%;height:100%;background-color:rgba(0,0,0,.25);border-radius:50%;opacity:.5;left:0;top:0}.slim .slim-area .slim-result{overflow:hidden;-webkit-perspective:1px}.slim .slim-area .slim-result img{display:block;width:100%;position:absolute;left:0;top:0}.slim .slim-area .slim-result img:not([src]),.slim .slim-area .slim-result img[src=""]{visibility:hidden}.slim .slim-btn-group{position:absolute;right:0;bottom:0;left:0;z-index:3;overflow:hidden;pointer-events:none}.slim .slim-btn-group button{pointer-events:all;cursor:pointer}.slim[data-ratio*=":"]{min-height:0}.slim[data-ratio*=":"] .slim-status{position:absolute;padding:0 1.5em}.slim[data-ratio="16:10"]>img,.slim[data-ratio="16:10"]>input[type=file]{margin-bottom:62.5%}.slim[data-ratio="10:16"]>img,.slim[data-ratio="10:16"]>input[type=file]{margin-bottom:160%}.slim[data-ratio="16:9"]>img,.slim[data-ratio="16:9"]>input[type=file]{margin-bottom:56.25%}.slim[data-ratio="9:16"]>img,.slim[data-ratio="9:16"]>input[type=file]{margin-bottom:177.77778%}.slim[data-ratio="5:3"]>img,.slim[data-ratio="5:3"]>input[type=file]{margin-bottom:60%}.slim[data-ratio="3:5"]>img,.slim[data-ratio="3:5"]>input[type=file]{margin-bottom:166.66667%}.slim[data-ratio="5:4"]>img,.slim[data-ratio="5:4"]>input[type=file]{margin-bottom:80%}.slim[data-ratio="4:5"]>img,.slim[data-ratio="4:5"]>input[type=file]{margin-bottom:125%}.slim[data-ratio="4:3"]>img,.slim[data-ratio="4:3"]>input[type=file]{margin-bottom:75%}.slim[data-ratio="3:4"]>img,.slim[data-ratio="3:4"]>input[type=file]{margin-bottom:133.33333%}.slim[data-ratio="3:2"]>img,.slim[data-ratio="3:2"]>input[type=file]{margin-bottom:66.66667%}.slim[data-ratio="2:3"]>img,.slim[data-ratio="2:3"]>input[type=file]{margin-bottom:150%}.slim[data-ratio="1:1"]>img,.slim[data-ratio="1:1"]>input[type=file]{margin-bottom:100%}.slim-btn-group{padding:1.5em 0;text-align:center}.slim-btn{position:relative;padding:0;margin:0 7.2px;font-size:0;outline:none;width:36px;height:36px;border:none;color:#fff;background-color:rgba(0,0,0,.7);background-repeat:no-repeat;background-size:50% 50%;background-position:50%;border-radius:50%}.slim-btn:before{border-radius:inherit;position:absolute;box-sizing:border-box;left:-3px;right:-3px;bottom:-3px;top:-3px;border:3px solid #fff;content:"";-webkit-transform:scale(.95);transform:scale(.95);opacity:0;-webkit-transition:all .25s;transition:all .25s;z-index:-1;pointer-events:none}.slim-btn:focus:before,.slim-btn:hover:before{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.slim-btn *{pointer-events:none}.slim-btn-remove{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 269 269' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' clip-rule='evenodd' stroke-linejoin='round' stroke-miterlimit='1.414'%3E%3Cpath d='M63.12 250.254s3.998 18.222 24.582 18.222h93.072c20.583 0 24.582-18.222 24.582-18.222l18.374-178.66H44.746l18.373 178.66zM170.034 98.442a8.95 8.95 0 0 1 17.9 0l-8.95 134.238a8.95 8.95 0 0 1-17.9 0l8.95-134.238zm-44.746 0a8.949 8.949 0 1 1 17.898 0V232.68a8.95 8.95 0 1 1-17.9 0V98.442zm-35.798-8.95a8.95 8.95 0 0 1 8.95 8.95l8.95 134.237c0 4.942-4.008 8.948-8.95 8.948a8.95 8.95 0 0 1-8.95-8.95L80.54 98.441a8.95 8.95 0 0 1 8.95-8.95zm128.868-53.68h-39.376V17.898c0-13.578-4.39-17.9-17.898-17.9H107.39C95 0 89.492 6 89.492 17.9v17.91H50.116c-7.914 0-14.32 6.007-14.32 13.43 0 7.424 6.406 13.43 14.32 13.43H218.36c7.914 0 14.32-6.006 14.32-13.43 0-7.423-6.406-13.43-14.32-13.43zm-57.274 0H107.39l.002-17.914h53.695V35.81z' fill='%23fff'/%3E%3C/svg%3E")}.slim-btn-download{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 269 269' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' clip-rule='evenodd' stroke-linejoin='round' stroke-miterlimit='1.414'%3E%3Cpath d='M232.943 223.73H35.533c-12.21 0-22.11 10.017-22.11 22.373 0 12.356 9.9 22.373 22.11 22.373h197.41c12.21 0 22.11-10.017 22.11-22.373 0-12.356-9.9-22.373-22.11-22.373zM117.88 199.136c4.035 4.04 9.216 6.147 14.492 6.508.626.053 1.227.188 1.866.188.633 0 1.228-.135 1.847-.186 5.284-.357 10.473-2.464 14.512-6.51l70.763-70.967c8.86-8.876 8.86-23.268 0-32.143-8.86-8.876-23.225-8.876-32.086 0l-32.662 32.756V22.373C156.612 10.017 146.596 0 134.238 0c-12.356 0-22.372 10.017-22.372 22.373v106.41L79.204 96.027c-8.86-8.876-23.226-8.876-32.086 0-8.86 8.875-8.86 23.267 0 32.142l70.763 70.966z' fill='%23fff'/%3E%3C/svg%3E")}.slim-btn-upload{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='243' height='269' viewBox='0 0 243 269' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3EDownload%3C/title%3E%3Cpath d='M219.943 223.73H22.533c-12.21 0-22.11 10.017-22.11 22.373 0 12.356 9.9 22.373 22.11 22.373h197.41c12.21 0 22.11-10.017 22.11-22.373 0-12.356-9.9-22.373-22.11-22.373zM104.88 6.696c4.035-4.04 9.216-6.147 14.492-6.508C119.998.135 120.6 0 121.238 0c.633 0 1.228.135 1.847.186 5.284.357 10.473 2.464 14.512 6.51l70.763 70.967c8.86 8.875 8.86 23.267 0 32.142-8.86 8.876-23.225 8.876-32.086 0L143.612 77.05v106.41c0 12.355-10.016 22.372-22.374 22.372-12.356 0-22.372-10.017-22.372-22.373V77.05l-32.662 32.755c-8.86 8.876-23.226 8.876-32.086 0-8.86-8.875-8.86-23.267 0-32.142L104.88 6.696z' fill='%23FFF' fill-rule='evenodd'/%3E%3C/svg%3E")}.slim-btn-edit{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 269 269' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' clip-rule='evenodd' stroke-linejoin='round' stroke-miterlimit='1.414'%3E%3Cpath d='M161.36 56.337c-7.042-7.05-18.46-7.05-25.5 0l-6.373 6.38-89.243 89.338.023.023-2.812 2.82s-8.968 9.032-29.216 74.4c-.143.456-.284.91-.427 1.373-.36 1.172-.726 2.362-1.094 3.568a785.126 785.126 0 0 0-.988 3.25c-.28.922-.556 1.835-.84 2.778-.64 2.14-1.29 4.318-1.954 6.567-1.455 4.937-5.01 16.07-.99 20.1 3.87 3.882 15.12.467 20.043-.993a1275.615 1275.615 0 0 0 9.41-2.83c1.032-.314 2.058-.626 3.063-.935 1.27-.39 2.52-.775 3.75-1.157l1.09-.34c62.193-19.365 73.358-28.453 74.286-29.284l.01-.01.067-.06 2.88-2.886.192.193 89.244-89.336 6.373-6.382c7.04-7.048 7.04-18.476 0-25.525l-50.998-51.05zM103.4 219.782c-.08.053-.185.122-.297.193l-.21.133c-.076.047-.158.098-.245.15l-.243.148c-2.97 1.777-11.682 6.362-32.828 14.017-2.47.894-5.162 1.842-7.98 2.82l-30.06-30.092c.98-2.84 1.928-5.55 2.825-8.04 7.638-21.235 12.22-29.974 13.986-32.94l.12-.2c.063-.1.12-.196.175-.283l.126-.2c.07-.11.14-.217.192-.296l2.2-2.205 54.485 54.542-2.248 2.255zM263.35 56.337l-50.996-51.05c-7.04-7.048-18.456-7.048-25.498 0L174.108 18.05c-7.04 7.048-7.04 18.476 0 25.524l50.996 51.05c7.04 7.048 18.457 7.048 25.498 0l12.75-12.762c7.04-7.05 7.04-18.477 0-25.525z' fill='%23fff'/%3E%3C/svg%3E")}.slim-loader-background{stroke:rgba(0,0,0,.15)}.slim-loader-foreground{stroke:rgba(0,0,0,.65)}.slim[data-state*=preview] .slim-loader-background{stroke:hsla(0,0%,100%,.25)}.slim[data-state*=preview] .slim-loader-foreground{stroke:#fff}.slim-upload-status{padding:0 .5em;border-radius:.3125em;font-size:.75em;box-shadow:0 .125em .25em rgba(0,0,0,.25)}.slim-upload-status[data-state=success]{background-color:#d1ed8f;color:#323e15}.slim-upload-status[data-state=success] .slim-upload-status-icon{width:.5em;height:.75em;-webkit-transform:rotate(45deg);transform:rotate(45deg);border:.1875em solid currentColor;border-left:none;border-top:none;margin-right:.325em;margin-left:.25em;margin-bottom:.0625em}.slim-upload-status[data-state=error]{background:#efd472;color:#574016}.slim-upload-status[data-state=error] .slim-upload-status-icon{margin-left:-.125em;margin-right:.5em;width:.5625em;height:1em;position:relative;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.slim-upload-status[data-state=error] .slim-upload-status-icon:after,.slim-upload-status[data-state=error] .slim-upload-status-icon:before{content:"";position:absolute;box-sizing:content-box;width:0;height:0;border:.09em solid currentColor;background-color:currentColor;-webkit-transform:translate(-50%,-50%) translate(.5em,.5em);transform:translate(-50%,-50%) translate(.5em,.5em)}.slim-upload-status[data-state=error] .slim-upload-status-icon:before{width:.66666666667em}.slim-upload-status[data-state=error] .slim-upload-status-icon:after{height:.66666666667em} \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/css/style-rtl.css b/deployed/jsn/components/com_jsn/assets/css/style-rtl.css new file mode 100644 index 00000000..8ffeb88a --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/style-rtl.css @@ -0,0 +1,50 @@ +/* Author */ +img.avatar.author_avatar{margin-left:0px;margin-right:5px;} + +/* Privacy */ +.control-group.privacy .privacy_btn,.form-group.privacy .privacy_btn{right:auto;padding-left:0px;left:8px;padding-right:5px;} +.control-group.privacy ul,.form-group.privacy ul{text-align:right;margin-right:0px;margin-left:4px;right:auto} + +/* Maps */ +input.jsn_map_search{float:right;} +select.gmap_radius_select{float:right;margin-left:0%;margin-right:2%;} + +/* Search */ +.numericsearch,div.jsn_search .bsdatesearch{float:right;} +.numericsearch + .numericsearch,div.jsn_search .bsdatesearch + .bsdatesearch{margin-left:0%;margin-right:2%;} + +/* Registration - Edit Profile */ +.jsn_registration_controls{margin-right:0px !important;} + +/* Radio & Checkbox */ +label.checkbox,label.radio{padding-left:0px;padding-right:20px;} +label.radio.inline + label.radio.inline,label.checkbox.inline + label.checkbox.inline {margin-left: 0px;margin-right:10px;} + +/* Profile & Lists */ +.jsn-p-opt{text-align: left;} +.jsn-p-date-reg{margin-right:0px;margin-left:10px;} +.jsn-p-top-a .jsn-p-title,.jsn-p-top-a .jsn-p-before-fields{margin-left:0px;margin-right:120px;} +.jsn-p-top-a .status.label,.jsn-l-top-a .status.label{left:auto;right:-5px;} +.jsn-p-avatar,.jsn-l-avatar{float:right;} +@media (max-width: 767px){ + .jsn-p-top-a .jsn-p-title, + .jsn-p-top-a .jsn-p-before-fields {clear:both;margin-right:0px;} + .jsn-p-top-a .status.label{right:50%;margin-left:0px;margin-right:-55px;} + .jsn-p-avatar{float:none;} +} +.jsn-l-top-a .jsn-l-title,.jsn-l-top-a .jsn-l-fields{margin-left:0px;margin-right:60px;} +.jsn-l-map{padding:5px 5px 0 0px;} + +/* Field List */ +.jsn-p-fields dl dt,.jsn-p-fields dl dd{text-align:right;} +@media(min-width:767px){ + .jsn-p-fields dl dt{float:right;text-align:left;} + .jsn-p-fields dl dd{margin-left:0px;margin-right:180px;} +} + +/* Date Field */ +.jsndatepicker:before {right: 6px;left:auto;} +.jsndatepicker:after {right: 7px;left:auto;} + +/* Tabs */ +#jsn-form.horizontal>ul>li {float: right;} diff --git a/deployed/jsn/components/com_jsn/assets/css/style-rtl.min.css b/deployed/jsn/components/com_jsn/assets/css/style-rtl.min.css new file mode 100644 index 00000000..42f8ea02 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/style-rtl.min.css @@ -0,0 +1 @@ +img.avatar.author_avatar{margin-left:0;margin-right:5px}.control-group.privacy .privacy_btn,.form-group.privacy .privacy_btn{right:auto;padding-left:0;left:8px;padding-right:5px}.control-group.privacy ul,.form-group.privacy ul{text-align:right;margin-right:0;margin-left:4px;right:auto}input.jsn_map_search{float:right}select.gmap_radius_select{float:right;margin-left:0;margin-right:2%}.numericsearch,div.jsn_search .bsdatesearch{float:right}.numericsearch + .numericsearch,div.jsn_search .bsdatesearch + .bsdatesearch{margin-left:0;margin-right:2%}.jsn_registration_controls{margin-right:0!important}label.checkbox,label.radio{padding-left:0;padding-right:20px}label.radio.inline + label.radio.inline,label.checkbox.inline + label.checkbox.inline{margin-left:0;margin-right:10px}.jsn-p-opt{text-align:left}.jsn-p-date-reg{margin-right:0;margin-left:10px}.jsn-p-top-a .jsn-p-title,.jsn-p-top-a .jsn-p-before-fields{margin-left:0;margin-right:120px}.jsn-p-top-a .status.label,.jsn-l-top-a .status.label{left:auto;right:-5px}.jsn-p-avatar,.jsn-l-avatar{float:right}@media (max-width: 767px){.jsn-p-top-a .jsn-p-title,.jsn-p-top-a .jsn-p-before-fields{clear:both;margin-right:0}.jsn-p-top-a .status.label{right:50%;margin-left:0;margin-right:-55px}.jsn-p-avatar{float:none}}.jsn-l-top-a .jsn-l-title,.jsn-l-top-a .jsn-l-fields{margin-left:0;margin-right:60px}.jsn-l-map{padding:5px 5px 0 0}.jsn-p-fields dl dt,.jsn-p-fields dl dd{text-align:right}@media(min-width:767px){.jsn-p-fields dl dt{float:right;text-align:left}.jsn-p-fields dl dd{margin-left:0;margin-right:180px}}.jsndatepicker:before{right:6px;left:auto}.jsndatepicker:after{right:7px;left:auto}#jsn-form.horizontal>ul>li{float:right;} \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/css/style.css b/deployed/jsn/components/com_jsn/assets/css/style.css new file mode 100644 index 00000000..d1acde1c --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/style.css @@ -0,0 +1,169 @@ +@import url(./icons.min.css); + +/* Author */ +img.avatar.author_avatar{border-radius:3px;height:20px;width:20px;display:inline-block;margin-left:5px;} + +/* Privacy */ +.control-group.privacy,.control-group.privacy > div,.form-group.privacy,.form-group.privacy > div{height:0px !important;margin-top:0 !important;margin-bottom:0 !important;padding-top:0 !important;padding-bottom:0 !important;position:relative !important;} +.control-group.privacy .privacy_btn,.form-group.privacy .privacy_btn{z-index:100;position:absolute;margin-top:6px;right:8px;color:black;padding-left:5px;text-decoration:none;line-height:normal;} +.control-group.privacy .privacy_btn:hover,.form-group.privacy .privacy_btn:hover{text-decoration:none;color:black;} +.control-group.privacy .privacy_btn .caret{top:-4px;position:relative;} +.control-group.privacy ul,.form-group.privacy ul{z-index:200;margin-top:30px;text-align:left;margin-right:4px;} +.control-group.privacy div.dropdown,.form-group.privacy div.dropdown{display:block;} +.red{color:red;} +.orange{color:orange;} +.green{color:green;} + +/* Maps */ +.jsn_map{height:300px;border:10px solid #ddd} +input.jsn_map_search{float:left;width:70% !important;} +select.gmap_radius_select{float:left;width:28%;margin-left:2%;display:block !important;} +select.gmap_radius_select + div.chzn-container{display:none !important;} +.gm-style img{max-width:none !important;} +.jsn_map_address + .jsn_map,.input-prepend + .jsn_map{margin-top:10px;} + +/* Search */ +.bsdatesearch,.numericsearch{margin-bottom:5px;width:100%;} +.numericsearch,div.jsn_search .bsdatesearch{float:left;width:49%;} +.numericsearch + .numericsearch,div.jsn_search .bsdatesearch + .bsdatesearch{margin-left:2%;} +.bsdatesearch .input-prepend{margin-bottom:0px;} +div.jsn_search label.control-label,div.jsn_search_module label.control-label{font-weight:bold;} +div.jsn_search_module .chzn-container,div.jsn_search .chzn-container{min-width:80px !important;width:100% !important;} +div.jsn_search_module input,div.jsn_search input,div.jsn_search_module > input-prepend,div.jsn_search > input-prepend{width:100%;box-sizing:border-box;height:auto;margin-bottom:0px;} +div.jsn_search_module input[type="submit"],div.jsn_search input[type="submit"]{margin-top:10px;} + +/* Registration - Edit Profile */ +.jsn_registration_controls{margin-left:0px !important;width:auto;float:none;} +#member-profile .control-group,#member-registration .control-group{clear:both;} +#member-profile .control-group.privacy + .control-group,#member-registration .control-group.privacy + .control-group {clear:none;} +#member-profile .chzn-container,#member-registration .chzn-container{min-width:200px !important;max-width:100% !important;} +.controls > fieldset.checkboxes,.controls > fieldset.radio,.controls > fieldset.radio:first-child{margin:0px;padding:0px;} +.controls .icon{text-transform:none !important;} +#member-profile .control-label .optional, #member-registration .control-label .optional{display:none;} + +/* Radio & Checkbox */ +label.checkbox,label.radio{padding-left:20px;display:block;line-height:18px;} +label.checkbox input,label.radio input{width:auto;} +label.radio.inline,label.checkbox.inline{display:inline-block;margin-top:0px;} +label.radio.inline + label.radio.inline,label.checkbox.inline + label.checkbox.inline {margin-left: 10px;} + +/* Append Block */ +div.jsn_search .input-prepend,div.jsn_search_module .input-prepend,#member-profile .input-prepend,#member-registration .input-prepend,#filters .input-prepend {display:table !important;font-size:inherit;} +div.jsn_search .input-prepend > *,div.jsn_search_module .input-prepend > *,#member-profile .input-prepend > *,#member-registration .input-prepend > *,#filters .input-prepend > *{display: table-cell;float:none;position: relative;white-space: nowrap;} +div.jsn_search .input-prepend > .btn,div.jsn_search_module .input-prepend > .btn,#member-profile .input-prepend > .btn,#member-registration .input-prepend > .btn,#filters .input-prepend > .btn{width: 1%;height:100%;vertical-align:middle;padding:0px 12px;line-height:14px;font-size:14px;} +div.jsn_search .input-prepend > .btn .icon,div.jsn_search_module .input-prepend > .btn .icon,#member-profile .input-prepend > .btn .icon,#member-registration .input-prepend > .btn .icon,#filters .input-prepend > .btn .icon{margin:0px;} +div.jsn_search .input-prepend > input,div.jsn_search_module .input-prepend > input,#member-profile .input-prepend > input,#member-registration .input-prepend > input,#filters .input-prepend > input{z-index: 2;float: left;margin-bottom: 0;width:100%;} + +/* Fix choosen in some template */ +.chzn-search input{float:none !important;} + +/* Profile & Lists */ +.jsn-p-opt{text-align: right;} +.jsn-p-top,.jsn-l-top{position:relative;} +.jsn-p-top,.jsn-p-avatar{margin-bottom:2em;} +.jsn-p-dates > div{font-size:13px;line-height:20px;display:inline-block;} +.jsn-p-date-reg{margin-right:10px;} +.jsn-p-top-a .jsn-p-title,.jsn-p-top-a .jsn-p-before-fields{margin-left:120px;} +.jsn-p-title h3,.jsn-l-title h3{display:inline;font-size:30px;line-height:1;} +.jsn-p-title .status.label,.jsn-l-title .status.label { + font-size: 0px; + height: 15px; + width: 15px; + border-radius: 1000px; + padding: 0; + display:inline-block; + border:2px solid white; + box-sizing:border-box; + vertical-align: text-top; +} +.jsn-l-title .status.label{width:14px;height:14px;} +.jsn-l-top,.jsn-l-avatar{margin-bottom:20px;} +.jsn-p-top-a .status.label,.jsn-l-top-a .status.label{position:absolute;left:-5px;top:-5px;} +.jsn-p-avatar,.jsn-l-avatar{float:left;} +.jsn-p-avatar img,.jsn-l-avatar img{width:100px;display:block;border-radius:4px;box-sizing:border-box;} +.jsn_profilesocial {margin-top:4px;} +@media (max-width: 767px){ + .jsn-p-top-a .jsn-p-title, + .jsn-p-top-a .jsn-p-before-fields {clear:both;margin-left:0px;} + .jsn-p-top{text-align:center;} + .jsn-p-avatar{float:none;} + .jsn-p-avatar img{margin:auto;} + .jsn-p-top-a .status.label{left:50%;margin-left:-55px;} + .jsn-p-opt{text-align: center;margin-bottom:10px;} +} +.jsn-l-title h3{font-size:14px;font-weight: normal;} +.jsn-l-avatar img{width:50px;} +.jsn-l-fields{font-size:13px;line-height:16px;} +.jsn-l-top-a .jsn-l-title,.jsn-l-top-a .jsn-l-fields{margin-left:60px;} +.jsn-l-field-title{font-weight:bold;} +.jsn-list{display:table;width:100%;} +.jsn-l-row{clear:both;display:table-row;} +.jsn-l-w12, .jsn-l-w6, .jsn-l-w4, .jsn-l-w3, .jsn-l-w2, .jsn-l-w1{box-sizing:border-box;display:table-cell;border-bottom:1px #ccc dashed;padding-top:20px;} +.jsn-l-w12{width:100%;} +.jsn-l-w6{width:50%;} +.jsn-l-w4{width:33.333%;} +.jsn-l-w3{width:25%;} +.jsn-l-w2{width:16.666%;} +.jsn-l-w1{width:8.333%;} +@media (max-width: 767px){ + .jsn-list{display:block;width:100%;} + .jsn-l-row{display:block;} + .jsn-l-w12, .jsn-l-w6, .jsn-l-w4, .jsn-l-w3, .jsn-l-w2, .jsn-l-w1{width:100%;display:block;clear:both;} +} +.jsn-l-map{padding:5px 0 0 5px;} +.jsn-form-fieldset,.jsn-form-fieldset > dl{margin-top:0px;padding-top:0px;} +.jsn-total,.jsn-export{padding-bottom:10px;} +.jsn-p-fields .no-title{display:none;} + +/* Field List */ +.jsn-p-fields dl dt,.jsn-p-fields dl dd{margin:0;padding:0;float:none;display:block;text-align:left;width:auto;line-height:normal;} +.jsn-p-fields dl dd{margin:0 0 5px 0;padding:0 0 5px 0;border-bottom:1px dotted #ddd;} +.jsn-p-fields dl dd:after{content:"";clear:both;display:block;} +@media(min-width:767px){ + .jsn-p-fields dl dt{width:160px;float:left;text-align:right;} + .jsn-p-fields dl dd{margin-left:180px;} +} + +/* Map Module */ +.jsn-map{position:relative;border:10px solid #ddd;} +.jsn-map.empty > div{display:none !important;} +.jsn-map.empty{background:url(../img/emptymap.png) no-repeat center center #e5e3df;} + +/* Alerts */ +label.invalid{color:#9D261D !important;} +.control-group .controls .invalid,.control-group .controls .invalid + .chzn-container > .chzn-single, +.control-group .controls .invalid + .chzn-container >.chzn-choices{border-color:#9D261D !important;} + +/* Error Messages */ +.message-regex {color: #9D261D;font-size: 12px;display: none;} +input.invalid:not(.empty-val) + .message-regex {display: block;} + +/* Tabs */ +a.z-link {text-overflow: ellipsis;white-space: nowrap;overflow:hidden;} +#jsn-form.z-tabs > .z-container,#jsn-form.z-tabs > .z-container > .z-content{overflow: visible;z-index:auto;} +#jsn-form.z-tabs > ul#jsn-profile-tabs{border-radius:4px;overflow:hidden;} +#jsn-form.z-tabs > ul#jsn-profile-tabs > li.z-tab a{top:0px;} +#jsn-form.z-tabs > ul#jsn-profile-tabs > li.z-tab.z-first-row a{margin-top:0 !important;} +#member-registration,#member-profile,.jsn-p-fields #jsn-form{overflow: visible;} +#jsn-form.mobile>ul.z-tabs-nav, #jsn-form.mobile>ul.z-tabs-nav.z-tabs-mobile{box-sizing:border-box;overflow:hidden;border-radius:4px;} + +/* Images D&D button fix */ +#member-registration .slim-btn-group,#member-profile .slim-btn-group{padding:10px 0;} +.slim-image-editor .slim-btn-group button {line-height:1} + +/* Strenghmeter Fix */ +#jform_password1 + div{max-width:100% !important;} + +/* Fieldgroup description */ +#jsn-form.z-tabs > ul#jsn-profile-tabs li > a{font-size:14px;} +#jsn-form.z-tabs > ul#jsn-profile-tabs li > a span,#member-profile > fieldset > legend span,#member-registration > fieldset > legend span{display:block;font-size:12px;font-weight:normal;} + +/* Animation */ +@keyframes jsnpulse { + 0% { + transform: scale(.95); + } + 100% { + transform: scale(1.0); + } +} diff --git a/deployed/jsn/components/com_jsn/assets/css/style.min.css b/deployed/jsn/components/com_jsn/assets/css/style.min.css new file mode 100644 index 00000000..0632ff44 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/style.min.css @@ -0,0 +1,3 @@ +@import "./icons.min.css";img.avatar.author_avatar{border-radius:3px;height:20px;width:20px;display:inline-block;margin-left:5px}.control-group.privacy,.control-group.privacy > div,.form-group.privacy,.form-group.privacy > div{height:0!important;margin-top:0!important;margin-bottom:0!important;padding-top:0!important;padding-bottom:0!important;position:relative!important}.control-group.privacy .privacy_btn,.form-group.privacy .privacy_btn{z-index:100;position:absolute;margin-top:6px;right:8px;color:#000;padding-left:5px;text-decoration:none;line-height:normal}.control-group.privacy .privacy_btn:hover,.form-group.privacy .privacy_btn:hover{text-decoration:none;color:#000}.control-group.privacy .privacy_btn .caret{top:-4px;position:relative}.control-group.privacy ul,.form-group.privacy ul{z-index:200;margin-top:30px;text-align:left;margin-right:4px}.control-group.privacy div.dropdown,.form-group.privacy div.dropdown{display:block}.red{color:red}.orange{color:orange}.green{color:green}.jsn_map{height:300px;border:10px solid #ddd}input.jsn_map_search{float:left;width:70%!important}select.gmap_radius_select{float:left;width:28%;margin-left:2%;display:block!important}select.gmap_radius_select + div.chzn-container{display:none!important}.gm-style img{max-width:none!important}.jsn_map_address + .jsn_map,.input-prepend + .jsn_map{margin-top:10px}.bsdatesearch,.numericsearch{margin-bottom:5px;width:100%}.numericsearch,div.jsn_search .bsdatesearch{float:left;width:49%}.numericsearch + .numericsearch,div.jsn_search .bsdatesearch + .bsdatesearch{margin-left:2%}.bsdatesearch .input-prepend{margin-bottom:0}div.jsn_search label.control-label,div.jsn_search_module label.control-label{font-weight:700}div.jsn_search_module .chzn-container,div.jsn_search .chzn-container{min-width:80px!important;width:100%!important}div.jsn_search_module input,div.jsn_search input,div.jsn_search_module > input-prepend,div.jsn_search > input-prepend{width:100%;box-sizing:border-box;height:auto;margin-bottom:0}div.jsn_search_module input[type="submit"],div.jsn_search input[type="submit"]{margin-top:10px}.jsn_registration_controls{margin-left:0!important;width:auto;float:none}#member-profile .control-group,#member-registration .control-group{clear:both}#member-profile .control-group.privacy + .control-group,#member-registration .control-group.privacy + .control-group{clear:none}#member-profile .chzn-container,#member-registration .chzn-container{min-width:200px!important;max-width:100%!important}.controls > fieldset.checkboxes,.controls > fieldset.radio,.controls > fieldset.radio:first-child{margin:0;padding:0}.controls .icon{text-transform:none!important}#member-profile .control-label .optional,#member-registration .control-label .optional{display:none}label.checkbox,label.radio{padding-left:20px;display:block;line-height:18px}label.checkbox input,label.radio input{width:auto}label.radio.inline,label.checkbox.inline{display:inline-block;margin-top:0}label.radio.inline + label.radio.inline,label.checkbox.inline + label.checkbox.inline{margin-left:10px}div.jsn_search .input-prepend,div.jsn_search_module .input-prepend,#member-profile .input-prepend,#member-registration .input-prepend,#filters .input-prepend{display:table!important;font-size:inherit}div.jsn_search .input-prepend > *,div.jsn_search_module .input-prepend > *,#member-profile .input-prepend > *,#member-registration .input-prepend > *,#filters .input-prepend > *{display:table-cell;float:none;position:relative;white-space:nowrap}div.jsn_search .input-prepend > .btn,div.jsn_search_module .input-prepend > .btn,#member-profile .input-prepend > .btn,#member-registration .input-prepend > .btn,#filters .input-prepend > .btn{width:1%;height:100%;vertical-align:middle;padding:0 12px;line-height:14px;font-size:14px}div.jsn_search .input-prepend > .btn .icon,div.jsn_search_module .input-prepend > .btn .icon,#member-profile .input-prepend > .btn .icon,#member-registration .input-prepend > .btn .icon,#filters .input-prepend > .btn .icon{margin:0}div.jsn_search .input-prepend > input,div.jsn_search_module .input-prepend > input,#member-profile .input-prepend > input,#member-registration .input-prepend > input,#filters .input-prepend > input{z-index:2;float:left;margin-bottom:0;width:100%}.chzn-search input{float:none!important}.jsn-p-opt{text-align:right}.jsn-p-top,.jsn-l-top{position:relative}.jsn-p-top,.jsn-p-avatar{margin-bottom:2em}.jsn-p-dates > div{font-size:13px;line-height:20px;display:inline-block}.jsn-p-date-reg{margin-right:10px}.jsn-p-top-a .jsn-p-title,.jsn-p-top-a .jsn-p-before-fields{margin-left:120px}.jsn-p-title h3,.jsn-l-title h3{display:inline;font-size:30px;line-height:1}.jsn-p-title .status.label,.jsn-l-title .status.label{font-size:0;height:15px;width:15px;border-radius:1000px;padding:0;display:inline-block;border:2px solid #fff;box-sizing:border-box;vertical-align:text-top}.jsn-l-title .status.label{width:14px;height:14px}.jsn-l-top,.jsn-l-avatar{margin-bottom:20px}.jsn-p-top-a .status.label,.jsn-l-top-a .status.label{position:absolute;left:-5px;top:-5px}.jsn-p-avatar,.jsn-l-avatar{float:left}.jsn-p-avatar img,.jsn-l-avatar img{width:100px;display:block;border-radius:4px;box-sizing:border-box}.jsn_profilesocial{margin-top:4px}@media (max-width: 767px){.jsn-p-top-a .jsn-p-title,.jsn-p-top-a .jsn-p-before-fields{clear:both;margin-left:0}.jsn-p-top{text-align:center}.jsn-p-avatar{float:none}.jsn-p-avatar img{margin:auto}.jsn-p-top-a .status.label{left:50%;margin-left:-55px}.jsn-p-opt{text-align:center;margin-bottom:10px}}.jsn-l-title h3{font-size:14px;font-weight:400}.jsn-l-avatar img{width:50px}.jsn-l-fields{font-size:13px;line-height:16px}.jsn-l-top-a .jsn-l-title,.jsn-l-top-a .jsn-l-fields{margin-left:60px}.jsn-l-field-title{font-weight:700}.jsn-list{display:table;width:100%}.jsn-l-row{clear:both;display:table-row}.jsn-l-w12,.jsn-l-w6,.jsn-l-w4,.jsn-l-w3,.jsn-l-w2,.jsn-l-w1{box-sizing:border-box;display:table-cell;border-bottom:1px #ccc dashed;padding-top:20px}.jsn-l-w12{width:100%}.jsn-l-w6{width:50%}.jsn-l-w4{width:33.333%}.jsn-l-w3{width:25%}.jsn-l-w2{width:16.666%}.jsn-l-w1{width:8.333%}@media (max-width: 767px){.jsn-list{display:block;width:100%}.jsn-l-row{display:block}.jsn-l-w12,.jsn-l-w6,.jsn-l-w4,.jsn-l-w3,.jsn-l-w2,.jsn-l-w1{width:100%;display:block;clear:both}}.jsn-l-map{padding:5px 0 0 5px}.jsn-form-fieldset,.jsn-form-fieldset > dl{margin-top:0;padding-top:0}.jsn-total,.jsn-export{padding-bottom:10px}.jsn-p-fields .no-title{display:none}.jsn-p-fields dl dt,.jsn-p-fields dl dd{margin:0;padding:0;float:none;display:block;text-align:left;width:auto;line-height:normal}.jsn-p-fields dl dd{margin:0 0 5px;padding:0 0 5px;border-bottom:1px dotted #ddd}.jsn-p-fields dl dd:after{content:"";clear:both;display:block}@media(min-width:767px){.jsn-p-fields dl dt{width:160px;float:left;text-align:right}.jsn-p-fields dl dd{margin-left:180px}}.jsn-map{position:relative;border:10px solid #ddd}.jsn-map.empty > div{display:none!important}.jsn-map.empty{background:url(../img/emptymap.png) no-repeat center center #e5e3df}label.invalid{color:#9D261D!important}.control-group .controls .invalid,.control-group .controls .invalid + .chzn-container > .chzn-single,.control-group .controls .invalid + .chzn-container >.chzn-choices{border-color:#9D261D!important}.message-regex{color:#9D261D;font-size:12px;display:none}input.invalid:not(.empty-val) + .message-regex{display:block}a.z-link{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}#jsn-form.z-tabs > .z-container,#jsn-form.z-tabs > .z-container > .z-content{overflow:visible;z-index:auto}#jsn-form.z-tabs > ul#jsn-profile-tabs{border-radius:4px;overflow:hidden}#jsn-form.z-tabs > ul#jsn-profile-tabs > li.z-tab a{top:0}#jsn-form.z-tabs > ul#jsn-profile-tabs > li.z-tab.z-first-row a{margin-top:0!important}#member-registration,#member-profile,.jsn-p-fields #jsn-form{overflow:visible}#jsn-form.mobile>ul.z-tabs-nav,#jsn-form.mobile>ul.z-tabs-nav.z-tabs-mobile{box-sizing:border-box;overflow:hidden;border-radius:4px}#member-registration .slim-btn-group,#member-profile .slim-btn-group{padding:10px 0}.slim-image-editor .slim-btn-group button{line-height:1} +#jform_password1 + div{max-width:100%!important}@keyframes jsnpulse{0%{transform:scale(.95)}100%{transform:scale(1.0)}} +#jsn-form.z-tabs>ul#jsn-profile-tabs li>a{font-size:14px;}#jsn-form.z-tabs > ul#jsn-profile-tabs li>a span,#member-profile > fieldset > legend span,#member-registration > fieldset > legend span{display:block;font-size:12px;font-weight:normal;} diff --git a/deployed/jsn/components/com_jsn/assets/css/tabs.css b/deployed/jsn/components/com_jsn/assets/css/tabs.css new file mode 100644 index 00000000..cf19ca49 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/tabs.css @@ -0,0 +1,1502 @@ +/* +core +horizontal +flat.core +flat.style +mobile +finalfix (code below) +replace + .z-tabs(space) -> #jsn-form + .z-tabs, -> #jsn-form, + .z-tabs. -> #jsn-form. +check jsn comment +*/ +/************************************************************************** +* @name Zozo UI Tabs +* @descripton Create awesome tabbed content area +* @version 6.4 +* @requires jQuery v1.7 or later +* @copyright Copyright (c) 2013 Zozo UI +* @author Zozo UI +* @URL: http://www.zozoui.com +* +* 1. Core (structure) +* 2. Sizes +* 3. AJAX Support +* 4. Video +* 5. Icons +* 6. Helper classes +* +* Most of the time you shouldn't delete/edit section 1 (Core). +* You can delete/edit sizes, video, icons support and Helper classes if you need. +* +**************************************************************************/ + +/*#region ========================================================================== + Import Fonts (google fonts) +========================================================================== */ +/* JSN-EDIT */ +@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,400,800); +/* JSN-REMOVED +@import url(http://fonts.googleapis.com/css?family=Lato:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic); +*/ +/*#endregion*/ + + +/*#region ========================================================================== + Global Reset +========================================================================== */ + +/* cross browser compatibility html5 tags */ +article, aside, figcaption, figure, footer, header, hgroup, nav, section {display: block;} + +/*reset box-sizing*/ +#jsn-form, +#jsn-form > ul, +#jsn-form > ul > li, +#jsn-form > ul > li > a, +#jsn-form > .z-container, +#jsn-form > .z-container > .z-content, +#jsn-form > .z-container > .z-content > .z-content-inner { + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + + + #jsn-form, .z-tabs:before, .z-tabs:after { + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; + } + + /* common reset*/ + #jsn-form, + #jsn-form > ul, + #jsn-form > ul > li, + #jsn-form > ul > li > a { + position: relative; + margin: 0; + padding: 0; + border: 0; + outline: 0; + display: block; + outline: 0 none; + text-decoration: none; + list-style: none; + list-style-type: none; + } + + /*clear floats after each content*/ + #jsn-form > .z-container > .z-content::after, + #jsn-form > .z-container > .z-content > .z-content-inner::after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + + /*clear floats after each content For IE 6/7 */ + #jsn-form > .z-container > .z-content, + #jsn-form > .z-container > .z-content > .z-content-inner { + zoom: 1; + } + + +/*#endregion*/ + + + + +/*#region ========================================================================== + Core (structure) +========================================================================== */ +/* JSN-REMOVED*/ +#jsn-form { + clear: both; + /* JSN_REMOVED color: #333; + font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; */ +} + + #jsn-form > ul > li > a { + color: #111; + line-height: 18px; + font-weight: inherit; + font-size: 12px; + padding: 13px 24px; + background: #fff; + cursor: pointer; + } + + #jsn-form > ul > li.z-active > a { + cursor: default; + } + + #jsn-form > ul, + #jsn-form > ul > li > a, + #jsn-form > .z-container { + border-color: #CECECE; + border-style: solid; + } + + #jsn-form > .z-container { + padding: 0; + margin: 0; + border-width: 1px; + background: #fff; + position: relative; + overflow: hidden; + } + + #jsn-form > .z-container > .z-content { + position: absolute; + width: 100%; + height: 100%; + overflow: hidden; + padding: 0; + z-index: 7; + display: none; + } + + #jsn-form > .z-container > .z-content.z-active { + z-index: 8; + } + + #jsn-form > .z-container > .z-content > .z-content-inner { + padding: 18px 0px; /* JSN-EDIT 18px 24px */ + height: auto; + } + + /*#endregion*/ + + + + +/*#region ========================================================================== + Sizes +========================================================================== */ +/* version 6.0 +#jsn-form.mini > ul > li > a, +#jsn-form.small > ul > li > a {font-weight: inherit;} + +#jsn-form.mini > ul > li.z-active > a, +#jsn-form.small > ul > li.z-active > a {font-weight: bold;}*/ + + +/*top padding +2 and left -4*/ + +/*default sizes*/ +#jsn-form.mini > ul > li > a {font-size: 11px;padding: 7px 16px;} +#jsn-form.small > ul > li > a {font-size: 11px;padding: 10px 16px;} +#jsn-form.medium > ul > li > a {font-size: 12px;padding: 15px 20px;} +#jsn-form.large > ul > li > a {font-size: 13px;padding: 16px 24px;} +#jsn-form.xlarge > ul > li > a {font-size: 14px;padding: 19px 28px;} +#jsn-form.xxlarge > ul > li > a {font-size: 15px;padding: 22px 32px;} + +/*vertical sizes*/ +#jsn-form.mini.vertical > ul > li > a {padding: 7px 13px;} +#jsn-form.small.vertical > ul > li > a {padding: 10px 16px;} +#jsn-form.medium.vertical > ul > li > a {padding: 13px 19px;} +#jsn-form.large.vertical > ul > li > a {padding: 16px 22px;} +#jsn-form.xlarge.vertical > ul > li > a {padding: 19px 25px;} +#jsn-form.xxlarge.vertical > ul > li > a {padding: 22px 28px;} + + +#jsn-form.white.z-bordered > ul > li.z-active > a {color: #D13636;} + +/*vertical left size white theme with border*/ +#jsn-form.vertical.top-right.white.z-bordered > ul > li.z-active > a {border-right: 3px solid #D13636;} +#jsn-form.vertical.top-left.white.z-bordered > ul > li.z-active > a {border-left: 3px solid #D13636;} + +#jsn-form.mini.vertical.top-right.white.z-bordered > ul > li.z-active > a {border-right: 1px solid #D13636;} +#jsn-form.mini.vertical.top-left.white.z-bordered > ul > li.z-active > a {border-left: 1px solid #D13636;} + +#jsn-form.small.vertical.top-right.white.z-bordered > ul > li.z-active > a {border-right: 2px solid #D13636;} +#jsn-form.small.vertical.top-left.white.z-bordered > ul > li.z-active > a {border-left: 2px solid #D13636;} + +#jsn-form.mini.vertical.top-left.white.z-bordered > ul > li.z-active > a {padding-left: 10px;} +#jsn-form.small.vertical.top-left.white.z-bordered > ul > li.z-active > a {padding-left: 13px;} +#jsn-form.medium.vertical.top-left.white.z-bordered > ul > li.z-active > a {padding-left: 16px;} +#jsn-form.large.vertical.top-left.white.z-bordered > ul > li.z-active > a {padding-left: 19px;} +#jsn-form.xlarge.vertical.top-left.white.z-bordered > ul > li.z-active > a {padding-left: 22px;} +#jsn-form.xxlarge.vertical.top-left.white.z-bordered > ul > li.z-active > a {padding-left: 25px;} + + +/*horizontal top size white theme with border*/ +#jsn-form.horizontal.top.white.z-bordered > ul > li.z-active > a {border-top: 3px solid #F44343;margin-top: 0;margin-bottom: 0;} + + + +#jsn-form.mini.horizontal.top.white.z-bordered > ul > li.z-active > a {padding-top: 7px; border-top-width: 1px} +#jsn-form.small.horizontal.top.white.z-bordered > ul > li.z-active > a {padding-top: 9px;border-top-width: 2px} +#jsn-form.medium.horizontal.top.white.z-bordered > ul > li.z-active > a {padding-top: 13px;} +#jsn-form.large.horizontal.top.white.z-bordered > ul > li.z-active > a {padding-top: 14px;} +#jsn-form.xlarge.horizontal.top.white.z-bordered > ul > li.z-active > a {padding-top: 17px;} +#jsn-form.xxlarge.horizontal.top.white.z-bordered > ul > li.z-active > a {padding-top: 20px;} + + +/*horizontal bottom size white theme with border*/ +#jsn-form.horizontal.bottom.white.z-bordered > ul > li.z-active > a {border-bottom: 3px solid #D13636;margin-top: 0;margin-bottom: 0;} + +#jsn-form.mini.horizontal.bottom.white.z-bordered > ul > li.z-active > a {padding-bottom: 5px;} +#jsn-form.small.horizontal.bottom.white.z-bordered > ul > li.z-active > a {padding-bottom: 8px;} +#jsn-form.medium.horizontal.bottom.white.z-bordered > ul > li.z-active > a {padding-bottom: 11px;} +#jsn-form.large.horizontal.bottom.white.z-bordered > ul > li.z-active > a {padding-bottom: 14px;} +#jsn-form.xlarge.horizontal.bottom.white.z-bordered > ul > li.z-active > a {padding-bottom: 17px;} +#jsn-form.xxlarge.horizontal.bottom.white.z-bordered > ul > li.z-active > a {padding-bottom: 20px;} + +/*white bordered mobile*/ +#jsn-form.white.mobile.z-bordered > ul > li.z-active > a{border-bottom: 3px solid #D13636 !important;} + +/*#endregion*/ + + + + + /*#region ========================================================================== + AJAX Support +========================================================================== */ + +.z-tabs-loading {position: relative;width: 100%;min-height: 120px;} +.z-tabs-loading ul, .z-tabs-loading div {display: none;} + + +#jsn-form .z-container { + position: relative; +} + +#jsn-form span.z-spinner, .z-tabs-loading .z-spinner { + position: absolute; + top: 50%; + left: 50%; + z-index: 1000; + text-indent: -999em; + width: 55px; + height: 55px; + margin: -28px 0 0 -50px; + padding: 24px; + background: rgb(255, 255, 255) url("../img/loading-image.gif") no-repeat 50% 50%; +} + +#jsn-form.z-rounded span.z-spinner { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + + /*#endregion*/ + + + + /*#region ========================================================================== + Video Support, Youtube, Vimeo, Iframe +========================================================================== */ + +#jsn-form .z-video { + position: relative; + padding-bottom: 46.25%; + padding-bottom: 56.25%; /* 16:9 */ + padding-top: 30px; + height: 0; + overflow: hidden; +} + +#jsn-form .z-video.z-wide-screen { + padding-bottom: 56.25%; /* hard-coded 16:9 aspect ratio */ +} + +#jsn-form .z-video.z-four-by-three { + padding-bottom: 75%; /* hard-coded 4:3 aspect ratio */ +} + +#jsn-form .z-video.z-top-padding { + padding-top: 30px; +} + + + +#jsn-form .z-video iframe, +#jsn-form .z-video object, +#jsn-form .z-video embed { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; + z-index: 50; +} + + /*#endregion*/ + + + + + /*#region ========================================================================== + Icons Support +========================================================================== */ + /* Font Awesome */ + #jsn-form > ul > li > a i { + font-size: 1.125em; + display: inline; + width: auto; + height: auto; + line-height: normal; + width: 24px; + display: inline-block; + margin-top: 0.015em; + } + + #jsn-form > ul.z-tabs-mobile > li > a i { + display: none; + } + + + /*icons on top*/ + #jsn-form.z-icons-large > ul > li > a i { + font-size: 2.25em; + display: block; + margin: 0 auto; + padding-bottom: 0.65em; + text-align: center; + line-height: 0; + margin-top: 0.65em; + } + + #jsn-form.mini > ul > li > a i, + #jsn-form.small > ul > li > a i { + font-size: 1.25em; + } + + #jsn-form.z-icons-large > ul > li > a { + text-align: center; + } + + #jsn-form > ul > li > a > span.z-icon, + #jsn-form.z-multiline > ul.z-tabs-nav.z-tabs-desktop > li > a > span.z-icon, + #jsn-form.z-multiline > ul.z-tabs-nav.z-tabs-mobile > li > a > span > span.z-icon { + width: 20px; + display: inline-block; + font-size: inherit; + font-weight: normal; + text-transform: initial; + text-align: left; + } + + + #jsn-form.vertical > ul.z-tabs-nav > li > a > span.z-icon, + #jsn-form.z-multiline.vertical > ul.z-tabs-nav.z-tabs-desktop > li > a > span.z-icon, + #jsn-form.z-multiline.vertical > ul.z-tabs-nav.z-tabs-mobile > li > a > span > span.z-icon { + width: 24px; + } + + + +/*#endregion*/ + + + + + /*#region ========================================================================== + Helper classes +========================================================================== */ + + /*align tabs titles center*/ + #jsn-form.center > ul > li > a, + #jsn-form.center.mobile > ul > li > a { + text-align: center !important; + } + + /*align tabs titles right*/ + #jsn-form.right > ul > li > a, + #jsn-form.right.mobile > ul > li > a { + text-align: right !important; + } + + /*align tabs titles left*/ + #jsn-form.left > ul > li > a, + #jsn-form.left.mobile > ul > li > a { + text-align: left !important; + } + + /*z-nopadding on content*/ + #jsn-form.vertical > .z-container > .z-content.z-nopadding > .z-content-inner, + #jsn-form.horizontal > .z-container > .z-content.z-nopadding > .z-content-inner, + #jsn-form > .z-container > .z-content.z-nopadding > .z-content-inner { + padding: 0 !important; + } + + +/*Clear the float on any element*/ +.clearfix { + *zoom: 1; +} + + .clearfix:before, + .clearfix:after { + display: table; + content: ""; + line-height: 0; + } + + .clearfix:after { + clear: both; + } + + +/*#endregion*/ + +/************************************************************************** +* Zozo Tabs: Horizontal +* +* 1. Horizontal Structure +* 2. Horizontal Positioning +* 3. Horizontal Rounded Cornors + 4. Horizontal Shadows +* +* Most of the time you shouldn't delete/edit section 1 (structure). +* - You can delete/edit part of positioning +* - You can delete/edit rounded and shadows section if you need. +* +**************************************************************************/ + + +/*#region ========================================================================== + Horizontal Structure +========================================================================== */ + +#jsn-form.horizontal > ul > li +{ + float: left; +} + + #jsn-form.horizontal > ul > li.z-active + { + background: none; + z-index: 1; + } + + #jsn-form.horizontal > ul > li > a + { + margin-right: -1px; + /*font-size: 12px; + padding: 13px 24px;*/ + min-height: 1px; + } + + + #jsn-form.top-compact > ul > li > a, + #jsn-form.bottom-compact > ul > li > a +{ + padding-left: 0; + padding-right: 0; +} + +/*top*/ +#jsn-form.horizontal.top > ul > li.z-active +{ + top: 2px; + margin-top: -2px; + padding-bottom: 2px; +} + +#jsn-form.horizontal.top > ul > li > a +{ + top: 1px; + border-width: 1px 1px 0 1px; +} + +#jsn-form.horizontal > ul > li.z-last > a, +#jsn-form.horizontal > ul > li.z-last-col > a +{ + margin-right: 0 !important; +} + +#jsn-form.horizontal > .z-container +{ + clear: both; + zoom: 1; +} + + +/*#endregion*/ + + + + +/*#region ========================================================================== + Horizontal Positioning +========================================================================== */ + +/*top-left is the defalt structure above in region*/ + +/* top-center */ +#jsn-form.horizontal.top-center > ul.z-tabs-desktop +{ + clear: left; + float: left; + left: 50%; + text-align: center; +} + + #jsn-form.horizontal.top-center > ul > li + { + right: 50%; + } + +/* top-right */ +#jsn-form.horizontal.top-right > ul +{ + float: right; + margin: 0 -1px 0 0; +} + + #jsn-form.horizontal.top-right > ul > li.z-last + { + margin-right: 1px; + } + +.ie7 body #jsn-form.horizontal.top-right > ul > li.z-last +{ + margin-right: -1px; +} + +.ie7 body #jsn-form.horizontal > .z-container +{ + clear: none; + width: 100%; +} + +/* bottom-left*/ + +/*bottom*/ +#jsn-form.horizontal.bottom > ul > li.z-active +{ + top: -1px; + padding-top: 1px; + z-index: 9; +} + +#jsn-form.horizontal.bottom > .z-container +{ +z-index: 7; +} + +#jsn-form.horizontal.bottom > ul > li > a +{ + top: -1px; + border-width: 0 1px 1px 1px; +} + +/* bottom-center*/ +#jsn-form.horizontal.bottom-center > ul +{ + float: left; + left: 50%; + text-align: center; +} + + #jsn-form.horizontal.bottom-center > ul > li + { + right: 50%; + } + +/* bottom-right*/ +#jsn-form.horizontal.bottom-right > ul +{ + float: right; +} + +/* top compact*/ +.ie7 #jsn-form.horizontal.top-compact > ul.z-tabs-desktop > li.z-last +{ + margin-right: 0; +} + + +/* bottom compact*/ +.ie7 #jsn-form.horizontal.bottom-compact > ul.z-tabs-desktop > li.z-last +{ + margin-right: 0; +} + +/**/ +#jsn-form.horizontal.responsive > ul > li > a, +#jsn-form.horizontal.top-compact > ul > li > a, +#jsn-form.horizontal.bottom-compact > ul > li > a, +#jsn-form.horizontal.top-center > ul > li > a, +#jsn-form.horizontal.bottom-center > ul > li > a +{ + text-align: center; +} + + +/*#endregion*/ + + + + +/*#region ========================================================================== + Horizontal Rounded Cornors +========================================================================== */ + +/*top*/ +#jsn-form.horizontal.top.z-rounded > ul > li.z-first, +#jsn-form.horizontal.top.z-rounded > ul > li.z-first > a +{ + -webkit-border-radius: 5px 0 0 0; + -moz-border-radius: 5px 0 0 0; + border-radius: 5px 0 0 0; +} + +#jsn-form.horizontal.top.z-rounded > ul > li.z-last, +#jsn-form.horizontal.top.z-rounded > ul > li.z-last > a +{ + -webkit-border-radius: 0 5px 0 0; + -moz-border-radius: 0 5px 0 0; + border-radius: 0 5px 0 0; +} + +/*top-left*/ +#jsn-form.horizontal.top-left.z-rounded > .z-container +{ + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} + +/*top-center*/ +#jsn-form.horizontal.top-center.z-rounded > .z-container +{ + -webkit-border-radius: 6px 6px 6px 6px; + -moz-border-radius: 6px 6px 6px 6px; + border-radius: 6px 6px 6px 6px; +} + +/*top-right*/ +#jsn-form.horizontal.top-right.z-rounded > .z-container +{ + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +/* top compact*/ +#jsn-form.horizontal.z-rounded.top-compact > .z-container +{ + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + -khtml-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +/* bottom*/ +#jsn-form.horizontal.z-rounded.bottom > ul > li.z-first, +#jsn-form.horizontal.z-rounded.bottom > ul > li.z-first > a +{ + -webkit-border-radius: 0 0 0 5px; + -moz-border-radius: 0 0 0 5px; + border-radius: 0 0 0 5px; +} + +#jsn-form.horizontal.z-rounded.bottom > ul > li.z-last, +#jsn-form.horizontal.z-rounded.bottom > ul > li.z-last > a +{ + -webkit-border-radius: 0 0 5px 0; + -moz-border-radius: 0 0 5px 0; + border-radius: 0 0 5px 0; +} + +/* bottom-left*/ +#jsn-form.horizontal.z-rounded.bottom-left > .z-container +{ + -webkit-border-radius: 6px 6px 6px 0; + -moz-border-radius: 6px 6px 6px 0; + border-radius: 6px 6px 6px 0; +} + +/* bottom-center*/ +#jsn-form.horizontal.z-rounded.bottom-center > .z-container +{ + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; +} + +/* bottom-right*/ +#jsn-form.horizontal.z-rounded.bottom-right .z-container +{ + -webkit-border-radius: 6px 6px 0 6px; + -moz-border-radius: 6px 6px 0 6px; + -khtml-border-radius: 6px 6px 0 6px; + border-radius: 6px 6px 0 6px; +} + +/* bottom compact*/ +#jsn-form.horizontal.z-rounded.bottom-compact > .z-container +{ + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + -khtml-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} + +/*responsive*/ +#jsn-form.horizontal.responsive.top.z-rounded > .z-container +{ + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +#jsn-form.horizontal.responsive.bottom.z-rounded > .z-container +{ + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} + +/*responsive mobile dropdown menu*/ +#jsn-form.horizontal.responsive.top.z-rounded > .z-tabs-mobile, +#jsn-form.horizontal.responsive.top.z-rounded > .z-tabs-mobile > li +{ + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} + +#jsn-form.horizontal.responsive.bottom.z-rounded > .z-tabs-mobile, +#jsn-form.horizontal.responsive.bottom.z-rounded > .z-tabs-mobile > li +{ + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} +/*#endregion*/ + + + + +/*#region ========================================================================== + Horizontal Shadows +========================================================================== */ +#jsn-form.horizontal.z-shadows > .z-container +{ + -moz-box-shadow: 0px 0px 3px rgba(0, 0, 0, .125); + -webkit-box-shadow: 0px 0px 3px rgba(0, 0, 0, .125); + box-shadow: 0px 0px 3px rgba(0, 0, 0, .125); +} + +#jsn-form.horizontal.z-shadows > ul > li > a{box-shadow: -2px 0px 2px -2px rgba(0, 0, 0, .1);} +/* +#jsn-form.top.z-shadows > ul > li.z-first > a, +#jsn-form.bottom.z-shadows > ul > li.z-first > a{box-shadow: -3px 1px 1px -3px rgba(0, 0, 0, .2);} + +#jsn-form.top.z-shadows > ul > li.z-last > a, +#jsn-form.bottom.z-shadows > ul > li.z-last > a{box-shadow: 3px 1px 1px -3px rgba(0, 0, 0, .2);} +*/ + +#jsn-form.horizontal.z-shadows > ul > li.z-first > a{box-shadow: -3px 1px 1px -3px rgba(0, 0, 0, .2);} +#jsn-form.horizontal.z-shadows > ul > li.z-last > a{box-shadow: 3px 1px 1px -3px rgba(0, 0, 0, .2);} + +/*#endregion*/ + + +/*#region ========================================================================== + flat +========================================================================== */ + +/* flat reset*/ +#jsn-form.flat, +#jsn-form.flat > .z-container, +#jsn-form.flat > ul.z-tabs-nav, +#jsn-form.flat.horizontal > ul.z-tabs-nav, +#jsn-form.flat.vertical > ul.z-tabs-nav.z-tabs-desktop, +#jsn-form.flat > ul li.z-first, +#jsn-form.flat > ul.z-tabs-nav > li > a, +#jsn-form.flat.horizontal > ul.z-tabs-nav > li > a, +#jsn-form.flat.horizontal.clean > ul.z-tabs-nav > li > a +{ + border-width: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + -moz-box-shadow: none !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; +} + + + /*flat sizes*/ +#jsn-form.flat.mini > ul > li > a {font-size: 11px;padding: 7px 16px;} +#jsn-form.flat.small > ul > li > a {font-size: 11px;padding: 13px 20px;} +#jsn-form.flat.medium > ul > li > a {font-size: 13px;padding: 16px 24px;} /*font 1+ top 1+ left +4*/ +#jsn-form.flat.large > ul > li > a {font-size: 14px;padding: 19px 28px;} +#jsn-form.flat.xlarge > ul > li > a {font-size: 14px;padding: 22px 32px;} +#jsn-form.flat.xxlarge > ul > li > a {font-size: 15px;padding: 25px 36px;} + + #jsn-form.flat.top-compact > ul > li > a, + #jsn-form.flat.bottom-compact > ul > li > a { + padding-left: 0; + padding-right: 0; + } + +/*common*/ + +/* JSN-REMOVED */ +/*#jsn-form.flat +{ + -webkit-font-smoothing: subpixel-antialiased; + font-family: "Lato", Helvetica, Arial, sans-serif; + font-weight: normal; + line-height: 1.55em; + + font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; +}*/ + +/* JSN-IMPORTANT JSN-REMOVED #jsn-form.flat,*/ +#jsn-form.flat > ul > li > a { color: #374858;color: #2C3E50 !important;text-shadow: none;} + +#jsn-form.flat > ul > li > a +{/*text-transform: uppercase;*/ + /*font-weight: 600;*/ + /* JSN-REMOVED font-family: "Lato", Helvetica, Arial, sans-serif; */ + /*line-height: 1.55em;*/ + + font-family: 'Open Sans', Helvetica, Arial, sans-serif; +} + +#jsn-form.flat .z-container +{ + -webkit-border-radius: 0 !important; + -moz-border-radius: 0 !important; + border-radius: 0 !important; +} + +#jsn-form.flat > ul > li > a, +#jsn-form.flat > .z-container, +#jsn-form.flat > .z-container > .z-content { background: none; border-width: 0; } +#jsn-form.flat > ul.z-tabs-nav > li > a:hover { background: #e3eaf0; background: #F6F7F9; text-shadow: none; box-shadow: none; } +/* JSN-MPORTANT */ +#jsn-form.flat > ul.z-tabs-nav > li.z-active > a { background: #bdc3c7; color: #fff !important; text-shadow: none; box-shadow: none; } +/* JSN-ADD */ +#jsn-form.flat > ul.z-tabs-nav > li.z-active > a:hover {color:#2C3E50 !important;} + +/*dark*/ +/* JSN-REMOVED +#jsn-form.flat.z-dark { color: #F1F6F7;color: rgba(248, 251, 252, 0.9);} +#jsn-form.flat.z-dark > ul > li > a { color: #F1F6F7;} +#jsn-form.flat.z-dark > ul.z-tabs-nav > li > a:hover { background: #e3eaf0; background: #152232; text-shadow: none; box-shadow: none; background: #1D3449; } +#jsn-form.flat.z-dark > ul.z-tabs-nav > li.z-active > a { background: #bdc3c7; color: #fff; text-shadow: none; box-shadow: none; } +*/ + + +/*horizontal*/ +#jsn-form.flat.horizontal > .z-container { margin-right: 0 !important; } +#jsn-form.flat.horizontal > .z-container > .z-content > .z-content-inner { padding: 2em 0; } + +#jsn-form.flat.horizontal.top > ul.z-tabs-nav, +#jsn-form.flat.horizontal.top > ul.z-tabs-nav > li, +#jsn-form.flat.horizontal.bottom > ul.z-tabs-nav, +#jsn-form.flat.horizontal.bottom > ul.z-tabs-nav > li { margin: 0; padding: 0; } +#jsn-form.flat.horizontal > ul > li.z-active { top: 0; margin-top: 0; padding-bottom: 0; } +#jsn-form.flat.horizontal.top > ul.z-tabs-nav > li.z-active { margin-bottom: 0; padding-bottom: 0; } + + + +/*vertical*/ +#jsn-form.flat.vertical > .z-container > .z-content > .z-content-inner { padding: 0 2em; } +#jsn-form.flat.vertical.contained > .z-container > .z-content > .z-content-inner { padding: 2em; } +#jsn-form.flat.vertical > ul.z-tabs-nav { margin-left: 0; margin-right: 0; } +#jsn-form.flat.vertical > .z-container { border-width: 0; margin: 0; } +#jsn-form.flat.vertical > ul > li.z-first.z-active > a { border-width: 0; } +#jsn-form.flat.vertical > ul.z-tabs-nav > li.z-active { z-index: 0; } +#jsn-form.flat.vertical > ul.z-tabs-nav > li > a { margin: 0 0 0 0; text-align: left; } + +/*flat responsive */ +#jsn-form.flat.clean.responsive.horizontal.bottom > ul > li.z-first-row > a, +#jsn-form.flat.clean.responsive.horizontal.top > ul > li.z-last-row > a, +#jsn-form.flat.clean.responsive.horizontal.bottom > ul > li.z-last-row > a { border-width: 0; } +/*#endregion*/ + + +/************************************************************************** +* Zozo Tabs: Flat UI Styles +* +* - contained (normal, spaced, borderd, rounded) +* - clean (normal, spaced, borderd, rounded) +* - pills (normal, spaced, borderd, rounded +* +* Zozo Tabs: Optional +* - spaced +* - bordered +* - rounded +* +* +* Feel free to delete/edit anything +* +**************************************************************************/ + +/*#endregion*/ + + +/*#region ========================================================================== + Contained / clean +========================================================================== */ + +#jsn-form.flat.clean > ul > li.z-active > a { +/* JSN-REMOVE font-weight: inherit;*/ +/* JSN-ADD*/ font-weight: 800; +} + +#jsn-form.flat.z-multiline > ul > li> a, +#jsn-form.flat.z-multiline > ul > li.z-active > a { +font-weight: 600; +} + +/*light*/ + +/* new temp#jsn-form.flat.contained.horizontal > .z-container > .z-content,*/ +#jsn-form.flat.contained.horizontal> .z-container, +#jsn-form.flat.contained.vertical> .z-container {background: #F7F7F8;background: #EFF0F2;} +#jsn-form.flat.contained.horizontal > .z-container > .z-content > .z-content-inner {padding: 2em;} + +#jsn-form.flat.contained > ul > li a, +#jsn-form.flat.clean > ul > li a{background: #F7F7F8;background: #EFF0F2;} + +#jsn-form.flat.contained > ul > li > a:hover, +#jsn-form.flat.clean > ul > li > a:hover{background: #ECEDEE;} + +/*clean*/ +#jsn-form.flat.clean.horizontal > ul.z-tabs-nav > li > a{text-align:center;} +#jsn-form.flat.clean.vertical > ul.z-tabs-nav > li > a{text-align:left;} + + +/*dark*/ +/* JSN-REMOVE +#jsn-form.flat.z-dark.contained > ul.z-tabs-nav > li > a, +#jsn-form.flat.z-dark.clean > ul.z-tabs-nav > li > a{/*color:#fff;text-shadow: none;*//*background: #2C3E50;} +*/ + +/*contained*/ +#jsn-form.flat.contained.z-spaced.horizontal.top > .z-container {top:3px;/*padding: 3px 0 0 0;*/} +#jsn-form.flat.contained.z-spaced.horizontal.bottom > .z-container {margin: 0 0 3px 0;} + + +/*latest*/ +#jsn-form.flat.contained.z-spaced.z-bordered.horizontal.top> .z-container {padding: 0;top:0;} +#jsn-form.flat.contained.z-spaced.z-bordered.horizontal.bottom > .z-container {padding:0;margin:0;} + +/*contained responsive*/ +#jsn-form.flat.responsive.contained.z-spaced.horizontal.top > .z-container {top:2px;/*padding: 2px 0 0 0;*/} +#jsn-form.flat.responsive.contained.z-spaced.horizontal.bottom > .z-container {margin: 0 0 1px 0;} + + +/*#endregion*/ + + + + +/*#region ========================================================================== + Clean +========================================================================== */ + + + + + + +/*#endregion*/ + + + + + +/*#region ========================================================================== + Shadows +========================================================================== */ + + +/* +#jsn-form.flat.contained.horizontal.top > .z-container +{ + box-shadow: rgba(51, 51, 51, 0.0980392) 0px 2px 1px !important; + box-shadow: rgba(51, 51, 51, 0.09) 3px 3px 0px !important; +} +*/ +/*#endregion*/ + + + +/*#region ========================================================================== + Rounded +========================================================================== */ + + + + + +#jsn-form.flat.pills.z-rounded > ul.z-tabs-nav > li > a, +#jsn-form.flat.horizontal.top.responsive.z-rounded > ul.z-tabs-nav > li > a, +#jsn-form.flat.horizontal.top.responsive.z-rounded > ul.z-tabs-nav > li.z-active > a, +#jsn-form.flat.horizontal.bottom.responsive.z-rounded > ul.z-tabs-nav > li > a, +#jsn-form.flat.horizontal.bottom.responsive.z-rounded > ul.z-tabs-nav > li.z-active > a, +#jsn-form.flat.horizontal.bottom.z-rounded > ul.z-tabs-nav > li > a2 +{ + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + + + + + + +#jsn-form.flat.vertical.top-left.z-rounded > ul.z-tabs-nav > li > a, +#jsn-form.flat.vertical.top-right.z-rounded > ul.z-tabs-nav > li > a +{ + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + + + +/*mobile*/ +#jsn-form.flat.mobile.z-rounded > ul.z-tabs-nav > li.z-active, +#jsn-form.flat.mobile.z-rounded > ul.z-tabs-nav > li.z-active:hover, +#jsn-form.flat.mobile.z-rounded > ul.z-tabs-nav > li:hover, +#jsn-form.horizontal.top-left.z-rounded > .z-container +{ + -webkit-border-radius: 0 !important; + -moz-border-radius: 0 !important; + border-radius: 0 !important; +} + + + + + + +#jsn-form.flat.mobile.horizontal.z-rounded > ul.z-tabs-nav > li > a, +#jsn-form.flat.mobile.vertical.z-rounded > ul.z-tabs-mobile.z-state-closed > li > a, +#jsn-form.flat.mobile.horizontal.z-rounded > ul.z-tabs-mobile.z-state-closed > li > a +{ + -webkit-border-radius: 4px !important; + -moz-border-radius: 4px !important; + border-radius: 4px !important; +} + + + +#jsn-form.flat.vertical.top-left.z-rounded.z-bordered > ul.z-tabs-nav > li > a +{ + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +#jsn-form.flat.vertical.top-right.z-rounded.z-bordered > ul.z-tabs-nav > li > a +{ + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + + +/*clean vertical bordered rounded*/ +#jsn-form.flat.clean.vertical.top-left.z-rounded.z-bordered > ul.z-tabs-desktop { +-webkit-border-radius: 6px 0 0 6px; +-moz-border-radius: 6px 0 0 6px; +border-radius: 6px 0 0 6px; +} + +#jsn-form.flat.clean.vertical.top-right.z-rounded.z-bordered > ul.z-tabs-desktop { +-webkit-border-radius: 0 6px 6px 0; +-moz-border-radius: 0 6px 6px 0; +border-radius: 0 6px 6px 0; +} + + +/*#endregion*/ + + + +/*#region ========================================================================== + Bordered +========================================================================== */ + +/*#jsn-form.flat.horizontal.top.z-bordered > .z-container { border-width: .2em 0 0 0; margin: 0 !important;}*/ + + +/*top borderd*/ +#jsn-form.horizontal.top.flat.z-bordered.mini > .z-container {border-width: 3px 0 0 0;} +#jsn-form.horizontal.top.flat.z-bordered.small > .z-container {border-width: 4px 0 0 0;} +#jsn-form.horizontal.top.flat.z-bordered.medium > .z-container {border-width: 5px 0 0 0;} +#jsn-form.horizontal.top.flat.z-bordered.large > .z-container {border-width: 5px 0 0 0;} +#jsn-form.horizontal.top.flat.z-bordered.xlarge > .z-container {border-width: 6px 0 0 0;} +#jsn-form.horizontal.top.flat.z-bordered.xxlarge > .z-container {border-width: 6px 0 0 0;} + +/*bottom borderd*/ +#jsn-form.horizontal.bottom.flat.z-bordered.mini > .z-container {border-width: 0 0 3px 0;} +#jsn-form.horizontal.bottom.flat.z-bordered.small > .z-container {border-width: 0 0 4px 0;} +#jsn-form.horizontal.bottom.flat.z-bordered.medium > .z-container {border-width: 0 0 5px 0;} +#jsn-form.horizontal.bottom.flat.z-bordered.large > .z-container {border-width: 0 0 5px 0;} +#jsn-form.horizontal.bottom.flat.z-bordered.xlarge > .z-container {border-width: 0 0 6px 0;} +#jsn-form.horizontal.bottom.flat.z-bordered.xxlarge > .z-container {border-width: 0 0 6px 0;} + +/*top*/ +#jsn-form.flat.horizontal.top.z-rounded.z-bordered.z-spaced > ul.z-tabs-nav > li > a, +#jsn-form.flat.horizontal.top.z-rounded.z-bordered > ul.z-tabs-nav > li.z-active > a, +#jsn-form.flat.horizontal.top.z-rounded.z-bordered > ul.z-tabs-nav > li:hover > a { -webkit-border-radius: 3px 3px 0 0; -moz-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; } + +#jsn-form.flat.horizontal.bottom.z-rounded.z-bordered > ul.z-tabs-nav > li > a, +#jsn-form.flat.horizontal.bottom.z-rounded.z-bordered > ul.z-tabs-nav > li.z-active > a, +#jsn-form.flat.horizontal.bottom.z-rounded.z-bordered > ul.z-tabs-nav > li:hover > a { -webkit-border-radius: 0 0 3px 3px; -moz-border-radius: 0 0 3px 3px; border-radius: 0 0 3px 3px; } + +/*vertical right*/ +#jsn-form.flat.vertical.z-bordered.top-right.mini > ul.z-tabs-nav {border-width: 0 0 0 3px;} +#jsn-form.flat.vertical.z-bordered.top-right.small > ul.z-tabs-nav {border-width: 0 0 0 4px;} +#jsn-form.flat.vertical.z-bordered.top-right.medium > ul.z-tabs-nav {border-width: 0 0 0 5px;} +#jsn-form.flat.vertical.z-bordered.top-right.large > ul.z-tabs-nav {border-width: 0 0 0 5px;} +#jsn-form.flat.vertical.z-bordered.top-right.xlarge > ul.z-tabs-nav {border-width: 0 0 0 6px;} +#jsn-form.flat.vertical.z-bordered.top-right.xxlarge > ul.z-tabs-nav {border-width: 0 0 0 6px;} + +/*vertical left*/ +#jsn-form.flat.vertical.z-bordered.top-left.mini > ul.z-tabs-nav {border-width: 0 3px 0 0;} +#jsn-form.flat.vertical.z-bordered.top-left.small > ul.z-tabs-nav {border-width: 0 4px 0 0;} +#jsn-form.flat.vertical.z-bordered.top-left.medium > ul.z-tabs-nav {border-width: 0 5px 0 0;} +#jsn-form.flat.vertical.z-bordered.top-left.large > ul.z-tabs-nav {border-width: 0 5px 0 0;} +#jsn-form.flat.vertical.z-bordered.top-left.xlarge > ul.z-tabs-nav {border-width: 0 6px 0 0;} +#jsn-form.flat.vertical.z-bordered.top-left.xxlarge > ul.z-tabs-nav {border-width: 0 6px 0 0;} + +#jsn-form.flat.mobile.vertical.z-bordered > ul.z-tabs-nav +{ + border-width: 0 !important; +} +/*#endregion*/ + + + + +/*#region ========================================================================== + Spaced +========================================================================== */ +/*spacing*/ +#jsn-form.flat.z-spaced.horizontal > ul > li > a, +#jsn-form.flat.z-spaced.z-shadows.z-dark.horizontal > ul > li > a{margin-right:2px;} + + +/*spacing bordered*/ +#jsn-form.flat.z-spaced.z-bordered.horizontal > ul > li > a, +#jsn-form.flat.z-spaced.z-bordered.z-shadows.z-dark.horizontal > ul > li > a{margin-right:3px;} + + +#jsn-form.flat.z-spaced.horizontal > ul.z-tabs-nav > li.z-last > a, +#jsn-form.flat.z-spaced.horizontal.z-multiline > ul.z-tabs-nav > li.z-last > a, +#jsn-form.flat.z-spaced.horizontal.responsive > ul.z-tabs-nav > li.z-last-col > a {margin-right: 0 !important;} +#jsn-form.flat.z-spaced.horizontal.responsive > ul.z-tabs-nav > li > a{margin:1px 1px 0 0 !important;} + + +#jsn-form.flat.z-spaced.vertical > ul.z-tabs-desktop > li > a {margin-bottom: 1px;} +#jsn-form.flat.z-spaced.vertical.top-left > ul.z-tabs-desktop {margin:0 1px 0 0;} +#jsn-form.flat.z-spaced.vertical.top-right > ul.z-tabs-desktop {margin: 0 0 0 1px} +#jsn-form.flat.z-spaced.vertical.top-left > ul.z-tabs-desktop > li.z-last > a, +#jsn-form.flat.z-spaced.vertical.top-right > ul.z-tabs-desktop > li.z-last > a {margin-bottom: 0;} + +#jsn-form.flat.z-spaced.contained.horizontal.top.z-rounded > ul > li > a {border-radius: 4px 4px 0 0;} +#jsn-form.flat.z-spaced.contained.horizontal.bottom.z-rounded > ul > li > a {border-radius: 0 0 4px 4px;} +#jsn-form.flat.z-dark.contained.z-shadows.z-spaced.horizontal.top > ul > li > a {box-shadow: none !important;} + +/*#endregion*/ + + + +/*dark*/ +/* JSN-REMOVE +#jsn-form.flat.z-dark.contained.horizontal > .z-container, +#jsn-form.flat.z-dark.contained.vertical > .z-container { background: #2C3E50; } + +/************************************************************************** +* Zozo Tabs: Mobile +* +* 1. Horizontal Structure +* 2. Horizontal Positioning +* 3. Horizontal Rounded Cornors + 4. Horizontal Shadows +* +* Most of the time you shouldn't delete/edit section 1 (structure). +* - You can delete/edit part of positioning +* - You can delete/edit rounded and shadows section if you need. +* +**************************************************************************/ + +/*#region ========================================================================== + Zozo Tabs Mobile Menu +========================================================================== */ + + +/*reset*/ +#jsn-form.mobile > ul.z-tabs-nav, +#jsn-form.mobile > ul.z-tabs-nav > li, +#jsn-form.mobile > ul.z-tabs-nav > li.z-active, +#jsn-form.mobile > .z-container, +#jsn-form.mobile > .z-container > .z-content { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + text-shadow: none; +} + +#jsn-form.mobile { + position: relative; +} + + /*horizontal */ + #jsn-form.mobile > ul.z-tabs-nav, + #jsn-form.mobile > ul.z-tabs-nav.z-tabs-mobile, + #jsn-form.mobile > ul.z-tabs-nav.z-tabs-mobile > li, + #jsn-form.mobile > .z-container { + width: 100%; + float: none; + display: block; + width: 100%; + } + + + #jsn-form.mobile > ul.z-tabs-nav { + border-width: 1px 1px 1px 1px; + } + + #jsn-form.mobile > ul.z-tabs-nav > li > .z-link { + margin: 0 !important; + } + + #jsn-form.mobile > ul.z-tabs-desktop { + /* comment position and top to change to relative positioning */ + position: absolute; + top: inherit; + margin-top: 8px; + left: 0; + z-index: 1000; + width: 100%; + box-shadow: 0 2px 1px rgba(51, 51, 51, 0.1); + } + + #jsn-form.mobile > ul > li { + overflow: visible; + } + + #jsn-form.mobile > ul.z-tabs-nav > li > a { + top: 0; + } + + #jsn-form.mobile > ul > li.z-active > a { + font-weight: bold; + } + + #jsn-form.mobile.top > ul.z-tabs-desktop > li > a, + #jsn-form.mobile.bottom > ul.z-tabs-desktop > li > a { + border-width: 1px 0px 0 0px; + } + + #jsn-form.mobile > ul.z-tabs-nav > li.z-first > a { + border-width: 0; + } + /* +#jsn-form.mobile.horizontal.z-spaced > ul.z-tabs-nav > li > a +{ + margin-right: 0; +}*/ + + #jsn-form.mobile.z-shadows > ul.z-tabs-mobile { + -webkit-box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.9) inset; + -moz-box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.9) inset; + box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.9) inset; + } + + #jsn-form.mobile > ul.z-tabs-desktop > li { + float: none; + display: block; + } + + #jsn-form.mobile > ul.z-tabs-desktop.z-hide-menu { + opacity: 0; + height: 0; + visibility: hidden; + } + + #jsn-form.mobile.top > .z-container { + margin-top: 8px; + } + + #jsn-form.mobile.bottom > .z-container { + margin-bottom: 8px; + } + + #jsn-form.mobile > .z-container, + #jsn-form.mobile > .z-container > .z-content.z-active { + overflow: visible; + } + + #jsn-form.mobile > .z-container.z-animating, + #jsn-form.mobile > .z-container.z-animating > .z-content.z-active { + overflow: hidden; + } + + /*arrow mobile icons +#jsn-form.mobile > ul.z-tabs-mobile +{ + +} +#jsn-form.mobile > ul.z-tabs-mobile > li > a > span.z-title +{ + margin-left: 6px; + opacity: 1; +}*/ + + #jsn-form.mobile > ul.z-tabs-mobile.z-state-closed > li > a > span.z-arrow { + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + transform: rotate(0deg); + opacity: 1; + } + + + #jsn-form.mobile > ul.z-tabs-mobile > li > a > span.z-arrow { + position: absolute; + top: 50%; + background: url(../img/z-tabs-icons.png) no-repeat top left; + background-position: -1470px -3px; + width: 30px; + height: 30px; + margin-top: -25px; + margin-left: -0.75em; + display: inline-block; + right: 1.125em; + /*background-position: -1470px -60px;*/ + } + +#jsn-form.z-icons-dark > ul.z-tabs-mobile > li > a > span.z-arrow { + background-position: -1470px -3px; +} + +/*version 6.0 +#jsn-form.mobile > ul.z-tabs-mobile > li > a +{ + border-width: 0; +} +*/ + +/*mobile horizontal style*/ +#jsn-form.mobile > ul.z-tabs-nav > li.z-active { + margin: 0; + padding: 0; + top: 0; + bottom: 0; +} + + #jsn-form.mobile > ul.z-tabs-nav > li.z-active > a { + margin: 0; + top: 0; + bottom: 0; + width: auto; + } + +#jsn-form.mobile > ul.z-tabs-nav > li { + border-width: 0px; +} + + #jsn-form.mobile > ul.z-tabs-nav > li > a { + text-align: left; + } + +#jsn-form.mobile > ul.z-tabs-desktop > li.z-last { + border-bottom-width: 0; +} + + + +/*#endregion*/ + + + + + +/*#region ========================================================================== + Rounded +========================================================================== */ + +#jsn-form.mobile.z-rounded > ul.z-tabs-mobile.z-state-closed > li > a { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -khtml-border-radius: 5px; + border-radius: 5px; +} + +/*open rounded*/ +#jsn-form.mobile.z-rounded > ul.z-tabs-mobile, +#jsn-form.mobile.z-rounded > ul.z-tabs-desktop { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + + #jsn-form.mobile.z-rounded > ul.z-tabs-mobile > li > a { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + } + +#jsn-form.mobile.z-rounded > ul.z-tabs-nav.z-tabs-desktop > li.z-last > a.z-link { + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; +} + +#jsn-form.mobile.z-rounded > ul.z-tabs-nav > li.z-first > a { + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} + + +#jsn-form.mobile.z-rounded > .z-container { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -khtml-border-radius: 6px; + border-radius: 6px; +} + +/*#endregion*/ + + + + + +/*#region ========================================================================== + Mobile Fixes +========================================================================== */ +/* Prevent any object from being highlighted upon touch event*/ +#jsn-form #jsn-form *, +#jsn-form ul, +#jsn-form ul li, +#jsn-form ul li a, +#jsn-form .z-container .z-content { + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-touch-callout: none; + outline: none; +} + +/*#endregion*/ + +#member-registration > fieldset,#member-profile > fieldset,.jsn-p-fields > fieldset{display:none;} +#jsn-form.flat > ul > li > a.jsninvalidfieldgroup, #jsn-form.flat > ul > li.z-active > a.jsninvalidfieldgroup{font-weight:bold !important;color:#9D261D !important;} + + + + + + diff --git a/deployed/jsn/components/com_jsn/assets/css/tabs.min.css b/deployed/jsn/components/com_jsn/assets/css/tabs.min.css new file mode 100644 index 00000000..087e51fe --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/css/tabs.min.css @@ -0,0 +1 @@ +@import "https://fonts.googleapis.com/css?family=Open+Sans:300,400,800";article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}#jsn-form,#jsn-form > ul,#jsn-form > ul > li,#jsn-form > ul > li > a,#jsn-form > .z-container,#jsn-form > .z-container > .z-content,#jsn-form > .z-container > .z-content > .z-content-inner{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}#jsn-form,.z-tabs:before,.z-tabs:after{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}#jsn-form,#jsn-form > ul,#jsn-form > ul > li,#jsn-form > ul > li > a{position:relative;margin:0;padding:0;border:0;outline:0;display:block;outline:0 none;text-decoration:none;list-style:none;list-style-type:none}#jsn-form > .z-container > .z-content::after,#jsn-form > .z-container > .z-content > .z-content-inner::after{content:".";display:block;height:0;clear:both;visibility:hidden}#jsn-form > .z-container > .z-content,#jsn-form > .z-container > .z-content > .z-content-inner{zoom:1}#jsn-form{clear:both}#jsn-form > ul > li > a{color:#111;line-height:18px;font-weight:inherit;font-size:12px;padding:13px 24px;background:#fff;cursor:pointer}#jsn-form > ul > li.z-active > a{cursor:default}#jsn-form > ul,#jsn-form > ul > li > a,#jsn-form > .z-container{border-color:#CECECE;border-style:solid}#jsn-form > .z-container{padding:0;margin:0;border-width:1px;background:#fff;position:relative;overflow:hidden}#jsn-form > .z-container > .z-content{position:absolute;width:100%;height:100%;overflow:hidden;padding:0;z-index:7;display:none}#jsn-form > .z-container > .z-content.z-active{z-index:8}#jsn-form > .z-container > .z-content > .z-content-inner{padding:18px 0px;height:auto}#jsn-form.mini > ul > li > a{font-size:11px;padding:7px 16px}#jsn-form.small > ul > li > a{font-size:11px;padding:10px 16px}#jsn-form.medium > ul > li > a{font-size:12px;padding:15px 20px}#jsn-form.large > ul > li > a{font-size:13px;padding:16px 24px}#jsn-form.xlarge > ul > li > a{font-size:14px;padding:19px 28px}#jsn-form.xxlarge > ul > li > a{font-size:15px;padding:22px 32px}#jsn-form.mini.vertical > ul > li > a{padding:7px 13px}#jsn-form.small.vertical > ul > li > a{padding:10px 16px}#jsn-form.medium.vertical > ul > li > a{padding:13px 19px}#jsn-form.large.vertical > ul > li > a{padding:16px 22px}#jsn-form.xlarge.vertical > ul > li > a{padding:19px 25px}#jsn-form.xxlarge.vertical > ul > li > a{padding:22px 28px}#jsn-form.white.z-bordered > ul > li.z-active > a{color:#D13636}#jsn-form.vertical.top-right.white.z-bordered > ul > li.z-active > a{border-right:3px solid #D13636}#jsn-form.vertical.top-left.white.z-bordered > ul > li.z-active > a{border-left:3px solid #D13636}#jsn-form.mini.vertical.top-right.white.z-bordered > ul > li.z-active > a{border-right:1px solid #D13636}#jsn-form.mini.vertical.top-left.white.z-bordered > ul > li.z-active > a{border-left:1px solid #D13636}#jsn-form.small.vertical.top-right.white.z-bordered > ul > li.z-active > a{border-right:2px solid #D13636}#jsn-form.small.vertical.top-left.white.z-bordered > ul > li.z-active > a{border-left:2px solid #D13636}#jsn-form.mini.vertical.top-left.white.z-bordered > ul > li.z-active > a{padding-left:10px}#jsn-form.small.vertical.top-left.white.z-bordered > ul > li.z-active > a{padding-left:13px}#jsn-form.medium.vertical.top-left.white.z-bordered > ul > li.z-active > a{padding-left:16px}#jsn-form.large.vertical.top-left.white.z-bordered > ul > li.z-active > a{padding-left:19px}#jsn-form.xlarge.vertical.top-left.white.z-bordered > ul > li.z-active > a{padding-left:22px}#jsn-form.xxlarge.vertical.top-left.white.z-bordered > ul > li.z-active > a{padding-left:25px}#jsn-form.horizontal.top.white.z-bordered > ul > li.z-active > a{border-top:3px solid #F44343;margin-top:0;margin-bottom:0}#jsn-form.mini.horizontal.top.white.z-bordered > ul > li.z-active > a{padding-top:7px;border-top-width:1px}#jsn-form.small.horizontal.top.white.z-bordered > ul > li.z-active > a{padding-top:9px;border-top-width:2px}#jsn-form.medium.horizontal.top.white.z-bordered > ul > li.z-active > a{padding-top:13px}#jsn-form.large.horizontal.top.white.z-bordered > ul > li.z-active > a{padding-top:14px}#jsn-form.xlarge.horizontal.top.white.z-bordered > ul > li.z-active > a{padding-top:17px}#jsn-form.xxlarge.horizontal.top.white.z-bordered > ul > li.z-active > a{padding-top:20px}#jsn-form.horizontal.bottom.white.z-bordered > ul > li.z-active > a{border-bottom:3px solid #D13636;margin-top:0;margin-bottom:0}#jsn-form.mini.horizontal.bottom.white.z-bordered > ul > li.z-active > a{padding-bottom:5px}#jsn-form.small.horizontal.bottom.white.z-bordered > ul > li.z-active > a{padding-bottom:8px}#jsn-form.medium.horizontal.bottom.white.z-bordered > ul > li.z-active > a{padding-bottom:11px}#jsn-form.large.horizontal.bottom.white.z-bordered > ul > li.z-active > a{padding-bottom:14px}#jsn-form.xlarge.horizontal.bottom.white.z-bordered > ul > li.z-active > a{padding-bottom:17px}#jsn-form.xxlarge.horizontal.bottom.white.z-bordered > ul > li.z-active > a{padding-bottom:20px}#jsn-form.white.mobile.z-bordered > ul > li.z-active > a{border-bottom:3px solid #D13636!important}.z-tabs-loading{position:relative;width:100%;min-height:120px}.z-tabs-loading ul,.z-tabs-loading div{display:none}#jsn-form .z-container{position:relative}#jsn-form span.z-spinner,.z-tabs-loading .z-spinner{position:absolute;top:50%;left:50%;z-index:1000;text-indent:-999em;width:55px;height:55px;margin:-28px 0 0 -50px;padding:24px;background:#fff url(../img/loading-image.gif) no-repeat 50% 50%}#jsn-form.z-rounded span.z-spinner{-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}#jsn-form .z-video{position:relative;padding-bottom:46.25%;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden}#jsn-form .z-video.z-wide-screen{padding-bottom:56.25%}#jsn-form .z-video.z-four-by-three{padding-bottom:75%}#jsn-form .z-video.z-top-padding{padding-top:30px}#jsn-form .z-video iframe,#jsn-form .z-video object,#jsn-form .z-video embed{position:absolute;top:0;left:0;width:100%;height:100%;border:none;z-index:50}#jsn-form > ul > li > a i{font-size:1.125em;display:inline;width:auto;height:auto;line-height:normal;width:24px;display:inline-block;margin-top:.015em}#jsn-form > ul.z-tabs-mobile > li > a i{display:none}#jsn-form.z-icons-large > ul > li > a i{font-size:2.25em;display:block;margin:0 auto;padding-bottom:.65em;text-align:center;line-height:0;margin-top:.65em}#jsn-form.mini > ul > li > a i,#jsn-form.small > ul > li > a i{font-size:1.25em}#jsn-form.z-icons-large > ul > li > a{text-align:center}#jsn-form > ul > li > a > span.z-icon,#jsn-form.z-multiline > ul.z-tabs-nav.z-tabs-desktop > li > a > span.z-icon,#jsn-form.z-multiline > ul.z-tabs-nav.z-tabs-mobile > li > a > span > span.z-icon{width:20px;display:inline-block;font-size:inherit;font-weight:400;text-transform:initial;text-align:left}#jsn-form.vertical > ul.z-tabs-nav > li > a > span.z-icon,#jsn-form.z-multiline.vertical > ul.z-tabs-nav.z-tabs-desktop > li > a > span.z-icon,#jsn-form.z-multiline.vertical > ul.z-tabs-nav.z-tabs-mobile > li > a > span > span.z-icon{width:24px}#jsn-form.center > ul > li > a,#jsn-form.center.mobile > ul > li > a{text-align:center!important}#jsn-form.right > ul > li > a,#jsn-form.right.mobile > ul > li > a{text-align:right!important}#jsn-form.left > ul > li > a,#jsn-form.left.mobile > ul > li > a{text-align:left!important}#jsn-form.vertical > .z-container > .z-content.z-nopadding > .z-content-inner,#jsn-form.horizontal > .z-container > .z-content.z-nopadding > .z-content-inner,#jsn-form > .z-container > .z-content.z-nopadding > .z-content-inner{padding:0!important}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0}.clearfix:after{clear:both}#jsn-form.horizontal > ul > li{float:left}#jsn-form.horizontal > ul > li.z-active{background:none;z-index:1}#jsn-form.horizontal > ul > li > a{margin-right:-1px;min-height:1px}#jsn-form.top-compact > ul > li > a,#jsn-form.bottom-compact > ul > li > a{padding-left:0;padding-right:0}#jsn-form.horizontal.top > ul > li.z-active{top:2px;margin-top:-2px;padding-bottom:2px}#jsn-form.horizontal.top > ul > li > a{top:1px;border-width:1px 1px 0}#jsn-form.horizontal > ul > li.z-last > a,#jsn-form.horizontal > ul > li.z-last-col > a{margin-right:0!important}#jsn-form.horizontal > .z-container{clear:both;zoom:1}#jsn-form.horizontal.top-center > ul.z-tabs-desktop{clear:left;float:left;left:50%;text-align:center}#jsn-form.horizontal.top-center > ul > li{right:50%}#jsn-form.horizontal.top-right > ul{float:right;margin:0 -1px 0 0}#jsn-form.horizontal.top-right > ul > li.z-last{margin-right:1px}.ie7 body #jsn-form.horizontal.top-right > ul > li.z-last{margin-right:-1px}.ie7 body #jsn-form.horizontal > .z-container{clear:none;width:100%}#jsn-form.horizontal.bottom > ul > li.z-active{top:-1px;padding-top:1px;z-index:9}#jsn-form.horizontal.bottom > .z-container{z-index:7}#jsn-form.horizontal.bottom > ul > li > a{top:-1px;border-width:0 1px 1px}#jsn-form.horizontal.bottom-center > ul{float:left;left:50%;text-align:center}#jsn-form.horizontal.bottom-center > ul > li{right:50%}#jsn-form.horizontal.bottom-right > ul{float:right}.ie7 #jsn-form.horizontal.top-compact > ul.z-tabs-desktop > li.z-last{margin-right:0}.ie7 #jsn-form.horizontal.bottom-compact > ul.z-tabs-desktop > li.z-last{margin-right:0}#jsn-form.horizontal.responsive > ul > li > a,#jsn-form.horizontal.top-compact > ul > li > a,#jsn-form.horizontal.bottom-compact > ul > li > a,#jsn-form.horizontal.top-center > ul > li > a,#jsn-form.horizontal.bottom-center > ul > li > a{text-align:center}#jsn-form.horizontal.top.z-rounded > ul > li.z-first,#jsn-form.horizontal.top.z-rounded > ul > li.z-first > a{-webkit-border-radius:5px 0 0 0;-moz-border-radius:5px 0 0;border-radius:5px 0 0 0}#jsn-form.horizontal.top.z-rounded > ul > li.z-last,#jsn-form.horizontal.top.z-rounded > ul > li.z-last > a{-webkit-border-radius:0 5px 0 0;-moz-border-radius:0 5px 0 0;border-radius:0 5px 0 0}#jsn-form.horizontal.top-left.z-rounded > .z-container{-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px;border-radius:0 6px 6px 6px}#jsn-form.horizontal.top-center.z-rounded > .z-container{-webkit-border-radius:6px 6px 6px 6px;-moz-border-radius:6px;border-radius:6px 6px 6px 6px}#jsn-form.horizontal.top-right.z-rounded > .z-container{-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}#jsn-form.horizontal.z-rounded.top-compact > .z-container{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;-khtml-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}#jsn-form.horizontal.z-rounded.bottom > ul > li.z-first,#jsn-form.horizontal.z-rounded.bottom > ul > li.z-first > a{-webkit-border-radius:0 0 0 5px;-moz-border-radius:0 0 0 5px;border-radius:0 0 0 5px}#jsn-form.horizontal.z-rounded.bottom > ul > li.z-last,#jsn-form.horizontal.z-rounded.bottom > ul > li.z-last > a{-webkit-border-radius:0 0 5px 0;-moz-border-radius:0 0 5px;border-radius:0 0 5px 0}#jsn-form.horizontal.z-rounded.bottom-left > .z-container{-webkit-border-radius:6px 6px 6px 0;-moz-border-radius:6px 6px 6px 0;border-radius:6px 6px 6px 0}#jsn-form.horizontal.z-rounded.bottom-center > .z-container{-moz-border-radius:6px;-webkit-border-radius:6px;border-radius:6px}#jsn-form.horizontal.z-rounded.bottom-right .z-container{-webkit-border-radius:6px 6px 0 6px;-moz-border-radius:6px 6px 0;-khtml-border-radius:6px 6px 0 6px;border-radius:6px 6px 0 6px}#jsn-form.horizontal.z-rounded.bottom-compact > .z-container{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;-khtml-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}#jsn-form.horizontal.responsive.top.z-rounded > .z-container{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}#jsn-form.horizontal.responsive.bottom.z-rounded > .z-container{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}#jsn-form.horizontal.responsive.top.z-rounded > .z-tabs-mobile,#jsn-form.horizontal.responsive.top.z-rounded > .z-tabs-mobile > li{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}#jsn-form.horizontal.responsive.bottom.z-rounded > .z-tabs-mobile,#jsn-form.horizontal.responsive.bottom.z-rounded > .z-tabs-mobile > li{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}#jsn-form.horizontal.z-shadows > .z-container{-moz-box-shadow:0 0 3px rgba(0,0,0,.125);-webkit-box-shadow:0 0 3px rgba(0,0,0,.125);box-shadow:0 0 3px rgba(0,0,0,.125)}#jsn-form.horizontal.z-shadows > ul > li > a{box-shadow:-2px 0 2px -2px rgba(0,0,0,.1)}#jsn-form.horizontal.z-shadows > ul > li.z-first > a{box-shadow:-3px 1px 1px -3px rgba(0,0,0,.2)}#jsn-form.horizontal.z-shadows > ul > li.z-last > a{box-shadow:3px 1px 1px -3px rgba(0,0,0,.2)}#jsn-form.flat,#jsn-form.flat > .z-container,#jsn-form.flat > ul.z-tabs-nav,#jsn-form.flat.horizontal > ul.z-tabs-nav,#jsn-form.flat.vertical > ul.z-tabs-nav.z-tabs-desktop,#jsn-form.flat > ul li.z-first,#jsn-form.flat > ul.z-tabs-nav > li > a,#jsn-form.flat.horizontal > ul.z-tabs-nav > li > a,#jsn-form.flat.horizontal.clean > ul.z-tabs-nav > li > a{border-width:0;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;-moz-box-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}#jsn-form.flat.mini > ul > li > a{font-size:11px;padding:7px 16px}#jsn-form.flat.small > ul > li > a{font-size:11px;padding:13px 20px}#jsn-form.flat.medium > ul > li > a{font-size:13px;padding:16px 24px}#jsn-form.flat.large > ul > li > a{font-size:14px;padding:19px 28px}#jsn-form.flat.xlarge > ul > li > a{font-size:14px;padding:22px 32px}#jsn-form.flat.xxlarge > ul > li > a{font-size:15px;padding:25px 36px}#jsn-form.flat.top-compact > ul > li > a,#jsn-form.flat.bottom-compact > ul > li > a{padding-left:0;padding-right:0}#jsn-form.flat > ul > li > a{color:#374858;color:#2C3E50!important;text-shadow:none;font-family:'Open Sans',Helvetica,Arial,sans-serif}#jsn-form.flat .z-container{-webkit-border-radius:0!important;-moz-border-radius:0!important;border-radius:0!important}#jsn-form.flat > ul > li > a,#jsn-form.flat > .z-container,#jsn-form.flat > .z-container > .z-content{background:none;border-width:0}#jsn-form.flat > ul.z-tabs-nav > li > a:hover{background:#e3eaf0;background:#F6F7F9;text-shadow:none;box-shadow:none}#jsn-form.flat > ul.z-tabs-nav > li.z-active > a{background:#bdc3c7;color:#fff!important;text-shadow:none;box-shadow:none}#jsn-form.flat > ul.z-tabs-nav > li.z-active > a:hover{color:#2C3E50!important}#jsn-form.flat.horizontal > .z-container{margin-right:0!important}#jsn-form.flat.horizontal > .z-container > .z-content > .z-content-inner{padding:2em 0}#jsn-form.flat.horizontal.top > ul.z-tabs-nav,#jsn-form.flat.horizontal.top > ul.z-tabs-nav > li,#jsn-form.flat.horizontal.bottom > ul.z-tabs-nav,#jsn-form.flat.horizontal.bottom > ul.z-tabs-nav > li{margin:0;padding:0}#jsn-form.flat.horizontal > ul > li.z-active{top:0;margin-top:0;padding-bottom:0}#jsn-form.flat.horizontal.top > ul.z-tabs-nav > li.z-active{margin-bottom:0;padding-bottom:0}#jsn-form.flat.vertical > .z-container > .z-content > .z-content-inner{padding:0 2em}#jsn-form.flat.vertical.contained > .z-container > .z-content > .z-content-inner{padding:2em}#jsn-form.flat.vertical > ul.z-tabs-nav{margin-left:0;margin-right:0}#jsn-form.flat.vertical > .z-container{border-width:0;margin:0}#jsn-form.flat.vertical > ul > li.z-first.z-active > a{border-width:0}#jsn-form.flat.vertical > ul.z-tabs-nav > li.z-active{z-index:0}#jsn-form.flat.vertical > ul.z-tabs-nav > li > a{margin:0;text-align:left}#jsn-form.flat.clean.responsive.horizontal.bottom > ul > li.z-first-row > a,#jsn-form.flat.clean.responsive.horizontal.top > ul > li.z-last-row > a,#jsn-form.flat.clean.responsive.horizontal.bottom > ul > li.z-last-row > a{border-width:0}#jsn-form.flat.clean > ul > li.z-active > a{font-weight:800}#jsn-form.flat.z-multiline > ul > li> a,#jsn-form.flat.z-multiline > ul > li.z-active > a{font-weight:600}#jsn-form.flat.contained.horizontal> .z-container,#jsn-form.flat.contained.vertical> .z-container{background:#F7F7F8;background:#EFF0F2}#jsn-form.flat.contained.horizontal > .z-container > .z-content > .z-content-inner{padding:2em}#jsn-form.flat.contained > ul > li a,#jsn-form.flat.clean > ul > li a{background:#F7F7F8;background:#EFF0F2}#jsn-form.flat.contained > ul > li > a:hover,#jsn-form.flat.clean > ul > li > a:hover{background:#ECEDEE}#jsn-form.flat.clean.horizontal > ul.z-tabs-nav > li > a{text-align:center}#jsn-form.flat.clean.vertical > ul.z-tabs-nav > li > a{text-align:left}#jsn-form.flat.contained.z-spaced.horizontal.top > .z-container{top:3px}#jsn-form.flat.contained.z-spaced.horizontal.bottom > .z-container{margin:0 0 3px}#jsn-form.flat.contained.z-spaced.z-bordered.horizontal.top> .z-container{padding:0;top:0}#jsn-form.flat.contained.z-spaced.z-bordered.horizontal.bottom > .z-container{padding:0;margin:0}#jsn-form.flat.responsive.contained.z-spaced.horizontal.top > .z-container{top:2px}#jsn-form.flat.responsive.contained.z-spaced.horizontal.bottom > .z-container{margin:0 0 1px}#jsn-form.flat.pills.z-rounded > ul.z-tabs-nav > li > a,#jsn-form.flat.horizontal.top.responsive.z-rounded > ul.z-tabs-nav > li > a,#jsn-form.flat.horizontal.top.responsive.z-rounded > ul.z-tabs-nav > li.z-active > a,#jsn-form.flat.horizontal.bottom.responsive.z-rounded > ul.z-tabs-nav > li > a,#jsn-form.flat.horizontal.bottom.responsive.z-rounded > ul.z-tabs-nav > li.z-active > a,#jsn-form.flat.horizontal.bottom.z-rounded > ul.z-tabs-nav > li > a2{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}#jsn-form.flat.vertical.top-left.z-rounded > ul.z-tabs-nav > li > a,#jsn-form.flat.vertical.top-right.z-rounded > ul.z-tabs-nav > li > a{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}#jsn-form.flat.mobile.z-rounded > ul.z-tabs-nav > li.z-active,#jsn-form.flat.mobile.z-rounded > ul.z-tabs-nav > li.z-active:hover,#jsn-form.flat.mobile.z-rounded > ul.z-tabs-nav > li:hover,#jsn-form.horizontal.top-left.z-rounded > .z-container{-webkit-border-radius:0!important;-moz-border-radius:0!important;border-radius:0!important}#jsn-form.flat.mobile.horizontal.z-rounded > ul.z-tabs-nav > li > a,#jsn-form.flat.mobile.vertical.z-rounded > ul.z-tabs-mobile.z-state-closed > li > a,#jsn-form.flat.mobile.horizontal.z-rounded > ul.z-tabs-mobile.z-state-closed > li > a{-webkit-border-radius:4px!important;-moz-border-radius:4px!important;border-radius:4px!important}#jsn-form.flat.vertical.top-left.z-rounded.z-bordered > ul.z-tabs-nav > li > a{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}#jsn-form.flat.vertical.top-right.z-rounded.z-bordered > ul.z-tabs-nav > li > a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}#jsn-form.flat.clean.vertical.top-left.z-rounded.z-bordered > ul.z-tabs-desktop{-webkit-border-radius:6px 0 0 6px;-moz-border-radius:6px 0 0 6px;border-radius:6px 0 0 6px}#jsn-form.flat.clean.vertical.top-right.z-rounded.z-bordered > ul.z-tabs-desktop{-webkit-border-radius:0 6px 6px 0;-moz-border-radius:0 6px 6px 0;border-radius:0 6px 6px 0}#jsn-form.horizontal.top.flat.z-bordered.mini > .z-container{border-width:3px 0 0}#jsn-form.horizontal.top.flat.z-bordered.small > .z-container{border-width:4px 0 0}#jsn-form.horizontal.top.flat.z-bordered.medium > .z-container{border-width:5px 0 0}#jsn-form.horizontal.top.flat.z-bordered.large > .z-container{border-width:5px 0 0}#jsn-form.horizontal.top.flat.z-bordered.xlarge > .z-container{border-width:6px 0 0}#jsn-form.horizontal.top.flat.z-bordered.xxlarge > .z-container{border-width:6px 0 0}#jsn-form.horizontal.bottom.flat.z-bordered.mini > .z-container{border-width:0 0 3px}#jsn-form.horizontal.bottom.flat.z-bordered.small > .z-container{border-width:0 0 4px}#jsn-form.horizontal.bottom.flat.z-bordered.medium > .z-container{border-width:0 0 5px}#jsn-form.horizontal.bottom.flat.z-bordered.large > .z-container{border-width:0 0 5px}#jsn-form.horizontal.bottom.flat.z-bordered.xlarge > .z-container{border-width:0 0 6px}#jsn-form.horizontal.bottom.flat.z-bordered.xxlarge > .z-container{border-width:0 0 6px}#jsn-form.flat.horizontal.top.z-rounded.z-bordered.z-spaced > ul.z-tabs-nav > li > a,#jsn-form.flat.horizontal.top.z-rounded.z-bordered > ul.z-tabs-nav > li.z-active > a,#jsn-form.flat.horizontal.top.z-rounded.z-bordered > ul.z-tabs-nav > li:hover > a{-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0}#jsn-form.flat.horizontal.bottom.z-rounded.z-bordered > ul.z-tabs-nav > li > a,#jsn-form.flat.horizontal.bottom.z-rounded.z-bordered > ul.z-tabs-nav > li.z-active > a,#jsn-form.flat.horizontal.bottom.z-rounded.z-bordered > ul.z-tabs-nav > li:hover > a{-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px}#jsn-form.flat.vertical.z-bordered.top-right.mini > ul.z-tabs-nav{border-width:0 0 0 3px}#jsn-form.flat.vertical.z-bordered.top-right.small > ul.z-tabs-nav{border-width:0 0 0 4px}#jsn-form.flat.vertical.z-bordered.top-right.medium > ul.z-tabs-nav{border-width:0 0 0 5px}#jsn-form.flat.vertical.z-bordered.top-right.large > ul.z-tabs-nav{border-width:0 0 0 5px}#jsn-form.flat.vertical.z-bordered.top-right.xlarge > ul.z-tabs-nav{border-width:0 0 0 6px}#jsn-form.flat.vertical.z-bordered.top-right.xxlarge > ul.z-tabs-nav{border-width:0 0 0 6px}#jsn-form.flat.vertical.z-bordered.top-left.mini > ul.z-tabs-nav{border-width:0 3px 0 0}#jsn-form.flat.vertical.z-bordered.top-left.small > ul.z-tabs-nav{border-width:0 4px 0 0}#jsn-form.flat.vertical.z-bordered.top-left.medium > ul.z-tabs-nav{border-width:0 5px 0 0}#jsn-form.flat.vertical.z-bordered.top-left.large > ul.z-tabs-nav{border-width:0 5px 0 0}#jsn-form.flat.vertical.z-bordered.top-left.xlarge > ul.z-tabs-nav{border-width:0 6px 0 0}#jsn-form.flat.vertical.z-bordered.top-left.xxlarge > ul.z-tabs-nav{border-width:0 6px 0 0}#jsn-form.flat.mobile.vertical.z-bordered > ul.z-tabs-nav{border-width:0!important}#jsn-form.flat.z-spaced.horizontal > ul > li > a,#jsn-form.flat.z-spaced.z-shadows.z-dark.horizontal > ul > li > a{margin-right:2px}#jsn-form.flat.z-spaced.z-bordered.horizontal > ul > li > a,#jsn-form.flat.z-spaced.z-bordered.z-shadows.z-dark.horizontal > ul > li > a{margin-right:3px}#jsn-form.flat.z-spaced.horizontal > ul.z-tabs-nav > li.z-last > a,#jsn-form.flat.z-spaced.horizontal.z-multiline > ul.z-tabs-nav > li.z-last > a,#jsn-form.flat.z-spaced.horizontal.responsive > ul.z-tabs-nav > li.z-last-col > a{margin-right:0!important}#jsn-form.flat.z-spaced.horizontal.responsive > ul.z-tabs-nav > li > a{margin:1px 1px 0 0 !important}#jsn-form.flat.z-spaced.vertical > ul.z-tabs-desktop > li > a{margin-bottom:1px}#jsn-form.flat.z-spaced.vertical.top-left > ul.z-tabs-desktop{margin:0 1px 0 0}#jsn-form.flat.z-spaced.vertical.top-right > ul.z-tabs-desktop{margin:0 0 0 1px}#jsn-form.flat.z-spaced.vertical.top-left > ul.z-tabs-desktop > li.z-last > a,#jsn-form.flat.z-spaced.vertical.top-right > ul.z-tabs-desktop > li.z-last > a{margin-bottom:0}#jsn-form.flat.z-spaced.contained.horizontal.top.z-rounded > ul > li > a{border-radius:4px 4px 0 0}#jsn-form.flat.z-spaced.contained.horizontal.bottom.z-rounded > ul > li > a{border-radius:0 0 4px 4px}#jsn-form.flat.z-dark.contained.z-shadows.z-spaced.horizontal.top > ul > li > a{box-shadow:none!important}#jsn-form.mobile > ul.z-tabs-nav,#jsn-form.mobile > ul.z-tabs-nav > li,#jsn-form.mobile > ul.z-tabs-nav > li.z-active,#jsn-form.mobile > .z-container,#jsn-form.mobile > .z-container > .z-content{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;text-shadow:none}#jsn-form.mobile{position:relative}#jsn-form.mobile > ul.z-tabs-nav,#jsn-form.mobile > ul.z-tabs-nav.z-tabs-mobile,#jsn-form.mobile > ul.z-tabs-nav.z-tabs-mobile > li,#jsn-form.mobile > .z-container{width:100%;float:none;display:block;width:100%}#jsn-form.mobile > ul.z-tabs-nav{border-width:1px}#jsn-form.mobile > ul.z-tabs-nav > li > .z-link{margin:0!important}#jsn-form.mobile > ul.z-tabs-desktop{position:absolute;top:inherit;margin-top:8px;left:0;z-index:1000;width:100%;box-shadow:0 2px 1px rgba(51,51,51,0.1)}#jsn-form.mobile > ul > li{overflow:visible}#jsn-form.mobile > ul.z-tabs-nav > li > a{top:0}#jsn-form.mobile > ul > li.z-active > a{font-weight:700}#jsn-form.mobile.top > ul.z-tabs-desktop > li > a,#jsn-form.mobile.bottom > ul.z-tabs-desktop > li > a{border-width:1px 0 0}#jsn-form.mobile > ul.z-tabs-nav > li.z-first > a{border-width:0}#jsn-form.mobile.z-shadows > ul.z-tabs-mobile{-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1),0 1px 1px rgba(255,255,255,0.9) inset;-moz-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1),0 1px 1px rgba(255,255,255,0.9) inset;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1),0 1px 1px rgba(255,255,255,0.9) inset}#jsn-form.mobile > ul.z-tabs-desktop > li{float:none;display:block}#jsn-form.mobile > ul.z-tabs-desktop.z-hide-menu{opacity:0;height:0;visibility:hidden}#jsn-form.mobile.top > .z-container{margin-top:8px}#jsn-form.mobile.bottom > .z-container{margin-bottom:8px}#jsn-form.mobile > .z-container,#jsn-form.mobile > .z-container > .z-content.z-active{overflow:visible}#jsn-form.mobile > .z-container.z-animating,#jsn-form.mobile > .z-container.z-animating > .z-content.z-active{overflow:hidden}#jsn-form.mobile > ul.z-tabs-mobile.z-state-closed > li > a > span.z-arrow{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);transform:rotate(0deg);opacity:1}#jsn-form.mobile > ul.z-tabs-mobile > li > a > span.z-arrow{position:absolute;top:50%;background:url(../img/z-tabs-icons.png) no-repeat top left;background-position:-1470px -3px;width:30px;height:30px;margin-top:-25px;margin-left:-.75em;display:inline-block;right:1.125em}#jsn-form.z-icons-dark > ul.z-tabs-mobile > li > a > span.z-arrow{background-position:-1470px -3px}#jsn-form.mobile > ul.z-tabs-nav > li.z-active{margin:0;padding:0;top:0;bottom:0}#jsn-form.mobile > ul.z-tabs-nav > li.z-active > a{margin:0;top:0;bottom:0;width:auto}#jsn-form.mobile > ul.z-tabs-nav > li{border-width:0}#jsn-form.mobile > ul.z-tabs-nav > li > a{text-align:left}#jsn-form.mobile > ul.z-tabs-desktop > li.z-last{border-bottom-width:0}#jsn-form.mobile.z-rounded > ul.z-tabs-mobile.z-state-closed > li > a{-webkit-border-radius:5px;-moz-border-radius:5px;-khtml-border-radius:5px;border-radius:5px}#jsn-form.mobile.z-rounded > ul.z-tabs-mobile,#jsn-form.mobile.z-rounded > ul.z-tabs-desktop{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}#jsn-form.mobile.z-rounded > ul.z-tabs-mobile > li > a{-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}#jsn-form.mobile.z-rounded > ul.z-tabs-nav.z-tabs-desktop > li.z-last > a.z-link{-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px}#jsn-form.mobile.z-rounded > ul.z-tabs-nav > li.z-first > a{-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}#jsn-form.mobile.z-rounded > .z-container{-webkit-border-radius:6px;-moz-border-radius:6px;-khtml-border-radius:6px;border-radius:6px}#jsn-form #jsn-form *,#jsn-form ul,#jsn-form ul li,#jsn-form ul li a,#jsn-form .z-container .z-content{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-touch-callout:none;outline:none}#member-registration > fieldset,#member-profile > fieldset,.jsn-p-fields > fieldset{display:none}#jsn-form.flat > ul > li > a.jsninvalidfieldgroup,#jsn-form.flat > ul > li.z-active > a.jsninvalidfieldgroup{font-weight:700!important;color:#9D261D!important} \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.eot b/deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.eot new file mode 100644 index 0000000000000000000000000000000000000000..b1d693782a7d4ec4283ab7aa2e70204088ab3bd2 GIT binary patch literal 8396 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 PFSH@@Sa+)IcKg2oLhGld literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.svg b/deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.svg new file mode 100644 index 00000000..9a60e319 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.svg @@ -0,0 +1,31 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.ttf b/deployed/jsn/components/com_jsn/assets/fonts/jsn-icons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e28adee22f6f7bcd6b43cd96ed7a8ef772322b70 GIT binary patch literal 8224 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 literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/img/config-center.png b/deployed/jsn/components/com_jsn/assets/img/config-center.png new file mode 100644 index 0000000000000000000000000000000000000000..7f16e99460033fe50372b37b940d837f7ad0d407 GIT binary patch literal 4310 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 u3Dk#o%;3Wj8`qqkGxYE_H_h literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/img/config-fullwidth.png b/deployed/jsn/components/com_jsn/assets/img/config-fullwidth.png new file mode 100644 index 0000000000000000000000000000000000000000..f7b4ab30b0fca5b2ae9c87edd4f9a7dbddbb8311 GIT binary patch literal 4267 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 Gb>%-E8hd*H literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/img/default.jpg b/deployed/jsn/components/com_jsn/assets/img/default.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d8c188d7ca1c7b96b21aa0baeafd9c993023e144 GIT binary patch literal 4171 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
    qKz>Z!q5;1J~hK_~1i>wMBT=3+K!JmdcIgx|; z2&_!t@$PN@0^aR&sllSZkA>+XpU)2F`huYVuL^pJJ%m#daeQ>NY!WfNwq-GQ4|P?? zi;{>>;C=r@NE_c}WJ!4C(YIuUAIJfnoXAO#x%2@G&&5-=$fvV|Jtd9Q6&Nn3st*&7 zQ$60?7^o1LT z?ocqb0T06f7yJN`&?UR`&Blukv;G%6@Rv;8{qn&l-)Qege_3vfIp8G6)Cfx2xYRI*G*Mr! zztX0LRG?^T4BQg37>$DgEJcSN5ncEmTY36O9>y!`OPW# z*AYd)hUA!l@ksSC*(74NYU9v}r@Dn#1&3UDvPKX&3?$=W;IMUaOxJ05yCQOCh{)j_ z2sw|b5eDBFO~(1>Bz*EKBhG(QT-?#G(K#hAWRY#j!zY}i4<=%nQQQ|wcsGnkL7~zRZgG} zZ|1uA(9ooafS8gAskDM9O%ZG7!U4)+3QgCUG;`>&Z%Ak^RV|hozWAI#sa6jM563+o zp(;5mRk*k))5z%D!6v0BiMX{QX4c^ok9?cqHEKGSOz^$W36yH-sMF~d#i|R6LPb0U zxaJV)N13~axDHn0(h3G~)$Q56^YvwoR{dSREWHK7_dO?2%D6#XT-sCN>XI>EB8K#| zalV6<__Tt0Tz`MY;hPO3P`QI#-^&PJx|~3%gGM?Xx;9Rg9TTRhyzFhzh)f%&8dpgf zu5fXmQ#rHnEruAXlq)lQX>$Ulf=~U5P-QGvsB=q0HMOFHMr_r_*-FarX$5S@ugU=* zCvKYHTn4H8&qEwX+MGZ+FJ7z4yiK7pl?JP-CxpfgqP6VR#;GM`ga}0~r8@cG{AmH=I2gs5#tnepGt`k-CX&Yek z?3L7iQoz5SvbMaz$EBlB?d{ryt}!GRZOO~X+XcG0-C`)H$xG}7Y1d&*B*0%B3ib$} zUQ)(YE7@W^SCgl$tI16;R_4ZkT9U4KICSrOOJ?iy%H5vOaN>0ooA2Yr%hFy##QyJ= zq^macJEQ$aI$|=$IwMQRyThI1JrNz}dL#PI^+ychfYHcT{Skv-^+xuL_eQmhortP# zDb;?8vv1zSJ8d7XwP;uE*zx4`SHkC&qCKHP!hDL&^YP-pX>X3SC*%#UrQ0{{{p++R k#M`c+*wx>(cjdSD{|k0EDO3^)hyVZp07*qoM6N<$f)(ulW&i*H literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/img/icon-ccw.png b/deployed/jsn/components/com_jsn/assets/img/icon-ccw.png new file mode 100644 index 0000000000000000000000000000000000000000..8d88f3c949f1e1c908fc0957c12fb51c10b0175f GIT binary patch literal 2992 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 literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/img/icon-edit.png b/deployed/jsn/components/com_jsn/assets/img/icon-edit.png new file mode 100644 index 0000000000000000000000000000000000000000..ad91530ed0af0e015a23cc2ddd61706d3c6f4468 GIT binary patch literal 256 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 KboL(lcKscKb)zx> literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/img/m1.png b/deployed/jsn/components/com_jsn/assets/img/m1.png new file mode 100644 index 0000000000000000000000000000000000000000..329ff524c59e4ac6ba91db135e2257106253d7b9 GIT binary patch literal 3003 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 literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/img/m2.png b/deployed/jsn/components/com_jsn/assets/img/m2.png new file mode 100644 index 0000000000000000000000000000000000000000..b999cbcf69441f194768157d79a113b0fae03e3c GIT binary patch literal 3259 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 O0000KLZ*U+=)p!fv7f#TG` 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 literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/img/m5.png b/deployed/jsn/components/com_jsn/assets/img/m5.png new file mode 100644 index 0000000000000000000000000000000000000000..61387d2ab5c8d22efef4846617567a3b1ae6d72e GIT binary patch literal 6839 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 literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/img/no_image.gif b/deployed/jsn/components/com_jsn/assets/img/no_image.gif new file mode 100644 index 0000000000000000000000000000000000000000..2d01b9bb9b56a7ecb83432c39d0abc67ea8f6dee GIT binary patch literal 6795 zcmd7W`8Sk-+duI8p2gfVw!w^DhLj;Pv{>54uBe8xrx2w`ltQSPv5kFX8GB!YKi@7}#zTU%RQUH$Uq%lGf!mzS4+{`~p&?b}bEJ}oURO;1mM{rdICj~_f9Z)|Mr z+qZ9j|NdQBS(%!eT3lTG@ZkfW&mSBdeD&(p`1ttCmoMk%=Rbb@*w@!LGcz+XGBPwY z)ZN`(SXfw9RrTV;aX6gb-rl^tyoQE`l9H0z+S<0Zw)Xb+ z&d$#K{QSno#^&bc^78VIj*hyzx~ET{wzRZ7d-g0dGxPQ9*W26M!2g+1`h)nNT{Qli z|Gf!-+NN65!y_W2q8TxNzCN?DXD4ctc=X8?3~=Z2kiWU!lH+dic3n%$}1`# zS8=LqYU}D78k?G1TA#E%ea3C?=zQMwq6LJ(Ft7T1G2H`iTLr)&jI_|0&|XC`WhK#x z$q6MaTygIQp`Eayp?AwG`LYBB0#Wd<`X0*GHUP&6HPPu$kvgP+If{E;XLO>v7txT6 zh^0yI6F{*23n4Kr9WOFaU33^JE`82ooL$(*A|YW-eoAx%xclaoIFAs85~Jw7kU#Nr zmpQcK@L6tYZK(zvV`f4bCwmQ)J9xqnd};?(0w$!Vkc|Nuf`T<=F5YL6D6H&uPcL$p z8$z$rXLTN_M>C9UrfMG0Yjvv{@02z^$K???7tKH&`5d%TvnP)I`WnEvy|;dc5g~ zm*>5`i|Bm;JHFj44#44(bFMyc1e33hB(D*CVSdV_BW zLIesoPNQWVL`kuO+7X*x(qF)PG-50=QXk?9NLX*V+ zpy#jY7M_6ibG_8@ILs@WB%HV0b3JY=OuZsoskz;;5Mp7}J6GLQF z-ET?b`lBcO46jSXFU|YG`0wOUWmiUl?b18#0%W7<8Ywc0__Hq^Q@lH9*-Ji>vx6~$ z(3eH-s$$(0T6=rmD3>ei}k)Y z#m>5b?xOomhF(Tx-llPKvL1hG=mz^6`tGf)BB0;rA@=6d{j2#0qE6A-FO?QH-b-p!!~3^f{x zJo401AV$GDrsc%bN#Y8FeJ~4BJRt3BFcG4pqCyI9V{qxse#620ON`AefScZi@+1uN zko;H`Bia?%9J%rE!pIUe%3ld5GY-?(+Ua!rL*$p=DFEnOjh*g`TMN>D^5iE;%jxh% z<+n}gJnKT5kK+ZzPa_k3wfsvlG3Wr^kA zn1K6-&|OiMBOM~+@cqbm=-C}iT$v{<;v?dM_We$)R6Z=Szv9w?Y*{XX3U_$ot@fl$ z@(kU*1|F=gV!@>;`24Qt;59@Xu%i@dHcXLA6US1VZMcCGR#bCmJBn1$Oa7>sY78suS+ng3WhW76N#N7UQ5ICNfw-hAhX}h<0Iokj z;eN!8nl|5~h}P>0gxidomJB`t?)qYmw$n!*lkqP#dkLoF4i!W^9{nPA`+}%Hb>%Y^ zL>@6gO1qxN`qB|R1(Lcf^?8AZL(Sshy{gKg_(WwsYWm2s@=?lp<&q3BG}Twaw<0FE z%rl)$AxlKB05Wm(u6G_6(679wWU}q^GyIH#kIQ1v7Pq{=4kAnxKg4dro@cy{+$*#f z1Xusoi3^al(v1C$E8+oMux2m2#pj)oG$6oBTTnp&uJHwq{bde5c4J@B;;BJI35V~* zC;yVrjf93nJtkCBSM=&z68?d0A3Xg|%(qKj**Oq7&g|s8F(H$nkq00IRoMhYD|N?K=GJ(&@TC>fWDMVLLX*2qq~>Bb}?4u5I(@fkPXk)z=ImS@xVc zoGp%Xi z90d3@yJa_|%KG&(cHAeG=@6 z09R7dYOcCxJA&NMT?4?biq?q@6VJiaT*ng@{7Jp&+aimb3=w%hc>7&MRh&4Ty$^785FPhHBZ~(sp zI>wd(|0eaMLwoa?^Tfk0%k1r-^vY`&GBO&(H+o}lY0~IrsBL0VXYE;j5At)_t*!17PbcJdw`WFEY;~C_oi6@`TL1uo}H_HgisU3R&uNCE9v)%(XMqupl-LYXx z)Kc(jAT`1>AZ7_vV_it4TA3)xPNUGQ=%8cdP``*H0t_muz%(XsI2*aQm9P7lXjgQO$yIIO=v@m`c3#L#n#BS}B)@#T&{4`;`+n_Ni;f-BFJb_|r2=>{Bn}A@r1p`H-MsNe<@JV2nXwd@0#M?0ymjRQcnyI|kZCQ9hWFFvP;o)g{|Ni8&T0Vx*Ju ztW&aXrN|d2np8(Hc%WncHL_YHS|9oyWMifVNl;TG9;QYwc^i+XMgwUM+Th`INM1jQ zH0tgsgLHnGcAB3S#Z+7Q1qtwOnS$Wu80bnc^;8M-mIK=JMcNHV=&3y}Xchw5w;YtV z-8CJf%=qEib*$SK8CiVm%Ff8x(kSiZ^DG_Nd<^8zE|{YRdo~0 zs7LI-iVJ5#`yEpvk3)D)R_vAIriQkMyb>u?S~V+8-t2y}KGYh67v*Nr)2WU* zshqnrO%JTGfEE^auqh;tdB;BaZjxh^?(g{UIrclKz}hvC+%+J?LpG_{*ax09X7CPh?Jcx+}opRUI(9(pWEWdjPdx8?EMfQeXXB?x9xMwvXv`rTJ ztSrs07jkgIIkgm!h-oPt_LcfjIc#Az>5(xAc(y>7PvEY!6a|gseK*b;mO&2B#_60W z9#=URlvOD06xBNd?QMy^VeoK0uvoY3jzMfRmV8ua4NA^Jo6L)w#X>|U+zItuqb4wm z|47CtD{VTP_8+fa|(9Lvql#INY*c?Nk< zdymTU%QLvS_5(S>ad^=WY^c_SO$V)gy~sbFEVzER>ap zyrHAqsw^N~TdY2UR6jddlt||E=)(U#th46UK}`>c_N*iT#)AVI%{4|2h}l2IKQ2Ri zcy$@fl=beE0perX@xUFykujFguZ6IZ6PKkfhxV|tG2B3{_NWwQgkM~9Nl2JcU$I6UM*6ORWgsC+L^=KjMb@ob6t$MmSl;_sGFgsP& zpfm1GAiD5GnTmY!F+$;iG;W&y%QXH)hvlwRHrOfMLXL0oles&#QRJBuyM0-nck_;ucGJL|V&<_kAQYPKzSbgL#R^eBzJO`>` zaq54%Ah{7;bO@(RppPF;z%4bqu^h*5zjp6=gDg%xFW1s*0CmRU?+CqK6>^5NQze0* z>UxB?{z+-60gYL%f>K)=_nIl_k?>@o3W+dgg2Lo$^7ii(DTy=qOcBlQa9(4_Vj=ui zcRXo8d$}KVWc!3p@N;uv+*fnkC49|kv#Q$C!|oe&@-XiE0(5gT%*Zi`V+E1F zZTt8sAk#}EAC`IUjTa041hpL+VMo8o3>XRLKAEWxjSa>7R2DAV;^bWKqrFGjQt$hE z(?80&HoSt&>m-rfI=57o(Q(oD?Eu)a=i~y16o`{ zE)IV%)poO!caC%E`M3-7Yx-;o?_;aWa0BjuzL2x>dN;jpL2Ih9vE@Ik0!}psT8nXXk2j(J`&y$?iXssPkVrOGI2pCmn5gTZiD;H zCj9M3{#a2Xxj;`VL@k#Dy2q0f#OkupGE`-Yyr~mUr>s6to!XkB?3lI@nSSJxcD3(W z+K2wUkI?Wx@l{Q8<~ei`p3(K`FqM8kEbN%u>l+aZ;#!Gl?eDj?Q%6HW(5So`&!cFI zddcN~MseAU;JDAEfysRAti86)&8^R8t!T$9#5US68o4zwJCIYGp5b%W-phxoT<4r` zez_Ylk-+ivUY@JKeqG4mkFL)07`j$h!dGT6Ip=Xi=4^ZIOcd$#dE8VL0jRu-Z~6Dt z{yfy7r&C^m;m6&(ew3W{*-O_JEIo${JC6ZLyc*xna)|lv92o7nRUKh_j->r8kx(2|-Lw5pSOoHMs4i4y-r&?r?(gfra`&R7pzdg^K%Vm&r~YW5usHuP9^P=sgj zz~JyPoE&Abl?_HI{WSja(>qK^s$UX)y_Y+Gu4+I-&+(Vbet z*S)2Q%*D~2;JpM3ilT7aK79p2Q>_aI|9mxngyKc`pwN#4aO!&#LmiI9--8wa>)6rq zn=9b*AAP0ekZPbx*ie%D*VORG4Qp7*1)L)F_l*KT$VNtq^L@AfDnm>Udsffz%$plx zx`vZ5^Qv9JH)Yh0Ney0*#WH8m#s>^*H>qOaR7(33qbR{!n^(o#lR1-ypp717aWxVptP*u}7meF_sJ9gI2(vPXMPk_3_4W94 z8h}*56J3|uJGVW8q|Vsi0SfAV7{aV7c;8ZBNKt~>qPwaaf&sl~7k^f#jEwm*ajrz55@qqG zIT9F6qYF%+ba$wiDrsi|UWHc`0GLn8?J^6vOi*O$3DI-ZcIUiDy;1_ikGk{v$|NSU ztnMJ4j8fBBDmy73K=G>N9(5-J(xDt`d8^U50ur9X=7zSLZ7=}EF7BD^R4YCWB|fM2 ztucw{I*7b)7~GCj+|So+T8y%x2`uFMY5D^U0t~eahrQDJ@2?FR1w7+$xq|zl0gO8K zFem^x^L}(L3dxayev)f-m!b)w11{>r)$ZPL3@}6}p7YVRlQ=E3+^dHqaJ_4~{?){3 Z4EwD1>&;fIzCOIRxcY`1C<_6H{vQ|_=4t={ literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/img/z-tabs-icons.png b/deployed/jsn/components/com_jsn/assets/img/z-tabs-icons.png new file mode 100644 index 0000000000000000000000000000000000000000..d6f615743b4c63a30422823e4789b97e075441af GIT binary patch literal 10359 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 literal 0 HcmV?d00001 diff --git a/deployed/jsn/components/com_jsn/assets/js/avatarletters.js b/deployed/jsn/components/com_jsn/assets/js/avatarletters.js new file mode 100644 index 00000000..f354ffd2 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/js/avatarletters.js @@ -0,0 +1,92 @@ +/* + * LetterAvatar + * + * Artur Heinze + * Create Letter avatar based on Initials + * based on https://gist.github.com/leecrossley/6027780 + */ + (function(w, d){ + + + function LetterAvatar (name, size) { + + name = name || ''; + size = size || 60; + + var colours = [ + "#1abc9c", "#2ecc71", "#3498db", "#9b59b6", "#34495e", "#16a085", "#27ae60", "#2980b9", "#8e44ad", "#2c3e50", + "#f1c40f", "#e67e22", "#e74c3c", "#ecf0f1", "#95a5a6", "#f39c12", "#d35400", "#c0392b", "#bdc3c7", "#7f8c8d" + ], + + nameSplit = String(name).toUpperCase().split(' '), + initials, charIndex, colourIndex, canvas, context, dataURI; + + + if (nameSplit.length == 1) { + initials = nameSplit[0] ? nameSplit[0].charAt(0):'?'; + } else { + initials = nameSplit[0].charAt(0) + nameSplit[1].charAt(0); + } + + if (w.devicePixelRatio) { + size = (size * w.devicePixelRatio); + } + + charIndex = (initials == '?' ? 72 : initials.charCodeAt(0)) - 64; + colourIndex = charIndex % 20; + canvas = d.createElement('canvas'); + canvas.width = size; + canvas.height = size; + context = canvas.getContext("2d"); + + context.fillStyle = colours[colourIndex - 1]; + context.fillRect (0, 0, canvas.width, canvas.height); + context.font = Math.round(canvas.width/2)+"px Arial"; + context.textAlign = "center"; + context.fillStyle = "#FFF"; + context.fillText(initials, size / 2, size / 1.5); + + dataURI = canvas.toDataURL(); + canvas = null; + + return dataURI; + } + + LetterAvatar.transform = function() { + + Array.prototype.forEach.call(d.querySelectorAll('img[avatar]'), function(img, name) { + name = img.getAttribute('avatar'); + img.src = LetterAvatar(name, img.getAttribute('width')); + img.removeAttribute('avatar'); + img.setAttribute('alt', name); + }); + }; + + + // AMD support + if (typeof define === 'function' && define.amd) { + + define(function () { return LetterAvatar; }); + + // CommonJS and Node.js module support. + } else if (typeof exports !== 'undefined') { + + // Support Node.js specific `module.exports` (which can be a function) + if (typeof module != 'undefined' && module.exports) { + exports = module.exports = LetterAvatar; + } + + // But always support CommonJS module 1.1.1 spec (`exports` cannot be a function) + exports.LetterAvatar = LetterAvatar; + + } else { + + window.LetterAvatar = LetterAvatar; + + d.addEventListener('DOMContentLoaded', function(event) { + LetterAvatar.transform(); + jQuery(d).ajaxStop(function(){LetterAvatar.transform();}); + }); + } + + })(window, document); \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/js/avatarletters.min.js b/deployed/jsn/components/com_jsn/assets/js/avatarletters.min.js new file mode 100644 index 00000000..ecc25018 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/js/avatarletters.min.js @@ -0,0 +1 @@ +!function(a,b){function c(c,d){c=c||"",d=d||60;var g,h,i,j,k,l,e=["#1abc9c","#2ecc71","#3498db","#9b59b6","#34495e","#16a085","#27ae60","#2980b9","#8e44ad","#2c3e50","#f1c40f","#e67e22","#e74c3c","#ecf0f1","#95a5a6","#f39c12","#d35400","#c0392b","#bdc3c7","#7f8c8d"],f=String(c).toUpperCase().split(" ");return g=1==f.length?f[0]?f[0].charAt(0):"?":f[0].charAt(0)+f[1].charAt(0),a.devicePixelRatio&&(d*=a.devicePixelRatio),h=("?"==g?72:g.charCodeAt(0))-64,i=h%20,j=b.createElement("canvas"),j.width=d,j.height=d,k=j.getContext("2d"),k.fillStyle=e[i-1],k.fillRect(0,0,j.width,j.height),k.font=Math.round(j.width/2)+"px Arial",k.textAlign="center",k.fillStyle="#FFF",k.fillText(g,d/2,d/1.5),l=j.toDataURL(),j=null,l}c.transform=function(){Array.prototype.forEach.call(b.querySelectorAll("img[avatar]"),function(a,b){b=a.getAttribute("avatar"),a.src=c(b,a.getAttribute("width")),a.removeAttribute("avatar"),a.setAttribute("alt",b)})},"function"==typeof define&&define.amd?define(function(){return c}):"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=c),exports.LetterAvatar=c):(window.LetterAvatar=c,b.addEventListener("DOMContentLoaded",function(a){c.transform(),jQuery(b).ajaxStop(function(){c.transform()})}))}(window,document); \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/js/bootstrap-datepicker.js b/deployed/jsn/components/com_jsn/assets/js/bootstrap-datepicker.js new file mode 100644 index 00000000..bea73425 --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/js/bootstrap-datepicker.js @@ -0,0 +1,508 @@ +/* ========================================================= + * bootstrap-jsndatepicker.js + * http://www.eyecon.ro/bootstrap-jsndatepicker + * ========================================================= + * Copyright 2012 Stefan Petre + * + * Licensed 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. + * ========================================================= */ + +!function( $ ) { + + // Picker object + + var JsnDatepicker = function(element, options){ + DPGlobal.dates=DPGlobalDates; + this.element = $(element); + this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy'); + this.picker = $(DPGlobal.template) + .appendTo('body') + .on({ + click: $.proxy(this.click, this)//, + //mousedown: $.proxy(this.mousedown, this) + }); + this.isInput = this.element.is('input'); + this.component = this.element.is('.date') ? this.element.find('.btn') : false; + + if (this.isInput) { + this.element.on({ + focus: $.proxy(this.show, this), + //blur: $.proxy(this.hide, this), + keyup: $.proxy(this.update, this) + }); + } else { + if (this.component){ + this.component.on('click', $.proxy(this.show, this)); + } else { + this.element.on('click', $.proxy(this.show, this)); + } + } + + this.minViewMode = options.minViewMode||this.element.data('date-minviewmode')||0; + if (typeof this.minViewMode === 'string') { + switch (this.minViewMode) { + case 'months': + this.minViewMode = 1; + break; + case 'years': + this.minViewMode = 2; + break; + default: + this.minViewMode = 0; + break; + } + } + this.viewMode = options.viewMode||this.element.data('date-viewmode')||0; + if (typeof this.viewMode === 'string') { + switch (this.viewMode) { + case 'months': + this.viewMode = 1; + break; + case 'years': + this.viewMode = 2; + break; + default: + this.viewMode = 0; + break; + } + } + this.startViewMode = this.viewMode; + this.weekStart = options.weekStart||this.element.data('date-weekstart')||0; + this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1; + this.onRender = options.onRender; + this.fillDow(); + this.fillMonths(); + this.update(); + this.showMode(); + }; + + JsnDatepicker.prototype = { + constructor: JsnDatepicker, + + show: function(e) { + this.picker.show(); + this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); + this.place(); + $(window).on('resize', $.proxy(this.place, this)); + if (e ) { + e.stopPropagation(); + e.preventDefault(); + } + if (!this.isInput) { + } + var that = this; + $(document).on('mousedown', function(ev){ + if ($(ev.target).closest('.jsndatepicker').length == 0) { + that.hide(); + } + }); + this.element.trigger({ + type: 'show', + date: this.date + }); + }, + + hide: function(){ + this.picker.hide(); + $(window).off('resize', this.place); + this.viewMode = this.startViewMode; + this.showMode(); + if (!this.isInput) { + $(document).off('mousedown', this.hide); + } + //this.set(); + this.element.trigger({ + type: 'hide', + date: this.date + }); + }, + + set: function() { + var formated = DPGlobal.formatDate(this.date, this.format); + var noFormated = DPGlobal.formatDate(this.date, {parts: ['yyyy','mm','dd'], separator: ['-'] }); // JSN + if (!this.isInput) { + if (this.component){ + this.element.find('input:first').prop('value', formated); // JSN + this.element.find('input:last').prop('value', noFormated); // JSN + // JSN IE9 - START + if(navigator.appVersion.indexOf("MSIE 9.")!=-1 || navigator.appVersion.indexOf("MSIE 8.")!=-1) { + this.element.find('input').removeAttr('required').removeClass('required'); + } + // JSN IE9 - END + this.element.find('input').change(); // JSN + } + this.element.data('date', formated); + } else { + this.element.prop('value', formated); + } + }, + + setValue: function(newDate) { + if (typeof newDate === 'string') { + this.date = DPGlobal.parseDate(newDate, this.format); + } else { + this.date = new Date(newDate); + } + this.set(); + this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0); + this.fill(); + }, + + place: function(){ + var offset = this.component ? this.component.offset() : this.element.offset(); + this.picker.css({ + top: offset.top + this.height, + left: offset.left + }); + // JSN RTL - START + if($('html').attr('dir')=='rtl'){ + this.picker.css({ + right: $(window).width() - offset.left - 35, + left: 'auto' + }); + } + // JSN RTL - END + }, + + update: function(newDate){ + this.date = DPGlobal.parseDate( + typeof newDate === 'string' ? newDate : (this.isInput ? this.element.prop('value') : this.element.data('date')), + this.format + ); + this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0); + this.fill(); + }, + + fillDow: function(){ + var dowCnt = this.weekStart; + var html = ''; + while (dowCnt < this.weekStart + 7) { + html += ''+DPGlobal.dates.daysMin[(dowCnt++)%7]+''; + } + html += ''; + this.picker.find('.jsndatepicker-days thead').append(html); + }, + + fillMonths: function(){ + var html = ''; + var i = 0 + while (i < 12) { + html += ''+DPGlobal.dates.monthsShort[i++]+''; + } + this.picker.find('.jsndatepicker-months td').append(html); + }, + + fill: function() { + var d = new Date(this.viewDate), + year = d.getFullYear(), + month = d.getMonth(), + currentDate = this.date.valueOf(); + this.picker.find('.jsndatepicker-days th:eq(1)') + .text(DPGlobal.dates.months[month]+' '+year); + var prevMonth = new Date(year, month-1, 28,0,0,0,0), + day = DPGlobal.getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth()); + prevMonth.setDate(day); + prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7)%7); + var nextMonth = new Date(prevMonth); + nextMonth.setDate(nextMonth.getDate() + 42); + nextMonth = nextMonth.valueOf(); + var html = []; + var clsName, + prevY, + prevM; + while(prevMonth.valueOf() < nextMonth) { + if (prevMonth.getDay() === this.weekStart) { + html.push(''); + } + clsName = this.onRender(prevMonth); + prevY = prevMonth.getFullYear(); + prevM = prevMonth.getMonth(); + if ((prevM < month && prevY === year) || prevY < year) { + clsName += ' old'; + } else if ((prevM > month && prevY === year) || prevY > year) { + clsName += ' new'; + } + if (prevMonth.valueOf() === currentDate) { + clsName += ' active'; + } + html.push(''+prevMonth.getDate() + ''); + if (prevMonth.getDay() === this.weekEnd) { + html.push(''); + } + prevMonth.setDate(prevMonth.getDate()+1); + } + this.picker.find('.jsndatepicker-days tbody').empty().append(html.join('')); + var currentYear = this.date.getFullYear(); + + var months = this.picker.find('.jsndatepicker-months') + .find('th:eq(1)') + .text(year) + .end() + .find('span').removeClass('active'); + if (currentYear === year) { + months.eq(this.date.getMonth()).addClass('active'); + } + + html = ''; + year = parseInt(year/10, 10) * 10; + var yearCont = this.picker.find('.jsndatepicker-years') + .find('th:eq(1)') + .text(year + '-' + (year + 9)) + .end() + .find('td'); + year -= 1; + for (var i = -1; i < 11; i++) { + html += ''+year+''; + year += 1; + } + yearCont.html(html); + }, + + click: function(e) { + e.stopPropagation(); + e.preventDefault(); + var target = $(e.target).closest('span, td, th'); + if (target.length === 1) { + switch(target[0].nodeName.toLowerCase()) { + case 'th': + switch(target[0].className) { + case 'switch': + this.showMode(1); + break; + case 'prev': + case 'next': + this.viewDate['set'+DPGlobal.modes[this.viewMode].navFnc].call( + this.viewDate, + this.viewDate['get'+DPGlobal.modes[this.viewMode].navFnc].call(this.viewDate) + + DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1) + ); + this.fill(); + //this.set(); + break; + } + break; + case 'span': + if (target.is('.month')) { + var month = target.parent().find('span').index(target); + this.viewDate.setMonth(month); + } else { + var year = parseInt(target.text(), 10)||0; + this.viewDate.setFullYear(year); + } + if (this.viewMode !== 0) { + this.date = new Date(this.viewDate); + this.element.trigger({ + type: 'changeDate', + date: this.date, + viewMode: DPGlobal.modes[this.viewMode].clsName + }); + } + this.showMode(-1); + this.fill(); + //this.set(); + break; + case 'td': + if (target.is('.day') && !target.is('.disabled')){ + var day = parseInt(target.text(), 10)||1; + var month = this.viewDate.getMonth(); + if (target.is('.old')) { + month -= 1; + } else if (target.is('.new')) { + month += 1; + } + var year = this.viewDate.getFullYear(); + this.date = new Date(year, month, day,0,0,0,0); + this.viewDate = new Date(year, month, Math.min(28, day),0,0,0,0); + this.fill(); + this.set(); + this.hide(); + this.element.trigger({ + type: 'changeDate', + date: this.date, + viewMode: DPGlobal.modes[this.viewMode].clsName + }); + } + break; + } + } + }, + + mousedown: function(e){ + e.stopPropagation(); + e.preventDefault(); + }, + + showMode: function(dir) { + if (dir) { + this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir)); + } + this.picker.find('>div').hide().filter('.jsndatepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); + } + }; + + $.fn.jsndatepicker = function ( option, val ) { + return this.each(function () { + var $this = $(this), + data = $this.data('jsndatepicker'), + options = typeof option === 'object' && option; + if (!data) { + $this.data('jsndatepicker', (data = new JsnDatepicker(this, $.extend({}, $.fn.jsndatepicker.defaults,options)))); + } + if (typeof option === 'string') data[option](val); + }); + }; + + $.fn.jsndatepicker.defaults = { + onRender: function(date) { + return ''; + } + }; + $.fn.jsndatepicker.Constructor = JsnDatepicker; + + var DPGlobal = { + modes: [ + { + clsName: 'days', + navFnc: 'Month', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'FullYear', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'FullYear', + navStep: 10 + }], + dates:{ + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + }, + isLeapYear: function (year) { + return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)) + }, + getDaysInMonth: function (year, month) { + return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] + }, + parseFormat: function(format){ + var separator = format.match(/[.\/\-\s].*?/), + parts = format.split(/\W+/); + if (!separator || !parts || parts.length === 0){ + throw new Error("Invalid date format."); + } + return {separator: separator, parts: parts}; + }, + parseDate: function(date, format) { + var parts = date.split(format.separator), + date = new Date(), + val; + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + if (parts.length === format.parts.length) { + var year = date.getFullYear(), day = date.getDate(), month = date.getMonth(); + for (var i=0, cnt = format.parts.length; i < cnt; i++) { + val = parseInt(parts[i], 10)||/* JSN 1 ;*/parts[i]; + switch(format.parts[i]) { + case 'dd': + case 'd': + day = val; + date.setDate(val); + break; + case 'mm': + case 'm': + month = val - 1; + date.setMonth(val - 1); + break; + /* JSN Start */ + case 'MM': + val=DPGlobal.dates.months.indexOf(val); + month = val; + date.setMonth(val); + break; + case 'M': + val=DPGlobal.dates.monthsShort.indexOf(val); + month = val; + date.setMonth(val); + break; + /* JSN End */ + case 'yy': + year = 2000 + val; + date.setFullYear(2000 + val); + break; + case 'yyyy': + year = val; + date.setFullYear(val); + break; + } + } + date = new Date(year, month, day, 0 ,0 ,0); + } + return date; + }, + formatDate: function(date, format){ + var val = { + d: date.getDate(), + m: date.getMonth() + 1, + yy: date.getFullYear().toString().substring(2), + yyyy: date.getFullYear() + }; + val.dd = (val.d < 10 ? '0' : '') + val.d; + val.mm = (val.m < 10 ? '0' : '') + val.m; + /* JSN Start */ + val.MM = DPGlobal.dates.months[date.getMonth()]; + val.M = DPGlobal.dates.monthsShort[date.getMonth()]; + /* JSN End */ + var date = []; + for (var i=0, cnt = format.parts.length; i < cnt; i++) { + date.push(val[format.parts[i]]); + } + return date.join(format.separator); + }, + headTemplate: ''+ + ''+ + '‹'+ + ''+ + '›'+ + ''+ + '', + contTemplate: '' + }; + DPGlobal.template = ''; + +}( window.jQuery ); \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/js/bootstrap-datepicker.min.js b/deployed/jsn/components/com_jsn/assets/js/bootstrap-datepicker.min.js new file mode 100644 index 00000000..a7e3c0cf --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/js/bootstrap-datepicker.min.js @@ -0,0 +1 @@ +!function(a){var b=function(b,d){if(c.dates=DPGlobalDates,this.element=a(b),this.format=c.parseFormat(d.format||this.element.data("date-format")||"mm/dd/yyyy"),this.picker=a(c.template).appendTo("body").on({click:a.proxy(this.click,this)}),this.isInput=this.element.is("input"),this.component=!!this.element.is(".date")&&this.element.find(".btn"),this.isInput?this.element.on({focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this)}):this.component?this.component.on("click",a.proxy(this.show,this)):this.element.on("click",a.proxy(this.show,this)),this.minViewMode=d.minViewMode||this.element.data("date-minviewmode")||0,"string"==typeof this.minViewMode)switch(this.minViewMode){case"months":this.minViewMode=1;break;case"years":this.minViewMode=2;break;default:this.minViewMode=0}if(this.viewMode=d.viewMode||this.element.data("date-viewmode")||0,"string"==typeof this.viewMode)switch(this.viewMode){case"months":this.viewMode=1;break;case"years":this.viewMode=2;break;default:this.viewMode=0}this.startViewMode=this.viewMode,this.weekStart=d.weekStart||this.element.data("date-weekstart")||0,this.weekEnd=0===this.weekStart?6:this.weekStart-1,this.onRender=d.onRender,this.fillDow(),this.fillMonths(),this.update(),this.showMode()};b.prototype={constructor:b,show:function(b){this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.place(),a(window).on("resize",a.proxy(this.place,this)),b&&(b.stopPropagation(),b.preventDefault()),!this.isInput;var c=this;a(document).on("mousedown",function(b){0==a(b.target).closest(".jsndatepicker").length&&c.hide()}),this.element.trigger({type:"show",date:this.date})},hide:function(){this.picker.hide(),a(window).off("resize",this.place),this.viewMode=this.startViewMode,this.showMode(),this.isInput||a(document).off("mousedown",this.hide),this.element.trigger({type:"hide",date:this.date})},set:function(){var a=c.formatDate(this.date,this.format),b=c.formatDate(this.date,{parts:["yyyy","mm","dd"],separator:["-"]});this.isInput?this.element.prop("value",a):(this.component&&(this.element.find("input:first").prop("value",a),this.element.find("input:last").prop("value",b),navigator.appVersion.indexOf("MSIE 9.")==-1&&navigator.appVersion.indexOf("MSIE 8.")==-1||this.element.find("input").removeAttr("required").removeClass("required"),this.element.find("input").change()),this.element.data("date",a))},setValue:function(a){"string"==typeof a?this.date=c.parseDate(a,this.format):this.date=new Date(a),this.set(),this.viewDate=new Date(this.date.getFullYear(),this.date.getMonth(),1,0,0,0,0),this.fill()},place:function(){var b=this.component?this.component.offset():this.element.offset();this.picker.css({top:b.top+this.height,left:b.left}),"rtl"==a("html").attr("dir")&&this.picker.css({right:a(window).width()-b.left-35,left:"auto"})},update:function(a){this.date=c.parseDate("string"==typeof a?a:this.isInput?this.element.prop("value"):this.element.data("date"),this.format),this.viewDate=new Date(this.date.getFullYear(),this.date.getMonth(),1,0,0,0,0),this.fill()},fillDow:function(){for(var a=this.weekStart,b="";a'+c.dates.daysMin[a++%7]+"";b+="",this.picker.find(".jsndatepicker-days thead").append(b)},fillMonths:function(){for(var a="",b=0;b<12;)a+=''+c.dates.monthsShort[b++]+"";this.picker.find(".jsndatepicker-months td").append(a)},fill:function(){var a=new Date(this.viewDate),b=a.getFullYear(),d=a.getMonth(),e=this.date.valueOf();this.picker.find(".jsndatepicker-days th:eq(1)").text(c.dates.months[d]+" "+b);var f=new Date(b,d-1,28,0,0,0,0),g=c.getDaysInMonth(f.getFullYear(),f.getMonth());f.setDate(g),f.setDate(g-(f.getDay()-this.weekStart+7)%7);var h=new Date(f);h.setDate(h.getDate()+42),h=h.valueOf();for(var j,k,l,i=[];f.valueOf()"),j=this.onRender(f),k=f.getFullYear(),l=f.getMonth(),ld&&k===b||k>b)&&(j+=" new"),f.valueOf()===e&&(j+=" active"),i.push(''+f.getDate()+""),f.getDay()===this.weekEnd&&i.push(""),f.setDate(f.getDate()+1);this.picker.find(".jsndatepicker-days tbody").empty().append(i.join(""));var m=this.date.getFullYear(),n=this.picker.find(".jsndatepicker-months").find("th:eq(1)").text(b).end().find("span").removeClass("active");m===b&&n.eq(this.date.getMonth()).addClass("active"),i="",b=10*parseInt(b/10,10);var o=this.picker.find(".jsndatepicker-years").find("th:eq(1)").text(b+"-"+(b+9)).end().find("td");b-=1;for(var p=-1;p<11;p++)i+=''+b+"",b+=1;o.html(i)},click:function(b){b.stopPropagation(),b.preventDefault();var d=a(b.target).closest("span, td, th");if(1===d.length)switch(d[0].nodeName.toLowerCase()){case"th":switch(d[0].className){case"switch":this.showMode(1);break;case"prev":case"next":this.viewDate["set"+c.modes[this.viewMode].navFnc].call(this.viewDate,this.viewDate["get"+c.modes[this.viewMode].navFnc].call(this.viewDate)+c.modes[this.viewMode].navStep*("prev"===d[0].className?-1:1)),this.fill()}break;case"span":if(d.is(".month")){var e=d.parent().find("span").index(d);this.viewDate.setMonth(e)}else{var f=parseInt(d.text(),10)||0;this.viewDate.setFullYear(f)}0!==this.viewMode&&(this.date=new Date(this.viewDate),this.element.trigger({type:"changeDate",date:this.date,viewMode:c.modes[this.viewMode].clsName})),this.showMode(-1),this.fill();break;case"td":if(d.is(".day")&&!d.is(".disabled")){var g=parseInt(d.text(),10)||1,e=this.viewDate.getMonth();d.is(".old")?e-=1:d.is(".new")&&(e+=1);var f=this.viewDate.getFullYear();this.date=new Date(f,e,g,0,0,0,0),this.viewDate=new Date(f,e,Math.min(28,g),0,0,0,0),this.fill(),this.set(),this.hide(),this.element.trigger({type:"changeDate",date:this.date,viewMode:c.modes[this.viewMode].clsName})}}},mousedown:function(a){a.stopPropagation(),a.preventDefault()},showMode:function(a){a&&(this.viewMode=Math.max(this.minViewMode,Math.min(2,this.viewMode+a))),this.picker.find(">div").hide().filter(".jsndatepicker-"+c.modes[this.viewMode].clsName).show()}},a.fn.jsndatepicker=function(c,d){return this.each(function(){var e=a(this),f=e.data("jsndatepicker"),g="object"==typeof c&&c;f||e.data("jsndatepicker",f=new b(this,a.extend({},a.fn.jsndatepicker.defaults,g))),"string"==typeof c&&f[c](d)})},a.fn.jsndatepicker.defaults={onRender:function(a){return""}},a.fn.jsndatepicker.Constructor=b;var c={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],dates:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]},isLeapYear:function(a){return a%4===0&&a%100!==0||a%400===0},getDaysInMonth:function(a,b){return[31,c.isLeapYear(a)?29:28,31,30,31,30,31,31,30,31,30,31][b]},parseFormat:function(a){var b=a.match(/[.\/\-\s].*?/),c=a.split(/\W+/);if(!b||!c||0===c.length)throw new Error("Invalid date format.");return{separator:b,parts:c}},parseDate:function(a,b){var e,d=a.split(b.separator),a=new Date;if(a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0),d.length===b.parts.length){for(var f=a.getFullYear(),g=a.getDate(),h=a.getMonth(),i=0,j=b.parts.length;i‹›',contTemplate:''};c.template='"}(window.jQuery); \ No newline at end of file diff --git a/deployed/jsn/components/com_jsn/assets/js/jquery.Jcrop.min.js b/deployed/jsn/components/com_jsn/assets/js/jquery.Jcrop.min.js new file mode 100644 index 00000000..41857f5e --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/js/jquery.Jcrop.min.js @@ -0,0 +1,7 @@ +/** + * jquery.Jcrop.min.js v0.9.12 (build:20130202) + * jQuery Image Cropping Plugin - released under MIT License + * Copyright (c) 2008-2013 Tapmodo Interactive LLC + * https://github.com/tapmodo/Jcrop + */ +(function(e){e.Jcrop=function(t,n){function r(e){return Math.round(e)+"px"}function i(e){return H.baseClass+"-"+e}function s(){return e.fx.step.hasOwnProperty("backgroundColor")}function o(t){var n=e(t).offset();return[n.left,n.top]}function u(e){return[e.pageX-B[0],e.pageY-B[1]]}function f(t){typeof t!="object"&&(t={}),H=e.extend(H,t),e.each(["onChange","onSelect","onRelease","onDblClick"],function(e,t){typeof H[t]!="function"&&(H[t]=function(){})})}function l(e,t,n){B=o(W),mt.setCursor(e==="move"?e:e+"-resize");if(e==="move")return mt.activateHandlers(h(t),g,n);var r=pt.getFixed(),i=p(e),s=pt.getCorner(p(i));pt.setPressed(pt.getCorner(i)),pt.setCurrent(s),mt.activateHandlers(c(e,r),g,n)}function c(e,t){return function(n){if(!H.aspectRatio)switch(e){case"e":n[1]=t.y2;break;case"w":n[1]=t.y2;break;case"n":n[0]=t.x2;break;case"s":n[0]=t.x2}else switch(e){case"e":n[1]=t.y+1;break;case"w":n[1]=t.y+1;break;case"n":n[0]=t.x+1;break;case"s":n[0]=t.x+1}pt.setCurrent(n),vt.update()}}function h(e){var t=e;return gt.watchKeys(),function(e){pt.moveOffset([e[0]-t[0],e[1]-t[1]]),t=e,vt.update()}}function p(e){switch(e){case"n":return"sw";case"s":return"nw";case"e":return"nw";case"w":return"ne";case"ne":return"sw";case"nw":return"se";case"se":return"nw";case"sw":return"ne"}}function d(e){return function(t){return H.disabled?!1:e==="move"&&!H.allowMove?!1:(B=o(W),ft=!0,l(e,u(t)),t.stopPropagation(),t.preventDefault(),!1)}}function v(e,t,n){var r=e.width(),i=e.height();r>t&&t>0&&(r=t,i=t/e.width()*e.height()),i>n&&n>0&&(i=n,r=n/e.height()*e.width()),ot=e.width()/r,ut=e.height()/i,e.width(r).height(i)}function m(e){return{x:e.x*ot,y:e.y*ut,x2:e.x2*ot,y2:e.y2*ut,w:e.w*ot,h:e.h*ut}}function g(e){var t=pt.getFixed();t.w>H.minSelect[0]&&t.h>H.minSelect[1]?(vt.enableHandles(),vt.done()):vt.release(),mt.setCursor(H.allowSelect?"crosshair":"default")}function y(e){if(H.disabled)return!1;if(!H.allowSelect)return!1;ft=!0,B=o(W),vt.disableHandles(),mt.setCursor("crosshair");var t=u(e);return pt.setPressed(t),vt.update(),mt.activateHandlers(b,g,e.type.substring(0,5)==="touch"),gt.watchKeys(),e.stopPropagation(),e.preventDefault(),!1}function b(e){pt.setCurrent(e),vt.update()}function w(){var t=e("
    ").addClass(i("tracker"));return F&&t.css({opacity:0,backgroundColor:"white"}),t}function E(e){$.removeClass().addClass(i("holder")).addClass(e)}function S(e,t){function n(){window.setTimeout(b,c)}var r=e[0]/ot,i=e[1]/ut,s=e[2]/ot,o=e[3]/ut;if(lt)return;var u=pt.flipCoords(r,i,s,o),a=pt.getFixed(),f=[a.x,a.y,a.x2,a.y2],l=f,c=H.animationDelay,h=u[0]-f[0],p=u[1]-f[1],d=u[2]-f[2],v=u[3]-f[3],m=0,g=H.swingSpeed;r=l[0],i=l[1],s=l[2],o=l[3],vt.animMode(!0);var y,b=function(){return function(){m+=(100-m)/g,l[0]=Math.round(r+m/100*h),l[1]=Math.round(i+m/100*p),l[2]=Math.round(s+m/100*d),l[3]=Math.round(o+m/100*v),m>=99.8&&(m=100),m<100?(T(l),n()):(vt.done(),vt.animMode(!1),typeof t=="function"&&t.call(yt))}}();n()}function x(e){T([e[0]/ot,e[1]/ut,e[2]/ot,e[3]/ut]),H.onSelect.call(yt,m(pt.getFixed())),vt.enableHandles()}function T(e){pt.setPressed([e[0],e[1]]),pt.setCurrent([e[2],e[3]]),vt.update()}function N(){return m(pt.getFixed())}function C(){return pt.getFixed()}function k(e){f(e),P()}function L(){H.disabled=!0,vt.disableHandles(),vt.setCursor("default"),mt.setCursor("default")}function A(){H.disabled=!1,P()}function O(){vt.done(),mt.activateHandlers(null,null)}function M(){$.remove(),R.show(),R.css("visibility","visible"),e(t).removeData("Jcrop")}function _(e,t){vt.release(),L();var n=new Image;n.onload=function(){var r=n.width,i=n.height,s=H.boxWidth,o=H.boxHeight;W.width(r).height(i),W.attr("src",e),J.attr("src",e),v(W,s,o),X=W.width(),V=W.height(),J.width(X).height(V),Z.width(X+Y*2).height(V+Y*2),$.width(X).height(V),dt.resize(X,V),A(),typeof t=="function"&&t.call(yt)},n.src=e}function D(e,t,n){var r=t||H.bgColor;H.bgFade&&s()&&H.fadeTime&&!n?e.animate({backgroundColor:r},{queue:!1,duration:H.fadeTime}):e.css("backgroundColor",r)}function P(e){H.allowResize?e?vt.enableOnly():vt.enableHandles():vt.disableHandles(),mt.setCursor(H.allowSelect?"crosshair":"default"),vt.setCursor(H.allowMove?"move":"default"),H.hasOwnProperty("trueSize")&&(ot=H.trueSize[0]/X,ut=H.trueSize[1]/V),H.hasOwnProperty("setSelect")&&(x(H.setSelect),vt.done(),delete H.setSelect),dt.refresh(),H.bgColor!=et&&(D(H.shade?dt.getShades():$,H.shade?H.shadeColor||H.bgColor:H.bgColor),et=H.bgColor),tt!=H.bgOpacity&&(tt=H.bgOpacity,H.shade?dt.refresh():vt.setBgOpacity(tt)),nt=H.maxSize[0]||0,rt=H.maxSize[1]||0,it=H.minSize[0]||0,st=H.minSize[1]||0,H.hasOwnProperty("outerImage")&&(W.attr("src",H.outerImage),delete H.outerImage),vt.refresh()}var H=e.extend({},e.Jcrop.defaults),B,j=navigator.userAgent.toLowerCase(),F=/msie/.test(j),I=/msie [1-6]\./.test(j);typeof t!="object"&&(t=e(t)[0]),typeof n!="object"&&(n={}),f(n);var q={border:"none",visibility:"visible",margin:0,padding:0,position:"absolute",top:0,left:0},R=e(t),U=!0;if(t.tagName=="IMG"){if(R[0].width!=0&&R[0].height!=0)R.width(R[0].width),R.height(R[0].height);else{var z=new Image;z.src=R[0].src,R.width(z.width),R.height(z.height)}var W=R.clone().removeAttr("id").css(q).show();W.width(R.width()),W.height(R.height()),R.after(W).hide()}else W=R.css(q).show(),U=!1,H.shade===null&&(H.shade=!0);v(W,H.boxWidth,H.boxHeight);var X=W.width(),V=W.height(),$=e("
    ").width(X).height(V).addClass(i("holder")).css({position:"relative",backgroundColor:H.bgColor}).insertAfter(R).append(W);H.addClass&&$.addClass(H.addClass);var J=e("
    "),K=e("
    ").width("100%").height("100%").css({zIndex:310,position:"absolute",overflow:"hidden"}),Q=e("
    ").width("100%").height("100%").css("zIndex",320),G=e("
    ").css({position:"absolute",zIndex:600}).dblclick(function(){var e=pt.getFixed();H.onDblClick.call(yt,e)}).insertBefore(W).append(K,Q);U&&(J=e("").attr("src",W.attr("src")).css(q).width(X).height(V),K.append(J)),I&&G.css({overflowY:"hidden"});var Y=H.boundary,Z=w().width(X+Y*2).height(V+Y*2).css({position:"absolute",top:r(-Y),left:r(-Y),zIndex:290}).mousedown(y),et=H.bgColor,tt=H.bgOpacity,nt,rt,it,st,ot,ut,at=!0,ft,lt,ct;B=o(W);var ht=function(){function e(){var e={},t=["touchstart","touchmove","touchend"],n=document.createElement("div"),r;try{for(r=0;rl+t&&(t-=t+l),0>c+n&&(n-=n+c),VX&&(m=X,b=Math.abs((m-l)/e),g=s<0?c-b:b+c)):(m=h,b=o/e,g=s<0?c-b:c+b,g<0?(g=0,y=Math.abs((g-c)*e),m=i<0?l-y:y+l):g>V&&(g=V,y=Math.abs(g-c)*e,m=i<0?l-y:y+l)),m>l?(m-ln&&(m=l+n),g>c?g=c+(m-l)/e:g=c-(m-l)/e):mn&&(m=l-n),g>c?g=c+(l-m)/e:g=c-(l-m)/e),m<0?(l-=m,m=0):m>X&&(l-=m-X,m=X),g<0?(c-=g,g=0):g>V&&(c-=g-V,g=V),f(u(l,c,m,g))}function o(e){return e[0]<0&&(e[0]=0),e[1]<0&&(e[1]=0),e[0]>X&&(e[0]=X),e[1]>V&&(e[1]=V),[Math.round(e[0]),Math.round(e[1])]}function u(e,t,n,r){var i=e,s=n,o=t,u=r;return nnt&&(h=e>0?l+nt:l-nt),rt&&Math.abs(t)>rt&&(p=t>0?c+rt:c-rt),st/ut&&Math.abs(t)0?c+st/ut:c-st/ut),it/ot&&Math.abs(e)0?l+it/ot:l-it/ot),l<0&&(h-=l,l-=l),c<0&&(p-=c,c-=c),h<0&&(l-=h,h-=h),p<0&&(c-=p,p-=p),h>X&&(n=h-X,l-=n,h-=n),p>V&&(n=p-V,c-=n,p-=n),l>X&&(n=l-V,p-=n,c-=n),c>V&&(n=c-V,p-=n,c-=n),f(u(l,c,h,p))}function f(e){return{x:e[0],y:e[1],x2:e[2],y2:e[3],w:e[2]-e[0],h:e[3]-e[1]}}var l=0,c=0,h=0,p=0,d,v;return{flipCoords:u,setPressed:e,setCurrent:t,getOffset:n,moveOffset:r,getCorner:i,getFixed:s}}(),dt=function(){function t(e,t){v.left.css({height:r(t)}),v.right.css({height:r(t)})}function n(){return i(pt.getFixed())}function i(e){v.top.css({left:r(e.x),width:r(e.w),height:r(e.y)}),v.bottom.css({top:r(e.y2),left:r(e.x),width:r(e.w),height:r(V-e.y2)}),v.right.css({left:r(e.x2),width:r(X-e.x2)}),v.left.css({width:r(e.x)})}function s(){return e("
    ").css({position:"absolute",backgroundColor:H.shadeColor||H.bgColor}).appendTo(d)}function o(){p||(p=!0,d.insertBefore(W),n(),vt.setBgOpacity(1,0,1),J.hide(),u(H.shadeColor||H.bgColor,1),vt.isAwake()?l(H.bgOpacity,1):l(1,1))}function u(e,t){D(h(),e,t)}function f(){p&&(d.remove(),J.show(),p=!1,vt.isAwake()?vt.setBgOpacity(H.bgOpacity,1,1):(vt.setBgOpacity(1,1,1),vt.disableHandles()),D($,0,1))}function l(e,t){p&&(H.bgFade&&!t?d.animate({opacity:1-e},{queue:!1,duration:H.fadeTime}):d.css({opacity:1-e}))}function c(){H.shade?o():f(),vt.isAwake()&&l(H.bgOpacity)}function h(){return d.children()}var p=!1,d=e("
    ").css({position:"absolute",zIndex:240,opacity:0}),v={top:s(),left:s().height(V),right:s().height(V),bottom:s()};return{update:n,updateRaw:i,getShades:h,setBgColor:u,enable:o,disable:f,resize:t,refresh:c,opacity:l}}(),vt=function(){function t(t){var n=e("
    ").css({position:"absolute",opacity:H.borderOpacity}).addClass(i(t));return K.append(n),n}function n(t,n){var r=e("
    ").mousedown(d(t)).css({cursor:t+"-resize",position:"absolute",zIndex:n}).addClass("ord-"+t);return ht.support&&r.bind("touchstart.jcrop",ht.createDragger(t)),Q.append(r),r}function s(e){var t=H.handleSize,r=n(e,L++).css({opacity:H.handleOpacity}).addClass(i("handle"));return t&&r.width(t).height(t),r}function o(e){return n(e,L++).addClass("jcrop-dragbar")}function u(e){var t;for(t=0;t').css({position:"fixed",left:"-120px",width:"12px"}).addClass("jcrop-keymgr"),o=e("
    ").css({position:"absolute",overflow:"hidden"}).append(s);return H.keySupport&&(s.keydown(i).blur(n),I||!H.fixedSupport?(s.css({position:"absolute",left:"-20px"}),o.append(s).insertBefore(W)):s.insertBefore(W)),{watchKeys:t}}();ht.support&&Z.bind("touchstart.jcrop",ht.newSelection),Q.hide(),P(!0);var yt={setImage:_,animateTo:S,setSelect:x,setOptions:k,tellSelect:N,tellScaled:C,setClass:E,disable:L,enable:A,cancel:O,release:vt.release,destroy:M,focus:gt.watchKeys,getBounds:function(){return[X*ot,V*ut]},getWidgetSize:function(){return[X,V]},getScaleFactor:function(){return[ot,ut]},getOptions:function(){return H},ui:{holder:$,selection:G}};return F&&$.bind("selectstart",function(){return!1}),R.data("Jcrop",yt),yt},e.fn.Jcrop=function(t,n){var r;return this.each(function(){if(e(this).data("Jcrop")){if(t==="api")return e(this).data("Jcrop");e(this).data("Jcrop").setOptions(t)}else this.tagName=="IMG"?e.Jcrop.Loader(this,function(){e(this).css({display:"block",visibility:"hidden"}),r=e.Jcrop(this,t),e.isFunction(n)&&n.call(r)}):(e(this).css({display:"block",visibility:"hidden"}),r=e.Jcrop(this,t),e.isFunction(n)&&n.call(r))}),this},e.Jcrop.Loader=function(t,n,r){function i(){o.complete?(s.unbind(".jcloader"),e.isFunction(n)&&n.call(o)):window.setTimeout(i,50)}var s=e(t),o=s[0];s.bind("load.jcloader",i).bind("error.jcloader",function(t){s.unbind(".jcloader"),e.isFunction(r)&&r.call(o)}),o.complete&&e.isFunction(n)&&(s.unbind(".jcloader"),n.call(o))},e.Jcrop.defaults={allowSelect:!0,allowMove:!0,allowResize:!0,trackDocument:!0,baseClass:"jcrop",addClass:null,bgColor:"black",bgOpacity:.6,bgFade:!1,borderOpacity:.4,handleOpacity:.5,handleSize:null,aspectRatio:0,keySupport:!0,createHandles:["n","s","e","w","nw","ne","se","sw"],createDragbars:["n","s","e","w"],createBorders:["n","s","e","w"],drawBorders:!0,dragEdges:!0,fixedSupport:!0,touchSupport:null,shade:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onDblClick:function(){},onRelease:function(){}}})(jQuery) diff --git a/deployed/jsn/components/com_jsn/assets/js/jquery.imgpicker.js b/deployed/jsn/components/com_jsn/assets/js/jquery.imgpicker.js new file mode 100644 index 00000000..3c21544d --- /dev/null +++ b/deployed/jsn/components/com_jsn/assets/js/jquery.imgpicker.js @@ -0,0 +1,716 @@ +;(function($, window, document, undefined) { + + // Detect XMLHttpRequest support + $.support.xhrUpload = !!(window.XMLHttpRequest && window.File && window.FileReader + && window.FileList && window.Blob && window.FormData); + + // Detect getUserMedia support + $.support.getUserMedia = !!(navigator.getUserMedia || navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || navigator.msGetUserMedia); + + // Detect Jcrop support + $.support.Jcrop = !!$.Jcrop; + + // Detect JPEGCam support + $.support.Webcam = !!window.Webcam; + + var + // Plugin name + pluginName = 'imgPicker', + + // Default plugin options + defaults = { + // Upload url (Value Type: string) + url: 'server/upload.php', + + // DropZone (See Plugin.prototype.init()) + //dropZone: null, + + // Whether crop is enabled (Value Type: boolean) + crop: true, + + // Aspect ratio of w/h (Value Type: decimal) + aspectRatio: null, + + // Minimum width/height, use 0 for unbounded dimension (Value Type: array [ w, h ]) + minSize: null, + + // Maximum width/height, use 0 for unbounded dimension (Value Type: array [ w, h ]) + maxSize: null, + + // Set an initial selection area (Value Type: array [ x, y, x2, y2 ]) + setSelect: null, + + // Flash swf url + swf: 'assets/webcam.swf', + + // Flash swf width/height (Value Type: array [ w, h ]) + swfSize: [470, 350], + + // Custom data to be passed to server (Value Type: object) + data: {}, + + // Messages + messages: { + selectimg: 'Please select a image to upload', + parsererror: 'Invalid response', + webcamerror: 'Webcam Error: ', + uploading: 'Uploading...', + error: 'Unexpected error', + datauri: 'Cannot locate image format in Data URI', + webcamjs: 'Flash webcam not found', + upgrade: 'This feature is not available in this browser', + loading: 'Loading image...', + saving: 'Saving...', + jcrop: 'jQuery Jcrop not found', + minCropWidth: 'Crop selection requires a minimum width of ', + maxCropWidth: 'Crop selection exceeds maximum width of ', + minCropHeight: 'Crop selection requires a height of ', + maxCropHeight: 'Crop selection exceeds maximum height of ', + img404: 'Error 404: No image was found' + }, + }, + // HTML5 webcam stream + stream, + + // IframeTransport iframe counter + counter = 0; + + // Plugin constructor + function Plugin(container, options) { + this.options = $.extend({}, defaults, options); + this.container = $(container); + this.init(); + } + + // Plugin functions + Plugin.prototype = { + + // Initialization function + init: function() { + + // Add click events for the buttons + this.elem('.ip-upload').on('change', 'input', $.proxy(this.upload, this)); + this.elem('.ip-webcam').on('click', $.proxy(this.webcam, this)); + this.elem('.ip-edit').on('click', $.proxy(this.edit, this)); + this.elem('.ip-delete').on('click', $.proxy(this._delete, this)); + this.elem('.ip-cancel').on('click', $.proxy(this.reset, this)); + + if (this.options.dropZone === undefined) + this.options.dropZone = this.container; + + var self = this, + trigger = $('[data-ip-modal="#'+ this.container.attr('id') +'"]'); + + if (trigger.length) { + // Modal events + this.container.on({ + 'show.ip.modal': function() { + self.container.fadeIn(150, function() { + $(this).trigger('shown.ip.modal', self); + }); + }, + 'hide.ip.modal': function() { + self.container.fadeOut(150, function() { + self.reset(); + $(this).trigger('hidden.ip.modal', self); + }); + } + }); + + // Add click event on the button to open modal + trigger.on('click', function(e) { + e.preventDefault(); + self.modal('show'); + self.elem('.ip-close').off().on('click', function() { + self.modal('hide'); + }); + }); + + if (this.options.dropZone === undefined) + this.options.dropZone = this.elem('.ip-modal-content'); + } + + // Drag & drop upload + if (this.options.dropZone) { + this.options.dropZone.on('dragenter', function(e) { + e.stopPropagation(); + e.preventDefault(); + }).on('dragover', function(e) { + e.stopPropagation(); + e.preventDefault(); + }).on('drop', function(e) { + e.preventDefault(); + if (e.originalEvent.dataTransfer.files && e.originalEvent.dataTransfer.files[0]) { + self.reset(); + self.handleFileUpload(e.originalEvent.dataTransfer.files[0]); + } + }); + } + + if (this.options.loadComplete) + this.load(); + }, + + // Modal function, show/hide modal + modal: function(action) { + this.container.trigger(action + '.ip.modal'); + }, + + // Autoload image from server + load: function() { + var self = this; + $.ajax({ + url: this.options.url, + dataType: 'json', + data: {action: 'load', data: this.getData()}, + success: function(response) { + self.dispatch('loadComplete', response); + } + }); + }, + + // Upload init + upload: function(event) { + this.reset(); + + // Iframe Transport fallback + if (!$.support.xhrUpload) + return this.iframeTransport(event); + + // XHR Upload + if (event.target.files && event.target.files[0]) + this.handleFileUpload(event.target.files[0]); + + $(event.target).val(''); + }, + + // Iframe Transport upload + iframeTransport: function(event) { + var iframe, form, self = this, + fileInput = $(event.target), + parent = fileInput.parent(), + fileInputClone = fileInput.clone(); + + this.dispatch('uploadProgress', 100); + + // Create & add iframe to body + iframe = $('') + .appendTo('body') + .on('load', function() { + self.dispatch('uploadProgressComplete', function() { + try { + var response = $.parseJSON( iframe.contents().find('body').html() ); + } catch(e) {} + + // Check for response + if (response) { + self.alert('', 'hide'); + self.uploadComplete(response); + } else + self.alert(self.i18n('parsererror'), 'error'); + + // Remove iframe & form + setTimeout(function() { + iframe.remove(); form.remove(); + parent.append(fileInputClone); + }, 100); + }); + }); + + // Create form + form = $('
    '); + form.prop('method', 'POST'); + form.prop('action', this.options.url); + form.prop('target', iframe.prop('name')); + form.prop('enctype', 'multipart/form-data'); + form.prop('encoding', 'multipart/form-data'); + form.prop({action: this.options.url, target: iframe.prop('name')}); + form.append(fileInput); + form.append(''); + + // Add custom data to the form + var data = this.getData(); + if (data) { + $.each(data, function (name, value) { + $('').prop('name', 'data['+name+']').val(value).appendTo(form); + }); + } + + // Append the form to body and submit + form.appendTo('body').trigger('submit'); + }, + + // Webcam snapshot + webcam: function() { + this.reset(); + + // Flash webcam fallback + if (!$.support.getUserMedia) + return this.flashWebcam(); + + // HTML5 Webcam with