commit 9f1a0a42d599b05db40488311ecfa49a13d9deaa Author: Dro1d.Ru Date: Thu Jun 2 17:42:43 2016 +0500 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a351bd0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +cache/ +log/ +uploads/ +.idea/ +config.php +robots.txt +.htaccess diff --git a/403.html b/403.html new file mode 100644 index 0000000..cce6d55 --- /dev/null +++ b/403.html @@ -0,0 +1,29 @@ + + + + + +403. Forbidden + + + +

403 Forbidden

+

Sorry, access to requested page is restricted.

+Zira CMS + + \ No newline at end of file diff --git a/404.html b/404.html new file mode 100644 index 0000000..e1e9d0f --- /dev/null +++ b/404.html @@ -0,0 +1,29 @@ + + + + + +404. Page not found + + + +

404 Page not found

+

Sorry, requested page not found on this server.

+Zira CMS + + \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..8310aeb --- /dev/null +++ b/README @@ -0,0 +1,4 @@ +Zira CMS is a free content management software with unique windows-based backend. +Zira CMS requires PHP 5.5+, MySQL 5 or SQLite 3. + +Visit http://dro1d.ru for more details. \ No newline at end of file diff --git a/assets/css/bootstrap-datetimepicker.min.css b/assets/css/bootstrap-datetimepicker.min.css new file mode 100644 index 0000000..63c2a3a --- /dev/null +++ b/assets/css/bootstrap-datetimepicker.min.css @@ -0,0 +1,5 @@ +/*! + * Datetimepicker for Bootstrap 3 + * version : 4.17.37 + * https://github.com/Eonasdan/bootstrap-datetimepicker/ + */.bootstrap-datetimepicker-widget{list-style:none}.bootstrap-datetimepicker-widget.dropdown-menu{margin:2px 0;padding:4px;width:19em}@media (min-width:768px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:992px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:1200px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}.bootstrap-datetimepicker-widget.dropdown-menu:before,.bootstrap-datetimepicker-widget.dropdown-menu:after{content:'';display:inline-block;position:absolute}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);top:-7px;left:7px}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after{border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid white;top:-6px;left:8px}.bootstrap-datetimepicker-widget.dropdown-menu.top:before{border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,0.2);bottom:-7px;left:6px}.bootstrap-datetimepicker-widget.dropdown-menu.top:after{border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid white;bottom:-6px;left:7px}.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after{left:auto;right:7px}.bootstrap-datetimepicker-widget .list-unstyled{margin:0}.bootstrap-datetimepicker-widget a[data-action]{padding:6px 0}.bootstrap-datetimepicker-widget a[data-action]:active{box-shadow:none}.bootstrap-datetimepicker-widget .timepicker-hour,.bootstrap-datetimepicker-widget .timepicker-minute,.bootstrap-datetimepicker-widget .timepicker-second{width:54px;font-weight:bold;font-size:1.2em;margin:0}.bootstrap-datetimepicker-widget button[data-action]{padding:6px}.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Increment Hours"}.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Increment Minutes"}.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Decrement Hours"}.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Decrement Minutes"}.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Show Hours"}.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Show Minutes"}.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Toggle AM/PM"}.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Clear the picker"}.bootstrap-datetimepicker-widget .btn[data-action="today"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Set the date to today"}.bootstrap-datetimepicker-widget .picker-switch{text-align:center}.bootstrap-datetimepicker-widget .picker-switch::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Toggle Date and Time Screens"}.bootstrap-datetimepicker-widget .picker-switch td{padding:0;margin:0;height:auto;width:auto;line-height:inherit}.bootstrap-datetimepicker-widget .picker-switch td span{line-height:2.5;height:2.5em;width:100%}.bootstrap-datetimepicker-widget table{width:100%;margin:0}.bootstrap-datetimepicker-widget table td,.bootstrap-datetimepicker-widget table th{text-align:center;border-radius:4px}.bootstrap-datetimepicker-widget table th{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget table th.picker-switch{width:145px}.bootstrap-datetimepicker-widget table th.disabled,.bootstrap-datetimepicker-widget table th.disabled:hover{background:none;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget table th.prev::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Previous Month"}.bootstrap-datetimepicker-widget table th.next::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Next Month"}.bootstrap-datetimepicker-widget table thead tr:first-child th{cursor:pointer}.bootstrap-datetimepicker-widget table thead tr:first-child th:hover{background:#eee}.bootstrap-datetimepicker-widget table td{height:54px;line-height:54px;width:54px}.bootstrap-datetimepicker-widget table td.cw{font-size:.8em;height:20px;line-height:20px;color:#777}.bootstrap-datetimepicker-widget table td.day{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget table td.day:hover,.bootstrap-datetimepicker-widget table td.hour:hover,.bootstrap-datetimepicker-widget table td.minute:hover,.bootstrap-datetimepicker-widget table td.second:hover{background:#eee;cursor:pointer}.bootstrap-datetimepicker-widget table td.old,.bootstrap-datetimepicker-widget table td.new{color:#777}.bootstrap-datetimepicker-widget table td.today{position:relative}.bootstrap-datetimepicker-widget table td.today:before{content:'';display:inline-block;border:solid transparent;border-width:0 0 7px 7px;border-bottom-color:#337ab7;border-top-color:rgba(0,0,0,0.2);position:absolute;bottom:4px;right:4px}.bootstrap-datetimepicker-widget table td.active,.bootstrap-datetimepicker-widget table td.active:hover{background-color:#337ab7;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.bootstrap-datetimepicker-widget table td.active.today:before{border-bottom-color:#fff}.bootstrap-datetimepicker-widget table td.disabled,.bootstrap-datetimepicker-widget table td.disabled:hover{background:none;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget table td span{display:inline-block;width:54px;height:54px;line-height:54px;margin:2px 1.5px;cursor:pointer;border-radius:4px}.bootstrap-datetimepicker-widget table td span:hover{background:#eee}.bootstrap-datetimepicker-widget table td span.active{background-color:#337ab7;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.bootstrap-datetimepicker-widget table td span.old{color:#777}.bootstrap-datetimepicker-widget table td span.disabled,.bootstrap-datetimepicker-widget table td span.disabled:hover{background:none;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget.usetwentyfour td.hour{height:27px;line-height:27px}.bootstrap-datetimepicker-widget.wider{width:21em}.bootstrap-datetimepicker-widget .datepicker-decades .decade{line-height:1.8em !important}.input-group.date .input-group-addon{cursor:pointer}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0} \ No newline at end of file diff --git a/assets/css/bootstrap-theme.min.css b/assets/css/bootstrap-theme.min.css new file mode 100644 index 0000000..61358b1 --- /dev/null +++ b/assets/css/bootstrap-theme.min.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} \ No newline at end of file diff --git a/assets/css/bootstrap.min.css b/assets/css/bootstrap.min.css new file mode 100644 index 0000000..d65c66b --- /dev/null +++ b/assets/css/bootstrap.min.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:3;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} \ No newline at end of file diff --git a/assets/css/bxslider.css b/assets/css/bxslider.css new file mode 100644 index 0000000..9370c90 --- /dev/null +++ b/assets/css/bxslider.css @@ -0,0 +1,209 @@ +/** + * BxSlider v4.1.2 - Fully loaded, responsive content slider + * http://bxslider.com + * + * Written by: Steven Wanderski, 2014 + * http://stevenwanderski.com + * (while drinking Belgian ales and listening to jazz) + * + * CEO and founder of bxCreative, LTD + * http://bxcreative.com + */ + + +/** RESET AND LAYOUT +===================================*/ + +.bx-wrapper { + position: relative; + margin: 0 auto 60px; + padding: 0; + *zoom: 1; +} + +.bx-wrapper img { + max-width: 100%; + display: block; +} + +/** THEME +===================================*/ + +.bx-wrapper .bx-viewport { + box-shadow: 0 0 2px #ccc; + border: 1px solid #fff; + /*left: -5px;*/ + left: 0px; + background: #fafafa; + + /*fix other elements on the page moving (on Chrome)*/ + -webkit-transform: translatez(0); + -moz-transform: translatez(0); + -ms-transform: translatez(0); + -o-transform: translatez(0); + transform: translatez(0); +} + +.bx-wrapper .bx-viewport .image { + border: none; + box-shadow: none; + border-radius: 0; +} + +.bx-wrapper .bx-pager, +.bx-wrapper .bx-controls-auto { + position: absolute; + bottom: -30px; + width: 100%; +} + +/* LOADER */ + +.bx-wrapper .bx-loading { + min-height: 50px; + background: url(../images/bx_loader.gif) center center no-repeat #fff; + height: 100%; + width: 100%; + position: absolute; + top: 0; + left: 0; + z-index: 20; +} + +/* PAGER */ + +.bx-wrapper .bx-pager { + text-align: center; + font-size: .85em; + font-family: Arial; + font-weight: bold; + color: #666; + padding-top: 20px; +} + +.bx-wrapper .bx-pager .bx-pager-item, +.bx-wrapper .bx-controls-auto .bx-controls-auto-item { + display: inline-block; + *zoom: 1; + *display: inline; +} + +.bx-wrapper .bx-pager.bx-default-pager a { + background: #666; + text-indent: -9999px; + display: block; + width: 10px; + height: 10px; + margin: 0 5px; + outline: 0; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} + +.bx-wrapper .bx-pager.bx-default-pager a:hover, +.bx-wrapper .bx-pager.bx-default-pager a.active { + background: #000; +} + +/* DIRECTION CONTROLS (NEXT / PREV) */ + +.bx-wrapper .bx-prev { + left: 10px; + background: url(../images/bx_controls.png) no-repeat 0 -32px; +} + +.bx-wrapper .bx-next { + right: 10px; + background: url(../images/bx_controls.png) no-repeat -43px -32px; +} + +.bx-wrapper .bx-prev:hover { + background-position: 0 0; +} + +.bx-wrapper .bx-next:hover { + background-position: -43px 0; +} + +.bx-wrapper .bx-controls-direction a { + position: absolute; + top: 50%; + margin-top: -16px; + outline: 0; + width: 32px; + height: 32px; + text-indent: -9999px; + z-index: 99; +} + +.bx-wrapper .bx-controls-direction a.disabled { + display: none; +} + +/* AUTO CONTROLS (START / STOP) */ + +.bx-wrapper .bx-controls-auto { + text-align: center; +} + +.bx-wrapper .bx-controls-auto .bx-start { + display: block; + text-indent: -9999px; + width: 10px; + height: 11px; + outline: 0; + background: url(../images/bx_controls.png) -86px -11px no-repeat; + margin: 0 3px; +} + +.bx-wrapper .bx-controls-auto .bx-start:hover, +.bx-wrapper .bx-controls-auto .bx-start.active { + background-position: -86px 0; +} + +.bx-wrapper .bx-controls-auto .bx-stop { + display: block; + text-indent: -9999px; + width: 9px; + height: 11px; + outline: 0; + background: url(../images/bx_controls.png) -86px -44px no-repeat; + margin: 0 3px; +} + +.bx-wrapper .bx-controls-auto .bx-stop:hover, +.bx-wrapper .bx-controls-auto .bx-stop.active { + background-position: -86px -33px; +} + +/* PAGER WITH AUTO-CONTROLS HYBRID LAYOUT */ + +.bx-wrapper .bx-controls.bx-has-controls-auto.bx-has-pager .bx-pager { + text-align: left; + width: 80%; +} + +.bx-wrapper .bx-controls.bx-has-controls-auto.bx-has-pager .bx-controls-auto { + right: 0; + width: 35px; +} + +/* IMAGE CAPTIONS */ + +.bx-wrapper .bx-caption { + position: absolute; + bottom: 0; + left: 0; + background: #666\9; + background: rgba(80, 80, 80, 0.75); + width: 100%; +} + +.bx-wrapper .bx-caption span { + color: #fff; + font-family: Arial; + display: block; + font-size: .85em; + padding: 10px; +} diff --git a/assets/css/cropper.css b/assets/css/cropper.css new file mode 100644 index 0000000..41d83ba --- /dev/null +++ b/assets/css/cropper.css @@ -0,0 +1,40 @@ +.image-cropper { + position: relative; +} +.image-cropper img { + margin: 0; + padding: 0; + border: none; + position: absolute; + top: 0px; + left: 0px; + z-index: 9; +} +.image-cropper .image-cropper-selector { + position: absolute; + border: 1px solid #2aabd2; + background-color: rgba(15, 194, 248, 0.4); + z-index: 10; +} +.image-cropper .image-cropper-selector .image-cropper-resizer { + position: absolute; + border: 1px solid #9acfea; + background-color: #2aabd2; + cursor: nwse-resize; +} +.image-cropper .image-cropper-preview { + position: absolute; + background-color: #cccccc; + overflow: hidden; +} +.image-cropper-preview-custom { + overflow: hidden; +} +.image-cropper .image-cropper-preview img, +.image-cropper-preview-custom img { + position: absolute; + border: none; +} +body.image-cropper-resizing { + cursor: nwse-resize; +} \ No newline at end of file diff --git a/assets/css/index.php b/assets/css/index.php new file mode 100644 index 0000000..b052b3f --- /dev/null +++ b/assets/css/index.php @@ -0,0 +1,64 @@ +1; +$assets_root = '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . ASSETS_ROOT; +$path = $assets_root . DIRECTORY_SEPARATOR . ASSETS_CACHE_FILE; +$gz_path = $assets_root . DIRECTORY_SEPARATOR . ASSETS_GZIP_CACHE_FILE; + +if (!file_exists($path)) exit('File not found'); +if (!is_readable($path)) exit('File is not readable'); + +header_remove('X-Powered-By'); +header_remove('Pragma'); +header_remove('Set-Cookie'); +header("Content-Type: text/css; charset=utf-8"); +header('Cache-Control: public'); +header("Expires: ".date('r',time()+3600*24)); + +if (!empty($etag)) header('ETag: '.$etag); +if (empty($etag) || !isset($_SERVER['HTTP_IF_NONE_MATCH']) || $etag!=$_SERVER['HTTP_IF_NONE_MATCH']) { + header('HTTP/1.1 200 OK'); + + $accept_encoding = ''; + if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && preg_match( '/\b(x-gzip|gzip)\b/', strtolower($_SERVER['HTTP_ACCEPT_ENCODING']), $match)) { + $accept_encoding = $match[1]; + } + if (empty($accept_encoding) && defined('FORCE_GZIP_ASSETS') && FORCE_GZIP_ASSETS) $accept_encoding = 'gzip'; + if ($gzip && function_exists('gzencode') && !@ini_get('zlib.output_compression') && !empty($accept_encoding)) { + header("Vary: Accept-Encoding"); + header("Content-Encoding: " . $accept_encoding); + + if (file_exists($gz_path) && is_readable($gz_path) && filesize($gz_path)>0 && filemtime($gz_path)==filemtime($path)) { + $output = file_get_contents($gz_path); + } else { + $output = file_get_contents($path); + $output = gzencode($output, 9, FORCE_GZIP); + + if (is_writable($assets_root) && ($f=fopen($gz_path,'wb'))!==false) { + fwrite($f, $output); + fclose($f); + touch($gz_path, filemtime($path)); + } + } + } else { + $output = file_get_contents($path); + } + + echo $output; +} else { + header('HTTP/1.1 304 Not Modified'); +} \ No newline at end of file diff --git a/assets/css/lightbox.css b/assets/css/lightbox.css new file mode 100644 index 0000000..678c140 --- /dev/null +++ b/assets/css/lightbox.css @@ -0,0 +1,216 @@ +/* Preload images */ +body:after { + content: url(../images/close.png) url(../images/loading.gif) url(../images/prev.png) url(../images/next.png); + display: none; +} + +.lightboxOverlay { + position: absolute; + top: 0; + left: 0; + z-index: 9999; + background-color: black; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); + opacity: 0.8; + display: none; +} + +.lightbox { + position: absolute; + left: 0; + width: 100%; + z-index: 10000; + text-align: center; + line-height: 0; + font-weight: normal; +} + +.lightbox .lb-image { + display: block; + height: auto; + max-width: inherit; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; +} + +.lightbox a img { + border: none; +} + +.lb-outerContainer { + position: relative; + background-color: white; + *zoom: 1; + width: 250px; + height: 250px; + margin: 0 auto; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -ms-border-radius: 4px; + -o-border-radius: 4px; + border-radius: 4px; +} + +.lb-outerContainer:after { + content: ""; + display: table; + clear: both; +} + +.lb-container { + padding: 4px; +} + +.lb-loader { + position: absolute; + top: 43%; + left: 0; + height: 25%; + width: 100%; + text-align: center; + line-height: 0; +} + +.lb-cancel { + display: block; + width: 32px; + height: 32px; + margin: 0 auto; + background: url(../images/loading.gif) no-repeat; +} + +.lb-nav { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 10; +} + +.lb-container > .nav { + left: 0; +} + +.lb-nav a { + outline: none; + background-image: url('data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='); +} + +.lb-prev, .lb-next { + height: 100%; + cursor: pointer; + display: block; +} + +.lb-nav a.lb-prev { + width: 34%; + left: 0; + float: left; + background: url(../images/prev.png) left 48% no-repeat; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); + opacity: 0; + -webkit-transition: opacity 0.6s; + -moz-transition: opacity 0.6s; + -o-transition: opacity 0.6s; + transition: opacity 0.6s; +} + +.lb-nav a.lb-prev:hover { + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); + opacity: 1; +} + +.lb-nav a.lb-next { + width: 64%; + right: 0; + float: right; + background: url(../images/next.png) right 48% no-repeat; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); + opacity: 0; + -webkit-transition: opacity 0.6s; + -moz-transition: opacity 0.6s; + -o-transition: opacity 0.6s; + transition: opacity 0.6s; +} + +.lb-nav a.lb-next:hover { + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); + opacity: 1; +} + +.lb-dataContainer { + margin: 0 auto; + padding-top: 5px; + *zoom: 1; + width: 100%; + -moz-border-radius-bottomleft: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +.lb-dataContainer:after { + content: ""; + display: table; + clear: both; +} + +.lb-data { + padding: 0 4px; + color: #ccc; +} + +.lb-data .lb-details { + width: 85%; + float: left; + text-align: left; + line-height: 1.1em; +} + +.lb-data .lb-caption { + font-size: 13px; + font-weight: bold; + line-height: 1em; +} + +.lb-data .lb-number { + display: block; + clear: left; + padding-bottom: 1em; + font-size: 12px; + color: #999999; +} + +.lightbox .lb-closeContainer { + position: absolute; + top: -30px; + right: 10px; +} +.lightbox .lb-close { + display: block; + float: right; + width: 30px; + height: 30px; + background: url(../images/close.png) top right no-repeat; + text-align: right; + outline: none; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70); + opacity: 0.7; + -webkit-transition: opacity 0.2s; + -moz-transition: opacity 0.2s; + -o-transition: opacity 0.2s; + transition: opacity 0.2s; + cursor: pointer; +} + +.lb-data .lb-close:hover { + cursor: pointer; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); + opacity: 1; +} diff --git a/assets/css/zira.css b/assets/css/zira.css new file mode 100644 index 0000000..47ac59b --- /dev/null +++ b/assets/css/zira.css @@ -0,0 +1,152 @@ +html, body { + width: 100%; +} +select.form-control { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 6px; + background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%); + background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%); + background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0)); + background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); + filter:progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat:repeat-x; +} +select.form-control option { + padding: 5px 20px; +} +.form-panel { + margin: 20px 0px; +} +.form-alert { + margin-top: 20px; +} +.captcha-image-wrapper { + margin-bottom: 10px; +} +.captcha-image-wrapper img { + border: 1px solid #CCC; + border-radius: 4px; +} +.form-file-button { + position: relative; + overflow: hidden; +} +.form-file-button input[type=file] { + position: absolute; + top: 0; + right: 0; + min-width: 100%; + min-height: 100%; + filter: alpha(opacity=0); + opacity: 0; + display: block; + cursor: pointer; +} +.form-file-button-text { + padding: 0px 10px; +} +.form-horizontal .checkbox-float { + padding-top: 4px; +} +.modal-error { + color: #591053; +} +.modal-success { + color: #073954; +} +.error-page { + margin-top: 40px; +} +.error-page h1 { + display: inline-block; +} +span.required { + color: red; +} +.form-field-error { + box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.075) inset, 0px 0px 8px rgba(233, 139, 102, 0.6); +} +dl.user-info { + display: block; + overflow: hidden; +} +dl.user-info dt { + float: left; + margin-right: 10px; +} +img.user-photo { + width: 25px; + height: 25px; + border: none; +} +img.user-photo-mid { + width: 50px; + height: 50px; + border: none; +} +img.user-photo-big { + width: 100px; + height: 100px; + border: none; +} +.clear { + clear: both; +} +.zira-autocomplete-wnd { + position: absolute; + list-style-type: none; + margin: 0px; + padding: 0px; + background-color: #FFFFFF; + border: 1px solid #CCCCCC; + border-radius: 4px; + box-shadow: 0px 0px 4px #CCCCCC; + overflow: hidden; +} +.zira-autocomplete-wnd li { + margin: 0px; + padding: 0px; +} +.zira-autocomplete-wnd li a:link, +.zira-autocomplete-wnd li a:visited { + display: block; + min-width: 200px; + font-size: 14px; + color: #333; + margin: 0px; + padding: 4px 14px; + border-top: 1px solid #efefef; + text-decoration: none; +} +.zira-autocomplete-wnd li:first-child a { + border-top: none; +} +.zira-autocomplete-wnd li a:hover, +.zira-autocomplete-wnd li a.active { + color: #000; + background-color: #efefef; + text-decoration: none; +} +.form-group .zira_form_compose_remove_recipient_input { + display: none; + position: absolute; + right: 24px; + top: 8px; +} +.form-group-added .zira_form_compose_remove_recipient_input { + display: block; +} +.emoji { + vertical-align: middle; +} +.image { + max-width: 100%; + height: auto; +} +.external-image { + max-width: 100%; + height: auto; +} \ No newline at end of file diff --git a/assets/fonts/Lobster.ttf b/assets/fonts/Lobster.ttf new file mode 100644 index 0000000..5e848bb Binary files /dev/null and b/assets/fonts/Lobster.ttf differ diff --git a/assets/fonts/glyphicons-halflings-regular.eot b/assets/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000..b93a495 Binary files /dev/null and b/assets/fonts/glyphicons-halflings-regular.eot differ diff --git a/assets/fonts/glyphicons-halflings-regular.svg b/assets/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000..94fb549 --- /dev/null +++ b/assets/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/fonts/glyphicons-halflings-regular.ttf b/assets/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000..1413fc6 Binary files /dev/null and b/assets/fonts/glyphicons-halflings-regular.ttf differ diff --git a/assets/fonts/glyphicons-halflings-regular.woff b/assets/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..9e61285 Binary files /dev/null and b/assets/fonts/glyphicons-halflings-regular.woff differ diff --git a/assets/fonts/glyphicons-halflings-regular.woff2 b/assets/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000..64539b5 Binary files /dev/null and b/assets/fonts/glyphicons-halflings-regular.woff2 differ diff --git a/assets/images/blank.png b/assets/images/blank.png new file mode 100644 index 0000000..9a847fb Binary files /dev/null and b/assets/images/blank.png differ diff --git a/assets/images/bx_controls.png b/assets/images/bx_controls.png new file mode 100644 index 0000000..5c4898b Binary files /dev/null and b/assets/images/bx_controls.png differ diff --git a/assets/images/bx_loader.gif b/assets/images/bx_loader.gif new file mode 100644 index 0000000..f4ff40e Binary files /dev/null and b/assets/images/bx_loader.gif differ diff --git a/assets/images/close.png b/assets/images/close.png new file mode 100644 index 0000000..20baa1d Binary files /dev/null and b/assets/images/close.png differ diff --git a/assets/images/drag.png b/assets/images/drag.png new file mode 100644 index 0000000..2aed13b Binary files /dev/null and b/assets/images/drag.png differ diff --git a/assets/images/emoji/png/1f600.png b/assets/images/emoji/png/1f600.png new file mode 100644 index 0000000..5457c7b Binary files /dev/null and b/assets/images/emoji/png/1f600.png differ diff --git a/assets/images/emoji/png/1f601.png b/assets/images/emoji/png/1f601.png new file mode 100644 index 0000000..1449a4d Binary files /dev/null and b/assets/images/emoji/png/1f601.png differ diff --git a/assets/images/emoji/png/1f602.png b/assets/images/emoji/png/1f602.png new file mode 100644 index 0000000..6fcbc87 Binary files /dev/null and b/assets/images/emoji/png/1f602.png differ diff --git a/assets/images/emoji/png/1f603.png b/assets/images/emoji/png/1f603.png new file mode 100644 index 0000000..5e69b43 Binary files /dev/null and b/assets/images/emoji/png/1f603.png differ diff --git a/assets/images/emoji/png/1f604.png b/assets/images/emoji/png/1f604.png new file mode 100644 index 0000000..5a0490e Binary files /dev/null and b/assets/images/emoji/png/1f604.png differ diff --git a/assets/images/emoji/png/1f605.png b/assets/images/emoji/png/1f605.png new file mode 100644 index 0000000..8472063 Binary files /dev/null and b/assets/images/emoji/png/1f605.png differ diff --git a/assets/images/emoji/png/1f606.png b/assets/images/emoji/png/1f606.png new file mode 100644 index 0000000..d336015 Binary files /dev/null and b/assets/images/emoji/png/1f606.png differ diff --git a/assets/images/emoji/png/1f607.png b/assets/images/emoji/png/1f607.png new file mode 100644 index 0000000..b2d7004 Binary files /dev/null and b/assets/images/emoji/png/1f607.png differ diff --git a/assets/images/emoji/png/1f608.png b/assets/images/emoji/png/1f608.png new file mode 100644 index 0000000..fa7baa6 Binary files /dev/null and b/assets/images/emoji/png/1f608.png differ diff --git a/assets/images/emoji/png/1f609.png b/assets/images/emoji/png/1f609.png new file mode 100644 index 0000000..f69e1f8 Binary files /dev/null and b/assets/images/emoji/png/1f609.png differ diff --git a/assets/images/emoji/png/1f60a.png b/assets/images/emoji/png/1f60a.png new file mode 100644 index 0000000..41f4fd3 Binary files /dev/null and b/assets/images/emoji/png/1f60a.png differ diff --git a/assets/images/emoji/png/1f60b.png b/assets/images/emoji/png/1f60b.png new file mode 100644 index 0000000..e99c1e5 Binary files /dev/null and b/assets/images/emoji/png/1f60b.png differ diff --git a/assets/images/emoji/png/1f60c.png b/assets/images/emoji/png/1f60c.png new file mode 100644 index 0000000..0ff7e23 Binary files /dev/null and b/assets/images/emoji/png/1f60c.png differ diff --git a/assets/images/emoji/png/1f60d.png b/assets/images/emoji/png/1f60d.png new file mode 100644 index 0000000..af21d68 Binary files /dev/null and b/assets/images/emoji/png/1f60d.png differ diff --git a/assets/images/emoji/png/1f60e.png b/assets/images/emoji/png/1f60e.png new file mode 100644 index 0000000..bd9aa8c Binary files /dev/null and b/assets/images/emoji/png/1f60e.png differ diff --git a/assets/images/emoji/png/1f60f.png b/assets/images/emoji/png/1f60f.png new file mode 100644 index 0000000..1014a7d Binary files /dev/null and b/assets/images/emoji/png/1f60f.png differ diff --git a/assets/images/emoji/png/1f610.png b/assets/images/emoji/png/1f610.png new file mode 100644 index 0000000..590d790 Binary files /dev/null and b/assets/images/emoji/png/1f610.png differ diff --git a/assets/images/emoji/png/1f611.png b/assets/images/emoji/png/1f611.png new file mode 100644 index 0000000..e93769e Binary files /dev/null and b/assets/images/emoji/png/1f611.png differ diff --git a/assets/images/emoji/png/1f612.png b/assets/images/emoji/png/1f612.png new file mode 100644 index 0000000..075e950 Binary files /dev/null and b/assets/images/emoji/png/1f612.png differ diff --git a/assets/images/emoji/png/1f613.png b/assets/images/emoji/png/1f613.png new file mode 100644 index 0000000..6703e64 Binary files /dev/null and b/assets/images/emoji/png/1f613.png differ diff --git a/assets/images/emoji/png/1f614.png b/assets/images/emoji/png/1f614.png new file mode 100644 index 0000000..84afe36 Binary files /dev/null and b/assets/images/emoji/png/1f614.png differ diff --git a/assets/images/emoji/png/1f615.png b/assets/images/emoji/png/1f615.png new file mode 100644 index 0000000..7dbfab9 Binary files /dev/null and b/assets/images/emoji/png/1f615.png differ diff --git a/assets/images/emoji/png/1f616.png b/assets/images/emoji/png/1f616.png new file mode 100644 index 0000000..978686f Binary files /dev/null and b/assets/images/emoji/png/1f616.png differ diff --git a/assets/images/emoji/png/1f617.png b/assets/images/emoji/png/1f617.png new file mode 100644 index 0000000..8493c00 Binary files /dev/null and b/assets/images/emoji/png/1f617.png differ diff --git a/assets/images/emoji/png/1f618.png b/assets/images/emoji/png/1f618.png new file mode 100644 index 0000000..40ccac7 Binary files /dev/null and b/assets/images/emoji/png/1f618.png differ diff --git a/assets/images/emoji/png/1f619.png b/assets/images/emoji/png/1f619.png new file mode 100644 index 0000000..533e9b7 Binary files /dev/null and b/assets/images/emoji/png/1f619.png differ diff --git a/assets/images/emoji/png/1f61a.png b/assets/images/emoji/png/1f61a.png new file mode 100644 index 0000000..24cc483 Binary files /dev/null and b/assets/images/emoji/png/1f61a.png differ diff --git a/assets/images/emoji/png/1f61b.png b/assets/images/emoji/png/1f61b.png new file mode 100644 index 0000000..09207a6 Binary files /dev/null and b/assets/images/emoji/png/1f61b.png differ diff --git a/assets/images/emoji/png/1f61c.png b/assets/images/emoji/png/1f61c.png new file mode 100644 index 0000000..b03460b Binary files /dev/null and b/assets/images/emoji/png/1f61c.png differ diff --git a/assets/images/emoji/png/1f61d.png b/assets/images/emoji/png/1f61d.png new file mode 100644 index 0000000..747ec0c Binary files /dev/null and b/assets/images/emoji/png/1f61d.png differ diff --git a/assets/images/emoji/png/1f61e.png b/assets/images/emoji/png/1f61e.png new file mode 100644 index 0000000..d64131e Binary files /dev/null and b/assets/images/emoji/png/1f61e.png differ diff --git a/assets/images/emoji/png/1f61f.png b/assets/images/emoji/png/1f61f.png new file mode 100644 index 0000000..eae3566 Binary files /dev/null and b/assets/images/emoji/png/1f61f.png differ diff --git a/assets/images/emoji/png/1f620.png b/assets/images/emoji/png/1f620.png new file mode 100644 index 0000000..757cb72 Binary files /dev/null and b/assets/images/emoji/png/1f620.png differ diff --git a/assets/images/emoji/png/1f621.png b/assets/images/emoji/png/1f621.png new file mode 100644 index 0000000..8af9ea0 Binary files /dev/null and b/assets/images/emoji/png/1f621.png differ diff --git a/assets/images/emoji/png/1f622.png b/assets/images/emoji/png/1f622.png new file mode 100644 index 0000000..41b8892 Binary files /dev/null and b/assets/images/emoji/png/1f622.png differ diff --git a/assets/images/emoji/png/1f623.png b/assets/images/emoji/png/1f623.png new file mode 100644 index 0000000..19ae7dd Binary files /dev/null and b/assets/images/emoji/png/1f623.png differ diff --git a/assets/images/emoji/png/1f624.png b/assets/images/emoji/png/1f624.png new file mode 100644 index 0000000..51d5949 Binary files /dev/null and b/assets/images/emoji/png/1f624.png differ diff --git a/assets/images/emoji/png/1f625.png b/assets/images/emoji/png/1f625.png new file mode 100644 index 0000000..2098308 Binary files /dev/null and b/assets/images/emoji/png/1f625.png differ diff --git a/assets/images/emoji/png/1f626.png b/assets/images/emoji/png/1f626.png new file mode 100644 index 0000000..4587cf6 Binary files /dev/null and b/assets/images/emoji/png/1f626.png differ diff --git a/assets/images/emoji/png/1f627.png b/assets/images/emoji/png/1f627.png new file mode 100644 index 0000000..c8e6733 Binary files /dev/null and b/assets/images/emoji/png/1f627.png differ diff --git a/assets/images/emoji/png/1f628.png b/assets/images/emoji/png/1f628.png new file mode 100644 index 0000000..27709d0 Binary files /dev/null and b/assets/images/emoji/png/1f628.png differ diff --git a/assets/images/emoji/png/1f629.png b/assets/images/emoji/png/1f629.png new file mode 100644 index 0000000..465ccdf Binary files /dev/null and b/assets/images/emoji/png/1f629.png differ diff --git a/assets/images/emoji/png/1f62a.png b/assets/images/emoji/png/1f62a.png new file mode 100644 index 0000000..ad2dfec Binary files /dev/null and b/assets/images/emoji/png/1f62a.png differ diff --git a/assets/images/emoji/png/1f62b.png b/assets/images/emoji/png/1f62b.png new file mode 100644 index 0000000..a9b02cf Binary files /dev/null and b/assets/images/emoji/png/1f62b.png differ diff --git a/assets/images/emoji/png/1f62c.png b/assets/images/emoji/png/1f62c.png new file mode 100644 index 0000000..7f90796 Binary files /dev/null and b/assets/images/emoji/png/1f62c.png differ diff --git a/assets/images/emoji/png/1f62d.png b/assets/images/emoji/png/1f62d.png new file mode 100644 index 0000000..574110d Binary files /dev/null and b/assets/images/emoji/png/1f62d.png differ diff --git a/assets/images/emoji/png/1f62e.png b/assets/images/emoji/png/1f62e.png new file mode 100644 index 0000000..b78e2b1 Binary files /dev/null and b/assets/images/emoji/png/1f62e.png differ diff --git a/assets/images/emoji/png/1f62f.png b/assets/images/emoji/png/1f62f.png new file mode 100644 index 0000000..70ab9cc Binary files /dev/null and b/assets/images/emoji/png/1f62f.png differ diff --git a/assets/images/emoji/png/1f630.png b/assets/images/emoji/png/1f630.png new file mode 100644 index 0000000..263f803 Binary files /dev/null and b/assets/images/emoji/png/1f630.png differ diff --git a/assets/images/emoji/png/1f631.png b/assets/images/emoji/png/1f631.png new file mode 100644 index 0000000..d72d1a2 Binary files /dev/null and b/assets/images/emoji/png/1f631.png differ diff --git a/assets/images/emoji/png/1f632.png b/assets/images/emoji/png/1f632.png new file mode 100644 index 0000000..209abab Binary files /dev/null and b/assets/images/emoji/png/1f632.png differ diff --git a/assets/images/emoji/png/1f633.png b/assets/images/emoji/png/1f633.png new file mode 100644 index 0000000..72e76fa Binary files /dev/null and b/assets/images/emoji/png/1f633.png differ diff --git a/assets/images/emoji/png/1f634.png b/assets/images/emoji/png/1f634.png new file mode 100644 index 0000000..3cb76b8 Binary files /dev/null and b/assets/images/emoji/png/1f634.png differ diff --git a/assets/images/emoji/png/1f635.png b/assets/images/emoji/png/1f635.png new file mode 100644 index 0000000..ead8e90 Binary files /dev/null and b/assets/images/emoji/png/1f635.png differ diff --git a/assets/images/emoji/png/1f636.png b/assets/images/emoji/png/1f636.png new file mode 100644 index 0000000..72fed85 Binary files /dev/null and b/assets/images/emoji/png/1f636.png differ diff --git a/assets/images/emoji/png/1f637.png b/assets/images/emoji/png/1f637.png new file mode 100644 index 0000000..5de9cf9 Binary files /dev/null and b/assets/images/emoji/png/1f637.png differ diff --git a/assets/images/emoji/png/1f638.png b/assets/images/emoji/png/1f638.png new file mode 100644 index 0000000..d37a8c5 Binary files /dev/null and b/assets/images/emoji/png/1f638.png differ diff --git a/assets/images/emoji/png/1f639.png b/assets/images/emoji/png/1f639.png new file mode 100644 index 0000000..9f7aefe Binary files /dev/null and b/assets/images/emoji/png/1f639.png differ diff --git a/assets/images/emoji/png/1f640.png b/assets/images/emoji/png/1f640.png new file mode 100644 index 0000000..9133f76 Binary files /dev/null and b/assets/images/emoji/png/1f640.png differ diff --git a/assets/images/emoji/png/1f641.png b/assets/images/emoji/png/1f641.png new file mode 100644 index 0000000..4647a2f Binary files /dev/null and b/assets/images/emoji/png/1f641.png differ diff --git a/assets/images/emoji/png/1f642.png b/assets/images/emoji/png/1f642.png new file mode 100644 index 0000000..1187630 Binary files /dev/null and b/assets/images/emoji/png/1f642.png differ diff --git a/assets/images/emoji/png/1f643.png b/assets/images/emoji/png/1f643.png new file mode 100644 index 0000000..9515e6f Binary files /dev/null and b/assets/images/emoji/png/1f643.png differ diff --git a/assets/images/emoji/png/1f644.png b/assets/images/emoji/png/1f644.png new file mode 100644 index 0000000..2782fd0 Binary files /dev/null and b/assets/images/emoji/png/1f644.png differ diff --git a/assets/images/emoji/png/1f910.png b/assets/images/emoji/png/1f910.png new file mode 100644 index 0000000..2ddaf45 Binary files /dev/null and b/assets/images/emoji/png/1f910.png differ diff --git a/assets/images/emoji/png/1f911.png b/assets/images/emoji/png/1f911.png new file mode 100644 index 0000000..3b812a1 Binary files /dev/null and b/assets/images/emoji/png/1f911.png differ diff --git a/assets/images/emoji/png/1f912.png b/assets/images/emoji/png/1f912.png new file mode 100644 index 0000000..caa9677 Binary files /dev/null and b/assets/images/emoji/png/1f912.png differ diff --git a/assets/images/emoji/png/1f913.png b/assets/images/emoji/png/1f913.png new file mode 100644 index 0000000..87344a9 Binary files /dev/null and b/assets/images/emoji/png/1f913.png differ diff --git a/assets/images/emoji/png/1f914.png b/assets/images/emoji/png/1f914.png new file mode 100644 index 0000000..4697768 Binary files /dev/null and b/assets/images/emoji/png/1f914.png differ diff --git a/assets/images/emoji/png/1f915.png b/assets/images/emoji/png/1f915.png new file mode 100644 index 0000000..e88b489 Binary files /dev/null and b/assets/images/emoji/png/1f915.png differ diff --git a/assets/images/emoji/png/1f916.png b/assets/images/emoji/png/1f916.png new file mode 100644 index 0000000..80ea471 Binary files /dev/null and b/assets/images/emoji/png/1f916.png differ diff --git a/assets/images/emoji/png/1f917.png b/assets/images/emoji/png/1f917.png new file mode 100644 index 0000000..cb26c2c Binary files /dev/null and b/assets/images/emoji/png/1f917.png differ diff --git a/assets/images/emoji/svg/1f600.svg b/assets/images/emoji/svg/1f600.svg new file mode 100755 index 0000000..d1d05c7 --- /dev/null +++ b/assets/images/emoji/svg/1f600.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f601.svg b/assets/images/emoji/svg/1f601.svg new file mode 100755 index 0000000..4508211 --- /dev/null +++ b/assets/images/emoji/svg/1f601.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f602.svg b/assets/images/emoji/svg/1f602.svg new file mode 100755 index 0000000..5c4b086 --- /dev/null +++ b/assets/images/emoji/svg/1f602.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f603.svg b/assets/images/emoji/svg/1f603.svg new file mode 100755 index 0000000..2a26280 --- /dev/null +++ b/assets/images/emoji/svg/1f603.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f604.svg b/assets/images/emoji/svg/1f604.svg new file mode 100755 index 0000000..047f4e1 --- /dev/null +++ b/assets/images/emoji/svg/1f604.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f605.svg b/assets/images/emoji/svg/1f605.svg new file mode 100755 index 0000000..66a0724 --- /dev/null +++ b/assets/images/emoji/svg/1f605.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f606.svg b/assets/images/emoji/svg/1f606.svg new file mode 100755 index 0000000..551cb14 --- /dev/null +++ b/assets/images/emoji/svg/1f606.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f607.svg b/assets/images/emoji/svg/1f607.svg new file mode 100755 index 0000000..ea77fb6 --- /dev/null +++ b/assets/images/emoji/svg/1f607.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f608.svg b/assets/images/emoji/svg/1f608.svg new file mode 100755 index 0000000..27bd712 --- /dev/null +++ b/assets/images/emoji/svg/1f608.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f609.svg b/assets/images/emoji/svg/1f609.svg new file mode 100755 index 0000000..f596fb8 --- /dev/null +++ b/assets/images/emoji/svg/1f609.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f60a.svg b/assets/images/emoji/svg/1f60a.svg new file mode 100755 index 0000000..3b884ac --- /dev/null +++ b/assets/images/emoji/svg/1f60a.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f60b.svg b/assets/images/emoji/svg/1f60b.svg new file mode 100755 index 0000000..713c0fc --- /dev/null +++ b/assets/images/emoji/svg/1f60b.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f60c.svg b/assets/images/emoji/svg/1f60c.svg new file mode 100755 index 0000000..1965287 --- /dev/null +++ b/assets/images/emoji/svg/1f60c.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f60d.svg b/assets/images/emoji/svg/1f60d.svg new file mode 100755 index 0000000..e05ebcc --- /dev/null +++ b/assets/images/emoji/svg/1f60d.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f60e.svg b/assets/images/emoji/svg/1f60e.svg new file mode 100755 index 0000000..8306b98 --- /dev/null +++ b/assets/images/emoji/svg/1f60e.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f60f.svg b/assets/images/emoji/svg/1f60f.svg new file mode 100755 index 0000000..94a9c61 --- /dev/null +++ b/assets/images/emoji/svg/1f60f.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f610.svg b/assets/images/emoji/svg/1f610.svg new file mode 100755 index 0000000..5884158 --- /dev/null +++ b/assets/images/emoji/svg/1f610.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f611.svg b/assets/images/emoji/svg/1f611.svg new file mode 100755 index 0000000..f0d6b9c --- /dev/null +++ b/assets/images/emoji/svg/1f611.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f612.svg b/assets/images/emoji/svg/1f612.svg new file mode 100755 index 0000000..214ef7f --- /dev/null +++ b/assets/images/emoji/svg/1f612.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f613.svg b/assets/images/emoji/svg/1f613.svg new file mode 100755 index 0000000..994b9b6 --- /dev/null +++ b/assets/images/emoji/svg/1f613.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f614.svg b/assets/images/emoji/svg/1f614.svg new file mode 100755 index 0000000..6ff03c5 --- /dev/null +++ b/assets/images/emoji/svg/1f614.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f615.svg b/assets/images/emoji/svg/1f615.svg new file mode 100755 index 0000000..6e95232 --- /dev/null +++ b/assets/images/emoji/svg/1f615.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f616.svg b/assets/images/emoji/svg/1f616.svg new file mode 100755 index 0000000..32aa8c9 --- /dev/null +++ b/assets/images/emoji/svg/1f616.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f617.svg b/assets/images/emoji/svg/1f617.svg new file mode 100755 index 0000000..3c7642c --- /dev/null +++ b/assets/images/emoji/svg/1f617.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f618.svg b/assets/images/emoji/svg/1f618.svg new file mode 100755 index 0000000..9825701 --- /dev/null +++ b/assets/images/emoji/svg/1f618.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f619.svg b/assets/images/emoji/svg/1f619.svg new file mode 100755 index 0000000..06efa19 --- /dev/null +++ b/assets/images/emoji/svg/1f619.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f61a.svg b/assets/images/emoji/svg/1f61a.svg new file mode 100755 index 0000000..41b66cb --- /dev/null +++ b/assets/images/emoji/svg/1f61a.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f61b.svg b/assets/images/emoji/svg/1f61b.svg new file mode 100755 index 0000000..4431bef --- /dev/null +++ b/assets/images/emoji/svg/1f61b.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f61c.svg b/assets/images/emoji/svg/1f61c.svg new file mode 100755 index 0000000..e291d3c --- /dev/null +++ b/assets/images/emoji/svg/1f61c.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f61d.svg b/assets/images/emoji/svg/1f61d.svg new file mode 100755 index 0000000..57b9d38 --- /dev/null +++ b/assets/images/emoji/svg/1f61d.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f61e.svg b/assets/images/emoji/svg/1f61e.svg new file mode 100755 index 0000000..1ab9fbc --- /dev/null +++ b/assets/images/emoji/svg/1f61e.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f61f.svg b/assets/images/emoji/svg/1f61f.svg new file mode 100755 index 0000000..12a3af0 --- /dev/null +++ b/assets/images/emoji/svg/1f61f.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f620.svg b/assets/images/emoji/svg/1f620.svg new file mode 100755 index 0000000..5acf333 --- /dev/null +++ b/assets/images/emoji/svg/1f620.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f621.svg b/assets/images/emoji/svg/1f621.svg new file mode 100755 index 0000000..a8c8e2a --- /dev/null +++ b/assets/images/emoji/svg/1f621.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f622.svg b/assets/images/emoji/svg/1f622.svg new file mode 100755 index 0000000..b40a671 --- /dev/null +++ b/assets/images/emoji/svg/1f622.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f623.svg b/assets/images/emoji/svg/1f623.svg new file mode 100755 index 0000000..070964e --- /dev/null +++ b/assets/images/emoji/svg/1f623.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f624.svg b/assets/images/emoji/svg/1f624.svg new file mode 100755 index 0000000..4c1ef04 --- /dev/null +++ b/assets/images/emoji/svg/1f624.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f625.svg b/assets/images/emoji/svg/1f625.svg new file mode 100755 index 0000000..3194fa0 --- /dev/null +++ b/assets/images/emoji/svg/1f625.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f626.svg b/assets/images/emoji/svg/1f626.svg new file mode 100755 index 0000000..bae8cd6 --- /dev/null +++ b/assets/images/emoji/svg/1f626.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f627.svg b/assets/images/emoji/svg/1f627.svg new file mode 100755 index 0000000..c8e5812 --- /dev/null +++ b/assets/images/emoji/svg/1f627.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f628.svg b/assets/images/emoji/svg/1f628.svg new file mode 100755 index 0000000..dcf7548 --- /dev/null +++ b/assets/images/emoji/svg/1f628.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f629.svg b/assets/images/emoji/svg/1f629.svg new file mode 100755 index 0000000..a169e56 --- /dev/null +++ b/assets/images/emoji/svg/1f629.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f62a.svg b/assets/images/emoji/svg/1f62a.svg new file mode 100755 index 0000000..c74fa3e --- /dev/null +++ b/assets/images/emoji/svg/1f62a.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f62b.svg b/assets/images/emoji/svg/1f62b.svg new file mode 100755 index 0000000..13d66fa --- /dev/null +++ b/assets/images/emoji/svg/1f62b.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f62c.svg b/assets/images/emoji/svg/1f62c.svg new file mode 100755 index 0000000..ace1c3c --- /dev/null +++ b/assets/images/emoji/svg/1f62c.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f62d.svg b/assets/images/emoji/svg/1f62d.svg new file mode 100755 index 0000000..ddffc32 --- /dev/null +++ b/assets/images/emoji/svg/1f62d.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f62e.svg b/assets/images/emoji/svg/1f62e.svg new file mode 100755 index 0000000..88fdd32 --- /dev/null +++ b/assets/images/emoji/svg/1f62e.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f62f.svg b/assets/images/emoji/svg/1f62f.svg new file mode 100755 index 0000000..895b15c --- /dev/null +++ b/assets/images/emoji/svg/1f62f.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f630.svg b/assets/images/emoji/svg/1f630.svg new file mode 100755 index 0000000..d68e2ba --- /dev/null +++ b/assets/images/emoji/svg/1f630.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f631.svg b/assets/images/emoji/svg/1f631.svg new file mode 100755 index 0000000..b5f772e --- /dev/null +++ b/assets/images/emoji/svg/1f631.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f632.svg b/assets/images/emoji/svg/1f632.svg new file mode 100755 index 0000000..58f83d3 --- /dev/null +++ b/assets/images/emoji/svg/1f632.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f633.svg b/assets/images/emoji/svg/1f633.svg new file mode 100755 index 0000000..cb21ceb --- /dev/null +++ b/assets/images/emoji/svg/1f633.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f634.svg b/assets/images/emoji/svg/1f634.svg new file mode 100755 index 0000000..408ebe2 --- /dev/null +++ b/assets/images/emoji/svg/1f634.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f635.svg b/assets/images/emoji/svg/1f635.svg new file mode 100755 index 0000000..3ed3525 --- /dev/null +++ b/assets/images/emoji/svg/1f635.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f636.svg b/assets/images/emoji/svg/1f636.svg new file mode 100755 index 0000000..6a07bac --- /dev/null +++ b/assets/images/emoji/svg/1f636.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f637.svg b/assets/images/emoji/svg/1f637.svg new file mode 100755 index 0000000..80a2c6c --- /dev/null +++ b/assets/images/emoji/svg/1f637.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f638.svg b/assets/images/emoji/svg/1f638.svg new file mode 100755 index 0000000..f92e756 --- /dev/null +++ b/assets/images/emoji/svg/1f638.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f639.svg b/assets/images/emoji/svg/1f639.svg new file mode 100755 index 0000000..86b16f3 --- /dev/null +++ b/assets/images/emoji/svg/1f639.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f640.svg b/assets/images/emoji/svg/1f640.svg new file mode 100755 index 0000000..42210ac --- /dev/null +++ b/assets/images/emoji/svg/1f640.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f641.svg b/assets/images/emoji/svg/1f641.svg new file mode 100755 index 0000000..1beb89c --- /dev/null +++ b/assets/images/emoji/svg/1f641.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f642.svg b/assets/images/emoji/svg/1f642.svg new file mode 100755 index 0000000..23b1e7e --- /dev/null +++ b/assets/images/emoji/svg/1f642.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f643.svg b/assets/images/emoji/svg/1f643.svg new file mode 100755 index 0000000..fc78562 --- /dev/null +++ b/assets/images/emoji/svg/1f643.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f644.svg b/assets/images/emoji/svg/1f644.svg new file mode 100755 index 0000000..94c7269 --- /dev/null +++ b/assets/images/emoji/svg/1f644.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f910.svg b/assets/images/emoji/svg/1f910.svg new file mode 100755 index 0000000..2c2e27b --- /dev/null +++ b/assets/images/emoji/svg/1f910.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f911.svg b/assets/images/emoji/svg/1f911.svg new file mode 100755 index 0000000..9c47904 --- /dev/null +++ b/assets/images/emoji/svg/1f911.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f912.svg b/assets/images/emoji/svg/1f912.svg new file mode 100755 index 0000000..dcb6ea7 --- /dev/null +++ b/assets/images/emoji/svg/1f912.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f913.svg b/assets/images/emoji/svg/1f913.svg new file mode 100755 index 0000000..c6ea98b --- /dev/null +++ b/assets/images/emoji/svg/1f913.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f914.svg b/assets/images/emoji/svg/1f914.svg new file mode 100755 index 0000000..4ff8721 --- /dev/null +++ b/assets/images/emoji/svg/1f914.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f915.svg b/assets/images/emoji/svg/1f915.svg new file mode 100755 index 0000000..d40a8a4 --- /dev/null +++ b/assets/images/emoji/svg/1f915.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f916.svg b/assets/images/emoji/svg/1f916.svg new file mode 100755 index 0000000..ec03572 --- /dev/null +++ b/assets/images/emoji/svg/1f916.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/emoji/svg/1f917.svg b/assets/images/emoji/svg/1f917.svg new file mode 100755 index 0000000..505de9e --- /dev/null +++ b/assets/images/emoji/svg/1f917.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/loader.gif b/assets/images/loader.gif new file mode 100644 index 0000000..c48e97e Binary files /dev/null and b/assets/images/loader.gif differ diff --git a/assets/images/loading.gif b/assets/images/loading.gif new file mode 100644 index 0000000..5087c2a Binary files /dev/null and b/assets/images/loading.gif differ diff --git a/assets/images/next.png b/assets/images/next.png new file mode 100644 index 0000000..08365ac Binary files /dev/null and b/assets/images/next.png differ diff --git a/assets/images/noimage.jpg b/assets/images/noimage.jpg new file mode 100644 index 0000000..ab399d5 Binary files /dev/null and b/assets/images/noimage.jpg differ diff --git a/assets/images/nophoto.jpg b/assets/images/nophoto.jpg new file mode 100644 index 0000000..f7cfe24 Binary files /dev/null and b/assets/images/nophoto.jpg differ diff --git a/assets/images/prev.png b/assets/images/prev.png new file mode 100644 index 0000000..329fa98 Binary files /dev/null and b/assets/images/prev.png differ diff --git a/assets/images/zira.png b/assets/images/zira.png new file mode 100644 index 0000000..074a9e9 Binary files /dev/null and b/assets/images/zira.png differ diff --git a/assets/js/autocomplete.js b/assets/js/autocomplete.js new file mode 100644 index 0000000..6ba079a --- /dev/null +++ b/assets/js/autocomplete.js @@ -0,0 +1,171 @@ +(function($) { + $(document).ready(function () { + $('.container #content').on('keyup', '.form-input-autocomplete', zira_autocomplete); + $('.container #content').on('focus', '.form-input-autocomplete', zira_autocomplete_focus); + $('.container #content .form-input-autocomplete').attr('autocomplete','off'); + }); + + zira_autocomplete = function(e) { + if (typeof(e)!="undefined") { + if (e.keyCode == 13) { + e.stopPropagation(); + e.preventDefault(); + } + if (e.keyCode == 37 || e.keyCode == 38 || e.keyCode == 39 || e.keyCode == 40 || e.keyCode == 13) return; + } + + if (typeof(zira_autocomplete.inprogress)!="undefined" && zira_autocomplete.inprogress) return; + try { + window.clearTimeout(zira_autocomplete.timer); + } catch(err) {} + if (typeof(zira_autocomplete.text)!="undefined" && zira_autocomplete.text==$(this).val() && + typeof(zira_autocomplete.url)!="undefined" && zira_autocomplete.url==$(this).data('url') && + typeof(zira_autocomplete.token)!="undefined" && zira_autocomplete.token==$(this).data('token') && + typeof(zira_autocomplete.items)!="undefined" + ) { + zira_autocomplete_open.call(this, zira_autocomplete.items); + return; + } + zira_autocomplete.token = $(this).data('token'); + zira_autocomplete.url = $(this).data('url'); + zira_autocomplete.text = $(this).val(); + if (zira_autocomplete.text.length==0 || + typeof(zira_autocomplete.url)=="undefined" || + typeof(zira_autocomplete.token)=="undefined" + ) { + zira_autocomplete_close.call(this); + return; + } + if (typeof(zira_autocomplete.iterator)=="undefined") { + zira_autocomplete.iterator = 0; + } + var delay = 250; + if (zira_autocomplete.iterator >= 5) delay = 500; + if (zira_autocomplete.iterator >= 10) delay = 1000; + zira_autocomplete.timer = window.setTimeout(zira_bind(this, function(){ + zira_autocomplete.inprogress = true; + zira_autocomplete.iterator++; + $.post(zira_autocomplete.url,{ + 'text': zira_autocomplete.text, + 'token': zira_autocomplete.token + },zira_bind(this, function(response){ + zira_autocomplete.inprogress = false; + if (!response) return; + if (typeof(response.error)!="undefined") { + zira_error(response.error); + } else if (typeof(response.items)!="undefined") { + zira_autocomplete.items = response.items; + zira_autocomplete_open.call(this, response.items); + } + if ($(this).val() != zira_autocomplete.text) { + zira_autocomplete.call(this); + } + }),'json'); + }), delay); + + $(this).data('autocomplete_id',null); + $(this).data('autocomplete_text',null); + }; + + zira_autocomplete_focus = function() { + if (typeof(zira_autocomplete.inprogress)!="undefined" && zira_autocomplete.inprogress) return; + if (typeof(zira_autocomplete.text)!="undefined" && zira_autocomplete.text==$(this).val() && + typeof(zira_autocomplete.url)!="undefined" && zira_autocomplete.url==$(this).data('url') && + typeof(zira_autocomplete.token)!="undefined" && zira_autocomplete.token==$(this).data('token') && + typeof(zira_autocomplete.items)!="undefined" + ) { + zira_autocomplete_open.call(this, zira_autocomplete.items); + } + }; + + zira_autocomplete_open = function(items) { + zira_autocomplete_close.call(this); + $('body').append(''); + for (var i in items) { + $('.zira-autocomplete-wnd').append('
  • '+items[i]+'
  • '); + } + $('.zira-autocomplete-wnd').css({ + 'position': 'absolute', + 'top': $(this).offset().top + $(this).outerHeight(), + 'left': $(this).offset().left + }); + zira_autocomplete_click.input = this; + $('body').mousedown(zira_autocomplete_click); + $('body').keyup(zira_autocomplete_press); + $('.zira-autocomplete-wnd a').click(zira_autocomplete_select); + $(this).parents('form').submit(zira_autocomplete_prevent_submit); + }; + + zira_autocomplete_close = function() { + $('.zira-autocomplete-wnd').remove(); + $('body').unbind('click',zira_autocomplete_click); + $('body').unbind('keyup',zira_autocomplete_press); + $(this).parents('form').unbind('submit',zira_autocomplete_prevent_submit); + }; + + zira_autocomplete_click = function(e) { + if (typeof(e.originalEvent)=="undefined" || typeof(e.originalEvent.target)=="undefined") return; + if ($(e.originalEvent.target).parents('.zira-autocomplete-wnd').length==0 && + !$(e.originalEvent.target).is(zira_autocomplete_click.input) + ) { + zira_autocomplete_close.call(zira_autocomplete_click.input); + } + }; + + zira_autocomplete_select = function(e) { + var text = $(this).text(); + var id = $(this).data('id'); + $(zira_autocomplete_click.input).val(text); + $(zira_autocomplete_click.input).data('autocomplete_id',id); + $(zira_autocomplete_click.input).data('autocomplete_text',text); + zira_autocomplete_close.call(zira_autocomplete_click.input); + }; + + zira_autocomplete_press = function(e) { + if (e.keyCode == 40) { // arrow down + e.stopPropagation(); + e.preventDefault(); + var active = $('.zira-autocomplete-wnd li a.active'); + if ($(active).length==0) { + $('.zira-autocomplete-wnd li:first-child a').addClass('active'); + } else { + $(active).removeClass('active'); + var next = $(active).parent('li').next('li'); + if ($(next).length==0) { + $('.zira-autocomplete-wnd li:first-child a').addClass('active'); + } else { + $(next).children('a').addClass('active'); + } + } + } else if (e.keyCode == 38) { // arrow up + e.stopPropagation(); + e.preventDefault(); + var active = $('.zira-autocomplete-wnd li a.active'); + if ($(active).length==0) { + $('.zira-autocomplete-wnd li:last-child a').addClass('active'); + } else { + $(active).removeClass('active'); + var prev = $(active).parent('li').prev('li'); + if ($(prev).length==0) { + $('.zira-autocomplete-wnd li:last-child a').addClass('active'); + } else { + $(prev).children('a').addClass('active'); + } + } + } else if (e.keyCode == 13 || e.keyCode == 39) { // enter or arrow right + var active = $('.zira-autocomplete-wnd li a.active'); + if ($(active).length!=0) { + e.stopPropagation(); + e.preventDefault(); + zira_autocomplete_select.call($(active)); + } + } + }; + + zira_autocomplete_prevent_submit = function(e) { + e.stopPropagation(); + e.preventDefault(); + e.keyCode = 13; + zira_autocomplete_press.call(this, e); + }; +})(jQuery); \ No newline at end of file diff --git a/assets/js/bootstrap-datetimepicker.min.js b/assets/js/bootstrap-datetimepicker.min.js new file mode 100644 index 0000000..db3d085 --- /dev/null +++ b/assets/js/bootstrap-datetimepicker.min.js @@ -0,0 +1,9 @@ +/*! version : 4.17.37 + ========================================================= + bootstrap-datetimejs + https://github.com/Eonasdan/bootstrap-datetimepicker + Copyright (c) 2015 Jonathan Peterson + ========================================================= + */ +!function(a){"use strict";if("function"==typeof define&&define.amd)define(["jquery","moment"],a);else if("object"==typeof exports)a(require("jquery"),require("moment"));else{if("undefined"==typeof jQuery)throw"bootstrap-datetimepicker requires jQuery to be loaded first";if("undefined"==typeof moment)throw"bootstrap-datetimepicker requires Moment.js to be loaded first";a(jQuery,moment)}}(function(a,b){"use strict";if(!b)throw new Error("bootstrap-datetimepicker requires Moment.js to be loaded first");var c=function(c,d){var e,f,g,h,i,j,k,l={},m=!0,n=!1,o=!1,p=0,q=[{clsName:"days",navFnc:"M",navStep:1},{clsName:"months",navFnc:"y",navStep:1},{clsName:"years",navFnc:"y",navStep:10},{clsName:"decades",navFnc:"y",navStep:100}],r=["days","months","years","decades"],s=["top","bottom","auto"],t=["left","right","auto"],u=["default","top","bottom"],v={up:38,38:"up",down:40,40:"down",left:37,37:"left",right:39,39:"right",tab:9,9:"tab",escape:27,27:"escape",enter:13,13:"enter",pageUp:33,33:"pageUp",pageDown:34,34:"pageDown",shift:16,16:"shift",control:17,17:"control",space:32,32:"space",t:84,84:"t","delete":46,46:"delete"},w={},x=function(a){var c,e,f,g,h,i=!1;return void 0!==b.tz&&void 0!==d.timeZone&&null!==d.timeZone&&""!==d.timeZone&&(i=!0),void 0===a||null===a?c=i?b().tz(d.timeZone).startOf("d"):b().startOf("d"):i?(e=b().tz(d.timeZone).utcOffset(),f=b(a,j,d.useStrict).utcOffset(),f!==e?(g=b().tz(d.timeZone).format("Z"),h=b(a,j,d.useStrict).format("YYYY-MM-DD[T]HH:mm:ss")+g,c=b(h,j,d.useStrict).tz(d.timeZone)):c=b(a,j,d.useStrict).tz(d.timeZone)):c=b(a,j,d.useStrict),c},y=function(a){if("string"!=typeof a||a.length>1)throw new TypeError("isEnabled expects a single character string parameter");switch(a){case"y":return-1!==i.indexOf("Y");case"M":return-1!==i.indexOf("M");case"d":return-1!==i.toLowerCase().indexOf("d");case"h":case"H":return-1!==i.toLowerCase().indexOf("h");case"m":return-1!==i.indexOf("m");case"s":return-1!==i.indexOf("s");default:return!1}},z=function(){return y("h")||y("m")||y("s")},A=function(){return y("y")||y("M")||y("d")},B=function(){var b=a("").append(a("").append(a("").addClass("prev").attr("data-action","previous").append(a("").addClass(d.icons.previous))).append(a("").addClass("picker-switch").attr("data-action","pickerSwitch").attr("colspan",d.calendarWeeks?"6":"5")).append(a("").addClass("next").attr("data-action","next").append(a("").addClass(d.icons.next)))),c=a("").append(a("").append(a("").attr("colspan",d.calendarWeeks?"8":"7")));return[a("
    ").addClass("datepicker-days").append(a("").addClass("table-condensed").append(b).append(a(""))),a("
    ").addClass("datepicker-months").append(a("
    ").addClass("table-condensed").append(b.clone()).append(c.clone())),a("
    ").addClass("datepicker-years").append(a("
    ").addClass("table-condensed").append(b.clone()).append(c.clone())),a("
    ").addClass("datepicker-decades").append(a("
    ").addClass("table-condensed").append(b.clone()).append(c.clone()))]},C=function(){var b=a(""),c=a(""),e=a("");return y("h")&&(b.append(a(""}var d,e,f,g,h,k,l,m=this,n=m._id,o=0;for(d=c(),d.push({text:tinymce.translate("No color"),color:"transparent"}),f='
    ").append(a("").attr({href:"#",tabindex:"-1",title:d.tooltips.incrementHour}).addClass("btn").attr("data-action","incrementHours").append(a("").addClass(d.icons.up)))),c.append(a("").append(a("").addClass("timepicker-hour").attr({"data-time-component":"hours",title:d.tooltips.pickHour}).attr("data-action","showHours"))),e.append(a("").append(a("").attr({href:"#",tabindex:"-1",title:d.tooltips.decrementHour}).addClass("btn").attr("data-action","decrementHours").append(a("").addClass(d.icons.down))))),y("m")&&(y("h")&&(b.append(a("").addClass("separator")),c.append(a("").addClass("separator").html(":")),e.append(a("").addClass("separator"))),b.append(a("").append(a("").attr({href:"#",tabindex:"-1",title:d.tooltips.incrementMinute}).addClass("btn").attr("data-action","incrementMinutes").append(a("").addClass(d.icons.up)))),c.append(a("").append(a("").addClass("timepicker-minute").attr({"data-time-component":"minutes",title:d.tooltips.pickMinute}).attr("data-action","showMinutes"))),e.append(a("").append(a("").attr({href:"#",tabindex:"-1",title:d.tooltips.decrementMinute}).addClass("btn").attr("data-action","decrementMinutes").append(a("").addClass(d.icons.down))))),y("s")&&(y("m")&&(b.append(a("").addClass("separator")),c.append(a("").addClass("separator").html(":")),e.append(a("").addClass("separator"))),b.append(a("").append(a("").attr({href:"#",tabindex:"-1",title:d.tooltips.incrementSecond}).addClass("btn").attr("data-action","incrementSeconds").append(a("").addClass(d.icons.up)))),c.append(a("").append(a("").addClass("timepicker-second").attr({"data-time-component":"seconds",title:d.tooltips.pickSecond}).attr("data-action","showSeconds"))),e.append(a("").append(a("").attr({href:"#",tabindex:"-1",title:d.tooltips.decrementSecond}).addClass("btn").attr("data-action","decrementSeconds").append(a("").addClass(d.icons.down))))),h||(b.append(a("").addClass("separator")),c.append(a("").append(a("").addClass("separator"))),a("
    ").addClass("timepicker-picker").append(a("").addClass("table-condensed").append([b,c,e]))},D=function(){var b=a("
    ").addClass("timepicker-hours").append(a("
    ").addClass("table-condensed")),c=a("
    ").addClass("timepicker-minutes").append(a("
    ").addClass("table-condensed")),d=a("
    ").addClass("timepicker-seconds").append(a("
    ").addClass("table-condensed")),e=[C()];return y("h")&&e.push(b),y("m")&&e.push(c),y("s")&&e.push(d),e},E=function(){var b=[];return d.showTodayButton&&b.push(a("\s*$/g,ra={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"
    ").append(a("").attr({"data-action":"today",title:d.tooltips.today}).append(a("").addClass(d.icons.today)))),!d.sideBySide&&A()&&z()&&b.push(a("").append(a("").attr({"data-action":"togglePicker",title:d.tooltips.selectTime}).append(a("").addClass(d.icons.time)))),d.showClear&&b.push(a("").append(a("").attr({"data-action":"clear",title:d.tooltips.clear}).append(a("").addClass(d.icons.clear)))),d.showClose&&b.push(a("").append(a("").attr({"data-action":"close",title:d.tooltips.close}).append(a("").addClass(d.icons.close)))),a("").addClass("table-condensed").append(a("").append(a("").append(b)))},F=function(){var b=a("
    ").addClass("bootstrap-datetimepicker-widget dropdown-menu"),c=a("
    ").addClass("datepicker").append(B()),e=a("
    ").addClass("timepicker").append(D()),f=a("
      ").addClass("list-unstyled"),g=a("
    • ").addClass("picker-switch"+(d.collapse?" accordion-toggle":"")).append(E());return d.inline&&b.removeClass("dropdown-menu"),h&&b.addClass("usetwentyfour"),y("s")&&!h&&b.addClass("wider"),d.sideBySide&&A()&&z()?(b.addClass("timepicker-sbs"),"top"===d.toolbarPlacement&&b.append(g),b.append(a("
      ").addClass("row").append(c.addClass("col-md-6")).append(e.addClass("col-md-6"))),"bottom"===d.toolbarPlacement&&b.append(g),b):("top"===d.toolbarPlacement&&f.append(g),A()&&f.append(a("
    • ").addClass(d.collapse&&z()?"collapse in":"").append(c)),"default"===d.toolbarPlacement&&f.append(g),z()&&f.append(a("
    • ").addClass(d.collapse&&A()?"collapse":"").append(e)),"bottom"===d.toolbarPlacement&&f.append(g),b.append(f))},G=function(){var b,e={};return b=c.is("input")||d.inline?c.data():c.find("input").data(),b.dateOptions&&b.dateOptions instanceof Object&&(e=a.extend(!0,e,b.dateOptions)),a.each(d,function(a){var c="date"+a.charAt(0).toUpperCase()+a.slice(1);void 0!==b[c]&&(e[a]=b[c])}),e},H=function(){var b,e=(n||c).position(),f=(n||c).offset(),g=d.widgetPositioning.vertical,h=d.widgetPositioning.horizontal;if(d.widgetParent)b=d.widgetParent.append(o);else if(c.is("input"))b=c.after(o).parent();else{if(d.inline)return void(b=c.append(o));b=c,c.children().first().after(o)}if("auto"===g&&(g=f.top+1.5*o.height()>=a(window).height()+a(window).scrollTop()&&o.height()+c.outerHeight()a(window).width()?"right":"left"),"top"===g?o.addClass("top").removeClass("bottom"):o.addClass("bottom").removeClass("top"),"right"===h?o.addClass("pull-right"):o.removeClass("pull-right"),"relative"!==b.css("position")&&(b=b.parents().filter(function(){return"relative"===a(this).css("position")}).first()),0===b.length)throw new Error("datetimepicker component should be placed within a relative positioned container");o.css({top:"top"===g?"auto":e.top+c.outerHeight(),bottom:"top"===g?e.top+c.outerHeight():"auto",left:"left"===h?b===c?0:e.left:"auto",right:"left"===h?"auto":b.outerWidth()-c.outerWidth()-(b===c?0:e.left)})},I=function(a){"dp.change"===a.type&&(a.date&&a.date.isSame(a.oldDate)||!a.date&&!a.oldDate)||c.trigger(a)},J=function(a){"y"===a&&(a="YYYY"),I({type:"dp.update",change:a,viewDate:f.clone()})},K=function(a){o&&(a&&(k=Math.max(p,Math.min(3,k+a))),o.find(".datepicker > div").hide().filter(".datepicker-"+q[k].clsName).show())},L=function(){var b=a("
    "),c=f.clone().startOf("w").startOf("d");for(d.calendarWeeks===!0&&b.append(a(""),d.calendarWeeks&&c.append('"),k.push(c)),g="",b.isBefore(f,"M")&&(g+=" old"),b.isAfter(f,"M")&&(g+=" new"),b.isSame(e,"d")&&!m&&(g+=" active"),Q(b,"d")||(g+=" disabled"),b.isSame(x(),"d")&&(g+=" today"),(0===b.day()||6===b.day())&&(g+=" weekend"),c.append('"),b.add(1,"d");i.find("tbody").empty().append(k),S(),T(),U()}},W=function(){var b=o.find(".timepicker-hours table"),c=f.clone().startOf("d"),d=[],e=a("");for(f.hour()>11&&!h&&c.hour(12);c.isSame(f,"d")&&(h||f.hour()<12&&c.hour()<12||f.hour()>11);)c.hour()%4===0&&(e=a(""),d.push(e)),e.append('"),c.add(1,"h");b.empty().append(d)},X=function(){for(var b=o.find(".timepicker-minutes table"),c=f.clone().startOf("h"),e=[],g=a(""),h=1===d.stepping?5:d.stepping;f.isSame(c,"h");)c.minute()%(4*h)===0&&(g=a(""),e.push(g)),g.append('"),c.add(h,"m");b.empty().append(e)},Y=function(){for(var b=o.find(".timepicker-seconds table"),c=f.clone().startOf("m"),d=[],e=a("");f.isSame(c,"m");)c.second()%20===0&&(e=a(""),d.push(e)),e.append('"),c.add(5,"s");b.empty().append(d)},Z=function(){var a,b,c=o.find(".timepicker span[data-time-component]");h||(a=o.find(".timepicker [data-action=togglePeriod]"),b=e.clone().add(e.hours()>=12?-12:12,"h"),a.text(e.format("A")),Q(b,"h")?a.removeClass("disabled"):a.addClass("disabled")),c.filter("[data-time-component=hours]").text(e.format(h?"HH":"hh")),c.filter("[data-time-component=minutes]").text(e.format("mm")),c.filter("[data-time-component=seconds]").text(e.format("ss")),W(),X(),Y()},$=function(){o&&(V(),Z())},_=function(a){var b=m?null:e;return a?(a=a.clone().locale(d.locale),1!==d.stepping&&a.minutes(Math.round(a.minutes()/d.stepping)*d.stepping%60).seconds(0),void(Q(a)?(e=a,f=e.clone(),g.val(e.format(i)),c.data("date",e.format(i)),m=!1,$(),I({type:"dp.change",date:e.clone(),oldDate:b})):(d.keepInvalid||g.val(m?"":e.format(i)),I({type:"dp.error",date:a})))):(m=!0,g.val(""),c.data("date",""),I({type:"dp.change",date:!1,oldDate:b}),void $())},aa=function(){var b=!1;return o?(o.find(".collapse").each(function(){var c=a(this).data("collapse");return c&&c.transitioning?(b=!0,!1):!0}),b?l:(n&&n.hasClass("btn")&&n.toggleClass("active"),o.hide(),a(window).off("resize",H),o.off("click","[data-action]"),o.off("mousedown",!1),o.remove(),o=!1,I({type:"dp.hide",date:e.clone()}),g.blur(),l)):l},ba=function(){_(null)},ca={next:function(){var a=q[k].navFnc;f.add(q[k].navStep,a),V(),J(a)},previous:function(){var a=q[k].navFnc;f.subtract(q[k].navStep,a),V(),J(a)},pickerSwitch:function(){K(1)},selectMonth:function(b){var c=a(b.target).closest("tbody").find("span").index(a(b.target));f.month(c),k===p?(_(e.clone().year(f.year()).month(f.month())),d.inline||aa()):(K(-1),V()),J("M")},selectYear:function(b){var c=parseInt(a(b.target).text(),10)||0;f.year(c),k===p?(_(e.clone().year(f.year())),d.inline||aa()):(K(-1),V()),J("YYYY")},selectDecade:function(b){var c=parseInt(a(b.target).data("selection"),10)||0;f.year(c),k===p?(_(e.clone().year(f.year())),d.inline||aa()):(K(-1),V()),J("YYYY")},selectDay:function(b){var c=f.clone();a(b.target).is(".old")&&c.subtract(1,"M"),a(b.target).is(".new")&&c.add(1,"M"),_(c.date(parseInt(a(b.target).text(),10))),z()||d.keepOpen||d.inline||aa()},incrementHours:function(){var a=e.clone().add(1,"h");Q(a,"h")&&_(a)},incrementMinutes:function(){var a=e.clone().add(d.stepping,"m");Q(a,"m")&&_(a)},incrementSeconds:function(){var a=e.clone().add(1,"s");Q(a,"s")&&_(a)},decrementHours:function(){var a=e.clone().subtract(1,"h");Q(a,"h")&&_(a)},decrementMinutes:function(){var a=e.clone().subtract(d.stepping,"m");Q(a,"m")&&_(a)},decrementSeconds:function(){var a=e.clone().subtract(1,"s");Q(a,"s")&&_(a)},togglePeriod:function(){_(e.clone().add(e.hours()>=12?-12:12,"h"))},togglePicker:function(b){var c,e=a(b.target),f=e.closest("ul"),g=f.find(".in"),h=f.find(".collapse:not(.in)");if(g&&g.length){if(c=g.data("collapse"),c&&c.transitioning)return;g.collapse?(g.collapse("hide"),h.collapse("show")):(g.removeClass("in"),h.addClass("in")),e.is("span")?e.toggleClass(d.icons.time+" "+d.icons.date):e.find("span").toggleClass(d.icons.time+" "+d.icons.date)}},showPicker:function(){o.find(".timepicker > div:not(.timepicker-picker)").hide(),o.find(".timepicker .timepicker-picker").show()},showHours:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-hours").show()},showMinutes:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-minutes").show()},showSeconds:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-seconds").show()},selectHour:function(b){var c=parseInt(a(b.target).text(),10);h||(e.hours()>=12?12!==c&&(c+=12):12===c&&(c=0)),_(e.clone().hours(c)),ca.showPicker.call(l)},selectMinute:function(b){_(e.clone().minutes(parseInt(a(b.target).text(),10))),ca.showPicker.call(l)},selectSecond:function(b){_(e.clone().seconds(parseInt(a(b.target).text(),10))),ca.showPicker.call(l)},clear:ba,today:function(){var a=x();Q(a,"d")&&_(a)},close:aa},da=function(b){return a(b.currentTarget).is(".disabled")?!1:(ca[a(b.currentTarget).data("action")].apply(l,arguments),!1)},ea=function(){var b,c={year:function(a){return a.month(0).date(1).hours(0).seconds(0).minutes(0)},month:function(a){return a.date(1).hours(0).seconds(0).minutes(0)},day:function(a){return a.hours(0).seconds(0).minutes(0)},hour:function(a){return a.seconds(0).minutes(0)},minute:function(a){return a.seconds(0)}};return g.prop("disabled")||!d.ignoreReadonly&&g.prop("readonly")||o?l:(void 0!==g.val()&&0!==g.val().trim().length?_(ga(g.val().trim())):d.useCurrent&&m&&(g.is("input")&&0===g.val().trim().length||d.inline)&&(b=x(),"string"==typeof d.useCurrent&&(b=c[d.useCurrent](b)),_(b)),o=F(),L(),R(),o.find(".timepicker-hours").hide(),o.find(".timepicker-minutes").hide(),o.find(".timepicker-seconds").hide(),$(),K(),a(window).on("resize",H),o.on("click","[data-action]",da),o.on("mousedown",!1),n&&n.hasClass("btn")&&n.toggleClass("active"),o.show(),H(),d.focusOnShow&&!g.is(":focus")&&g.focus(),I({type:"dp.show"}),l)},fa=function(){return o?aa():ea()},ga=function(a){return a=void 0===d.parseInputDate?b.isMoment(a)||a instanceof Date?b(a):x(a):d.parseInputDate(a),a.locale(d.locale),a},ha=function(a){var b,c,e,f,g=null,h=[],i={},j=a.which,k="p";w[j]=k;for(b in w)w.hasOwnProperty(b)&&w[b]===k&&(h.push(b),parseInt(b,10)!==j&&(i[b]=!0));for(b in d.keyBinds)if(d.keyBinds.hasOwnProperty(b)&&"function"==typeof d.keyBinds[b]&&(e=b.split(" "),e.length===h.length&&v[j]===e[e.length-1])){for(f=!0,c=e.length-2;c>=0;c--)if(!(v[e[c]]in i)){f=!1;break}if(f){g=d.keyBinds[b];break}}g&&(g.call(l,o),a.stopPropagation(),a.preventDefault())},ia=function(a){w[a.which]="r",a.stopPropagation(),a.preventDefault()},ja=function(b){var c=a(b.target).val().trim(),d=c?ga(c):null;return _(d),b.stopImmediatePropagation(),!1},ka=function(){g.on({change:ja,blur:d.debug?"":aa,keydown:ha,keyup:ia,focus:d.allowInputToggle?ea:""}),c.is("input")?g.on({focus:ea}):n&&(n.on("click",fa),n.on("mousedown",!1))},la=function(){g.off({change:ja,blur:blur,keydown:ha,keyup:ia,focus:d.allowInputToggle?aa:""}),c.is("input")?g.off({focus:ea}):n&&(n.off("click",fa),n.off("mousedown",!1))},ma=function(b){var c={};return a.each(b,function(){var a=ga(this);a.isValid()&&(c[a.format("YYYY-MM-DD")]=!0)}),Object.keys(c).length?c:!1},na=function(b){var c={};return a.each(b,function(){c[this]=!0}),Object.keys(c).length?c:!1},oa=function(){var a=d.format||"L LT";i=a.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,function(a){var b=e.localeData().longDateFormat(a)||a;return b.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,function(a){return e.localeData().longDateFormat(a)||a})}),j=d.extraFormats?d.extraFormats.slice():[],j.indexOf(a)<0&&j.indexOf(i)<0&&j.push(i),h=i.toLowerCase().indexOf("a")<1&&i.replace(/\[.*?\]/g,"").indexOf("h")<1,y("y")&&(p=2),y("M")&&(p=1),y("d")&&(p=0),k=Math.max(p,k),m||_(e)};if(l.destroy=function(){aa(),la(),c.removeData("DateTimePicker"),c.removeData("date")},l.toggle=fa,l.show=ea,l.hide=aa,l.disable=function(){return aa(),n&&n.hasClass("btn")&&n.addClass("disabled"),g.prop("disabled",!0),l},l.enable=function(){return n&&n.hasClass("btn")&&n.removeClass("disabled"),g.prop("disabled",!1),l},l.ignoreReadonly=function(a){if(0===arguments.length)return d.ignoreReadonly;if("boolean"!=typeof a)throw new TypeError("ignoreReadonly () expects a boolean parameter");return d.ignoreReadonly=a,l},l.options=function(b){if(0===arguments.length)return a.extend(!0,{},d);if(!(b instanceof Object))throw new TypeError("options() options parameter should be an object");return a.extend(!0,d,b),a.each(d,function(a,b){if(void 0===l[a])throw new TypeError("option "+a+" is not recognized!");l[a](b)}),l},l.date=function(a){if(0===arguments.length)return m?null:e.clone();if(!(null===a||"string"==typeof a||b.isMoment(a)||a instanceof Date))throw new TypeError("date() parameter must be one of [null, string, moment or Date]");return _(null===a?null:ga(a)),l},l.format=function(a){if(0===arguments.length)return d.format;if("string"!=typeof a&&("boolean"!=typeof a||a!==!1))throw new TypeError("format() expects a sting or boolean:false parameter "+a);return d.format=a,i&&oa(),l},l.timeZone=function(a){return 0===arguments.length?d.timeZone:(d.timeZone=a,l)},l.dayViewHeaderFormat=function(a){if(0===arguments.length)return d.dayViewHeaderFormat;if("string"!=typeof a)throw new TypeError("dayViewHeaderFormat() expects a string parameter");return d.dayViewHeaderFormat=a,l},l.extraFormats=function(a){if(0===arguments.length)return d.extraFormats;if(a!==!1&&!(a instanceof Array))throw new TypeError("extraFormats() expects an array or false parameter");return d.extraFormats=a,j&&oa(),l},l.disabledDates=function(b){if(0===arguments.length)return d.disabledDates?a.extend({},d.disabledDates):d.disabledDates;if(!b)return d.disabledDates=!1,$(),l;if(!(b instanceof Array))throw new TypeError("disabledDates() expects an array parameter");return d.disabledDates=ma(b),d.enabledDates=!1,$(),l},l.enabledDates=function(b){if(0===arguments.length)return d.enabledDates?a.extend({},d.enabledDates):d.enabledDates;if(!b)return d.enabledDates=!1,$(),l;if(!(b instanceof Array))throw new TypeError("enabledDates() expects an array parameter");return d.enabledDates=ma(b),d.disabledDates=!1,$(),l},l.daysOfWeekDisabled=function(a){if(0===arguments.length)return d.daysOfWeekDisabled.splice(0);if("boolean"==typeof a&&!a)return d.daysOfWeekDisabled=!1,$(),l;if(!(a instanceof Array))throw new TypeError("daysOfWeekDisabled() expects an array parameter");if(d.daysOfWeekDisabled=a.reduce(function(a,b){return b=parseInt(b,10),b>6||0>b||isNaN(b)?a:(-1===a.indexOf(b)&&a.push(b),a)},[]).sort(),d.useCurrent&&!d.keepInvalid){for(var b=0;!Q(e,"d");){if(e.add(1,"d"),7===b)throw"Tried 7 times to find a valid date";b++}_(e)}return $(),l},l.maxDate=function(a){if(0===arguments.length)return d.maxDate?d.maxDate.clone():d.maxDate;if("boolean"==typeof a&&a===!1)return d.maxDate=!1,$(),l;"string"==typeof a&&("now"===a||"moment"===a)&&(a=x());var b=ga(a);if(!b.isValid())throw new TypeError("maxDate() Could not parse date parameter: "+a);if(d.minDate&&b.isBefore(d.minDate))throw new TypeError("maxDate() date parameter is before options.minDate: "+b.format(i));return d.maxDate=b,d.useCurrent&&!d.keepInvalid&&e.isAfter(a)&&_(d.maxDate),f.isAfter(b)&&(f=b.clone().subtract(d.stepping,"m")),$(),l},l.minDate=function(a){if(0===arguments.length)return d.minDate?d.minDate.clone():d.minDate;if("boolean"==typeof a&&a===!1)return d.minDate=!1,$(),l;"string"==typeof a&&("now"===a||"moment"===a)&&(a=x());var b=ga(a);if(!b.isValid())throw new TypeError("minDate() Could not parse date parameter: "+a);if(d.maxDate&&b.isAfter(d.maxDate))throw new TypeError("minDate() date parameter is after options.maxDate: "+b.format(i));return d.minDate=b,d.useCurrent&&!d.keepInvalid&&e.isBefore(a)&&_(d.minDate),f.isBefore(b)&&(f=b.clone().add(d.stepping,"m")),$(),l},l.defaultDate=function(a){if(0===arguments.length)return d.defaultDate?d.defaultDate.clone():d.defaultDate;if(!a)return d.defaultDate=!1,l;"string"==typeof a&&("now"===a||"moment"===a)&&(a=x());var b=ga(a);if(!b.isValid())throw new TypeError("defaultDate() Could not parse date parameter: "+a);if(!Q(b))throw new TypeError("defaultDate() date passed is invalid according to component setup validations");return d.defaultDate=b,(d.defaultDate&&d.inline||""===g.val().trim())&&_(d.defaultDate),l},l.locale=function(a){if(0===arguments.length)return d.locale;if(!b.localeData(a))throw new TypeError("locale() locale "+a+" is not loaded from moment locales!");return d.locale=a,e.locale(d.locale),f.locale(d.locale),i&&oa(),o&&(aa(),ea()),l},l.stepping=function(a){return 0===arguments.length?d.stepping:(a=parseInt(a,10),(isNaN(a)||1>a)&&(a=1),d.stepping=a,l)},l.useCurrent=function(a){var b=["year","month","day","hour","minute"];if(0===arguments.length)return d.useCurrent;if("boolean"!=typeof a&&"string"!=typeof a)throw new TypeError("useCurrent() expects a boolean or string parameter");if("string"==typeof a&&-1===b.indexOf(a.toLowerCase()))throw new TypeError("useCurrent() expects a string parameter of "+b.join(", "));return d.useCurrent=a,l},l.collapse=function(a){if(0===arguments.length)return d.collapse;if("boolean"!=typeof a)throw new TypeError("collapse() expects a boolean parameter");return d.collapse===a?l:(d.collapse=a,o&&(aa(),ea()),l)},l.icons=function(b){if(0===arguments.length)return a.extend({},d.icons);if(!(b instanceof Object))throw new TypeError("icons() expects parameter to be an Object");return a.extend(d.icons,b),o&&(aa(),ea()),l},l.tooltips=function(b){if(0===arguments.length)return a.extend({},d.tooltips);if(!(b instanceof Object))throw new TypeError("tooltips() expects parameter to be an Object");return a.extend(d.tooltips,b),o&&(aa(),ea()),l},l.useStrict=function(a){if(0===arguments.length)return d.useStrict;if("boolean"!=typeof a)throw new TypeError("useStrict() expects a boolean parameter");return d.useStrict=a,l},l.sideBySide=function(a){if(0===arguments.length)return d.sideBySide;if("boolean"!=typeof a)throw new TypeError("sideBySide() expects a boolean parameter");return d.sideBySide=a,o&&(aa(),ea()),l},l.viewMode=function(a){if(0===arguments.length)return d.viewMode;if("string"!=typeof a)throw new TypeError("viewMode() expects a string parameter");if(-1===r.indexOf(a))throw new TypeError("viewMode() parameter must be one of ("+r.join(", ")+") value");return d.viewMode=a,k=Math.max(r.indexOf(a),p),K(),l},l.toolbarPlacement=function(a){if(0===arguments.length)return d.toolbarPlacement;if("string"!=typeof a)throw new TypeError("toolbarPlacement() expects a string parameter");if(-1===u.indexOf(a))throw new TypeError("toolbarPlacement() parameter must be one of ("+u.join(", ")+") value");return d.toolbarPlacement=a,o&&(aa(),ea()),l},l.widgetPositioning=function(b){if(0===arguments.length)return a.extend({},d.widgetPositioning);if("[object Object]"!=={}.toString.call(b))throw new TypeError("widgetPositioning() expects an object variable");if(b.horizontal){if("string"!=typeof b.horizontal)throw new TypeError("widgetPositioning() horizontal variable must be a string");if(b.horizontal=b.horizontal.toLowerCase(),-1===t.indexOf(b.horizontal))throw new TypeError("widgetPositioning() expects horizontal parameter to be one of ("+t.join(", ")+")");d.widgetPositioning.horizontal=b.horizontal}if(b.vertical){if("string"!=typeof b.vertical)throw new TypeError("widgetPositioning() vertical variable must be a string");if(b.vertical=b.vertical.toLowerCase(),-1===s.indexOf(b.vertical))throw new TypeError("widgetPositioning() expects vertical parameter to be one of ("+s.join(", ")+")");d.widgetPositioning.vertical=b.vertical}return $(),l},l.calendarWeeks=function(a){if(0===arguments.length)return d.calendarWeeks;if("boolean"!=typeof a)throw new TypeError("calendarWeeks() expects parameter to be a boolean value");return d.calendarWeeks=a,$(),l},l.showTodayButton=function(a){if(0===arguments.length)return d.showTodayButton;if("boolean"!=typeof a)throw new TypeError("showTodayButton() expects a boolean parameter");return d.showTodayButton=a,o&&(aa(),ea()),l},l.showClear=function(a){if(0===arguments.length)return d.showClear;if("boolean"!=typeof a)throw new TypeError("showClear() expects a boolean parameter");return d.showClear=a,o&&(aa(),ea()),l},l.widgetParent=function(b){if(0===arguments.length)return d.widgetParent;if("string"==typeof b&&(b=a(b)),null!==b&&"string"!=typeof b&&!(b instanceof a))throw new TypeError("widgetParent() expects a string or a jQuery object parameter");return d.widgetParent=b,o&&(aa(),ea()),l},l.keepOpen=function(a){if(0===arguments.length)return d.keepOpen;if("boolean"!=typeof a)throw new TypeError("keepOpen() expects a boolean parameter");return d.keepOpen=a,l},l.focusOnShow=function(a){if(0===arguments.length)return d.focusOnShow;if("boolean"!=typeof a)throw new TypeError("focusOnShow() expects a boolean parameter");return d.focusOnShow=a,l},l.inline=function(a){if(0===arguments.length)return d.inline;if("boolean"!=typeof a)throw new TypeError("inline() expects a boolean parameter");return d.inline=a,l},l.clear=function(){return ba(),l},l.keyBinds=function(a){return d.keyBinds=a,l},l.getMoment=function(a){return x(a)},l.debug=function(a){if("boolean"!=typeof a)throw new TypeError("debug() expects a boolean parameter");return d.debug=a,l},l.allowInputToggle=function(a){if(0===arguments.length)return d.allowInputToggle;if("boolean"!=typeof a)throw new TypeError("allowInputToggle() expects a boolean parameter");return d.allowInputToggle=a,l},l.showClose=function(a){if(0===arguments.length)return d.showClose;if("boolean"!=typeof a)throw new TypeError("showClose() expects a boolean parameter");return d.showClose=a,l},l.keepInvalid=function(a){if(0===arguments.length)return d.keepInvalid;if("boolean"!=typeof a)throw new TypeError("keepInvalid() expects a boolean parameter");return d.keepInvalid=a,l},l.datepickerInput=function(a){if(0===arguments.length)return d.datepickerInput;if("string"!=typeof a)throw new TypeError("datepickerInput() expects a string parameter");return d.datepickerInput=a,l},l.parseInputDate=function(a){if(0===arguments.length)return d.parseInputDate; +if("function"!=typeof a)throw new TypeError("parseInputDate() sholud be as function");return d.parseInputDate=a,l},l.disabledTimeIntervals=function(b){if(0===arguments.length)return d.disabledTimeIntervals?a.extend({},d.disabledTimeIntervals):d.disabledTimeIntervals;if(!b)return d.disabledTimeIntervals=!1,$(),l;if(!(b instanceof Array))throw new TypeError("disabledTimeIntervals() expects an array parameter");return d.disabledTimeIntervals=b,$(),l},l.disabledHours=function(b){if(0===arguments.length)return d.disabledHours?a.extend({},d.disabledHours):d.disabledHours;if(!b)return d.disabledHours=!1,$(),l;if(!(b instanceof Array))throw new TypeError("disabledHours() expects an array parameter");if(d.disabledHours=na(b),d.enabledHours=!1,d.useCurrent&&!d.keepInvalid){for(var c=0;!Q(e,"h");){if(e.add(1,"h"),24===c)throw"Tried 24 times to find a valid date";c++}_(e)}return $(),l},l.enabledHours=function(b){if(0===arguments.length)return d.enabledHours?a.extend({},d.enabledHours):d.enabledHours;if(!b)return d.enabledHours=!1,$(),l;if(!(b instanceof Array))throw new TypeError("enabledHours() expects an array parameter");if(d.enabledHours=na(b),d.disabledHours=!1,d.useCurrent&&!d.keepInvalid){for(var c=0;!Q(e,"h");){if(e.add(1,"h"),24===c)throw"Tried 24 times to find a valid date";c++}_(e)}return $(),l},l.viewDate=function(a){if(0===arguments.length)return f.clone();if(!a)return f=e.clone(),l;if(!("string"==typeof a||b.isMoment(a)||a instanceof Date))throw new TypeError("viewDate() parameter must be one of [string, moment or Date]");return f=ga(a),J(),l},c.is("input"))g=c;else if(g=c.find(d.datepickerInput),0===g.size())g=c.find("input");else if(!g.is("input"))throw new Error('CSS class "'+d.datepickerInput+'" cannot be applied to non input element');if(c.hasClass("input-group")&&(n=0===c.find(".datepickerbutton").size()?c.find(".input-group-addon"):c.find(".datepickerbutton")),!d.inline&&!g.is("input"))throw new Error("Could not initialize DateTimePicker without an input element");return e=x(),f=e.clone(),a.extend(!0,d,G()),l.options(d),oa(),ka(),g.prop("disabled")&&l.disable(),g.is("input")&&0!==g.val().trim().length?_(ga(g.val().trim())):d.defaultDate&&void 0===g.attr("placeholder")&&_(d.defaultDate),d.inline&&ea(),l};a.fn.datetimepicker=function(b){return this.each(function(){var d=a(this);d.data("DateTimePicker")||(b=a.extend(!0,{},a.fn.datetimepicker.defaults,b),d.data("DateTimePicker",c(d,b)))})},a.fn.datetimepicker.defaults={timeZone:"Etc/UTC",format:!1,dayViewHeaderFormat:"MMMM YYYY",extraFormats:!1,stepping:1,minDate:!1,maxDate:!1,useCurrent:!0,collapse:!0,locale:b.locale(),defaultDate:!1,disabledDates:!1,enabledDates:!1,icons:{time:"glyphicon glyphicon-time",date:"glyphicon glyphicon-calendar",up:"glyphicon glyphicon-chevron-up",down:"glyphicon glyphicon-chevron-down",previous:"glyphicon glyphicon-chevron-left",next:"glyphicon glyphicon-chevron-right",today:"glyphicon glyphicon-screenshot",clear:"glyphicon glyphicon-trash",close:"glyphicon glyphicon-remove"},tooltips:{today:"Go to today",clear:"Clear selection",close:"Close the picker",selectMonth:"Select Month",prevMonth:"Previous Month",nextMonth:"Next Month",selectYear:"Select Year",prevYear:"Previous Year",nextYear:"Next Year",selectDecade:"Select Decade",prevDecade:"Previous Decade",nextDecade:"Next Decade",prevCentury:"Previous Century",nextCentury:"Next Century",pickHour:"Pick Hour",incrementHour:"Increment Hour",decrementHour:"Decrement Hour",pickMinute:"Pick Minute",incrementMinute:"Increment Minute",decrementMinute:"Decrement Minute",pickSecond:"Pick Second",incrementSecond:"Increment Second",decrementSecond:"Decrement Second",togglePeriod:"Toggle Period",selectTime:"Select Time"},useStrict:!1,sideBySide:!1,daysOfWeekDisabled:!1,calendarWeeks:!1,viewMode:"days",toolbarPlacement:"default",showTodayButton:!1,showClear:!1,showClose:!1,widgetPositioning:{horizontal:"auto",vertical:"auto"},widgetParent:null,ignoreReadonly:!1,keepOpen:!1,focusOnShow:!0,inline:!1,keepInvalid:!1,datepickerInput:".datepickerinput",keyBinds:{up:function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")?this.date(b.clone().subtract(7,"d")):this.date(b.clone().add(this.stepping(),"m"))}},down:function(a){if(!a)return void this.show();var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")?this.date(b.clone().add(7,"d")):this.date(b.clone().subtract(this.stepping(),"m"))},"control up":function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")?this.date(b.clone().subtract(1,"y")):this.date(b.clone().add(1,"h"))}},"control down":function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")?this.date(b.clone().add(1,"y")):this.date(b.clone().subtract(1,"h"))}},left:function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")&&this.date(b.clone().subtract(1,"d"))}},right:function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")&&this.date(b.clone().add(1,"d"))}},pageUp:function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")&&this.date(b.clone().subtract(1,"M"))}},pageDown:function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")&&this.date(b.clone().add(1,"M"))}},enter:function(){this.hide()},escape:function(){this.hide()},"control space":function(a){a.find(".timepicker").is(":visible")&&a.find('.btn[data-action="togglePeriod"]').click()},t:function(){this.date(this.getMoment())},"delete":function(){this.clear()}},debug:!1,allowInputToggle:!1,disabledTimeIntervals:!1,disabledHours:!1,enabledHours:!1,viewDate:!1}}); \ No newline at end of file diff --git a/assets/js/bootstrap.min.js b/assets/js/bootstrap.min.js new file mode 100644 index 0000000..133aeec --- /dev/null +++ b/assets/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.5",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.5",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),a(c.target).is('input[type="radio"]')||a(c.target).is('input[type="checkbox"]')||c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.5",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.5",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.5",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
    ',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.5",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.5",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.5",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/assets/js/bxslider.min.js b/assets/js/bxslider.min.js new file mode 100644 index 0000000..dc338f7 --- /dev/null +++ b/assets/js/bxslider.min.js @@ -0,0 +1,10 @@ +/** + * BxSlider v4.1.2 - Fully loaded, responsive content slider + * http://bxslider.com + * + * Copyright 2014, Steven Wanderski - http://stevenwanderski.com - http://bxcreative.com + * Written while drinking Belgian ales and listening to jazz + * + * Released under the MIT license - http://opensource.org/licenses/MIT + */ +!function(t){var e={},s={mode:"horizontal",slideSelector:"",infiniteLoop:!0,hideControlOnEnd:!1,speed:500,easing:null,slideMargin:0,startSlide:0,randomStart:!1,captions:!1,ticker:!1,tickerHover:!1,adaptiveHeight:!1,adaptiveHeightSpeed:500,video:!1,useCSS:!0,preloadImages:"visible",responsive:!0,slideZIndex:50,touchEnabled:!0,swipeThreshold:50,oneToOneTouch:!0,preventDefaultSwipeX:!0,preventDefaultSwipeY:!1,pager:!0,pagerType:"full",pagerShortSeparator:" / ",pagerSelector:null,buildPager:null,pagerCustom:null,controls:!0,nextText:"Next",prevText:"Prev",nextSelector:null,prevSelector:null,autoControls:!1,startText:"Start",stopText:"Stop",autoControlsCombine:!1,autoControlsSelector:null,auto:!1,pause:4e3,autoStart:!0,autoDirection:"next",autoHover:!1,autoDelay:0,minSlides:1,maxSlides:1,moveSlides:0,slideWidth:0,onSliderLoad:function(){},onSlideBefore:function(){},onSlideAfter:function(){},onSlideNext:function(){},onSlidePrev:function(){},onSliderResize:function(){}};t.fn.bxSlider=function(n){if(0==this.length)return this;if(this.length>1)return this.each(function(){t(this).bxSlider(n)}),this;var o={},r=this;e.el=this;var a=t(window).width(),l=t(window).height(),d=function(){o.settings=t.extend({},s,n),o.settings.slideWidth=parseInt(o.settings.slideWidth),o.children=r.children(o.settings.slideSelector),o.children.length1||o.settings.maxSlides>1,o.carousel&&(o.settings.preloadImages="all"),o.minThreshold=o.settings.minSlides*o.settings.slideWidth+(o.settings.minSlides-1)*o.settings.slideMargin,o.maxThreshold=o.settings.maxSlides*o.settings.slideWidth+(o.settings.maxSlides-1)*o.settings.slideMargin,o.working=!1,o.controls={},o.interval=null,o.animProp="vertical"==o.settings.mode?"top":"left",o.usingCSS=o.settings.useCSS&&"fade"!=o.settings.mode&&function(){var t=document.createElement("div"),e=["WebkitPerspective","MozPerspective","OPerspective","msPerspective"];for(var i in e)if(void 0!==t.style[e[i]])return o.cssPrefix=e[i].replace("Perspective","").toLowerCase(),o.animProp="-"+o.cssPrefix+"-transform",!0;return!1}(),"vertical"==o.settings.mode&&(o.settings.maxSlides=o.settings.minSlides),r.data("origStyle",r.attr("style")),r.children(o.settings.slideSelector).each(function(){t(this).data("origStyle",t(this).attr("style"))}),c()},c=function(){r.wrap('
    '),o.viewport=r.parent(),o.loader=t('
    '),o.viewport.prepend(o.loader),r.css({width:"horizontal"==o.settings.mode?100*o.children.length+215+"%":"auto",position:"relative"}),o.usingCSS&&o.settings.easing?r.css("-"+o.cssPrefix+"-transition-timing-function",o.settings.easing):o.settings.easing||(o.settings.easing="swing"),f(),o.viewport.css({width:"100%",overflow:"hidden",position:"relative"}),o.viewport.parent().css({maxWidth:p()}),o.settings.pager||o.viewport.parent().css({margin:"0 auto 0px"}),o.children.css({"float":"horizontal"==o.settings.mode?"left":"none",listStyle:"none",position:"relative"}),o.children.css("width",u()),"horizontal"==o.settings.mode&&o.settings.slideMargin>0&&o.children.css("marginRight",o.settings.slideMargin),"vertical"==o.settings.mode&&o.settings.slideMargin>0&&o.children.css("marginBottom",o.settings.slideMargin),"fade"==o.settings.mode&&(o.children.css({position:"absolute",zIndex:0,display:"none"}),o.children.eq(o.settings.startSlide).css({zIndex:o.settings.slideZIndex,display:"block"})),o.controls.el=t('
    '),o.settings.captions&&P(),o.active.last=o.settings.startSlide==x()-1,o.settings.video&&r.fitVids();var e=o.children.eq(o.settings.startSlide);"all"==o.settings.preloadImages&&(e=o.children),o.settings.ticker?o.settings.pager=!1:(o.settings.pager&&T(),o.settings.controls&&C(),o.settings.auto&&o.settings.autoControls&&E(),(o.settings.controls||o.settings.autoControls||o.settings.pager)&&o.viewport.after(o.controls.el)),g(e,h)},g=function(e,i){var s=e.find("img, iframe").length;if(0==s)return i(),void 0;var n=0;e.find("img, iframe").each(function(){t(this).one("load",function(){++n==s&&i()}).each(function(){this.complete&&t(this).load()})})},h=function(){if(o.settings.infiniteLoop&&"fade"!=o.settings.mode&&!o.settings.ticker){var e="vertical"==o.settings.mode?o.settings.minSlides:o.settings.maxSlides,i=o.children.slice(0,e).clone().addClass("bx-clone"),s=o.children.slice(-e).clone().addClass("bx-clone");r.append(i).prepend(s)}o.loader.remove(),S(),"vertical"==o.settings.mode&&(o.settings.adaptiveHeight=!0),o.viewport.height(v()),r.redrawSlider(),o.settings.onSliderLoad(o.active.index),o.initialized=!0,o.settings.responsive&&t(window).bind("resize",Z),o.settings.auto&&o.settings.autoStart&&H(),o.settings.ticker&&L(),o.settings.pager&&q(o.settings.startSlide),o.settings.controls&&W(),o.settings.touchEnabled&&!o.settings.ticker&&O()},v=function(){var e=0,s=t();if("vertical"==o.settings.mode||o.settings.adaptiveHeight)if(o.carousel){var n=1==o.settings.moveSlides?o.active.index:o.active.index*m();for(s=o.children.eq(n),i=1;i<=o.settings.maxSlides-1;i++)s=n+i>=o.children.length?s.add(o.children.eq(i-1)):s.add(o.children.eq(n+i))}else s=o.children.eq(o.active.index);else s=o.children;return"vertical"==o.settings.mode?(s.each(function(){e+=t(this).outerHeight()}),o.settings.slideMargin>0&&(e+=o.settings.slideMargin*(o.settings.minSlides-1))):e=Math.max.apply(Math,s.map(function(){return t(this).outerHeight(!1)}).get()),e},p=function(){var t="100%";return o.settings.slideWidth>0&&(t="horizontal"==o.settings.mode?o.settings.maxSlides*o.settings.slideWidth+(o.settings.maxSlides-1)*o.settings.slideMargin:o.settings.slideWidth),t},u=function(){var t=o.settings.slideWidth,e=o.viewport.width();return 0==o.settings.slideWidth||o.settings.slideWidth>e&&!o.carousel||"vertical"==o.settings.mode?t=e:o.settings.maxSlides>1&&"horizontal"==o.settings.mode&&(e>o.maxThreshold||e0)if(o.viewport.width()o.maxThreshold)t=o.settings.maxSlides;else{var e=o.children.first().width();t=Math.floor(o.viewport.width()/e)}else"vertical"==o.settings.mode&&(t=o.settings.minSlides);return t},x=function(){var t=0;if(o.settings.moveSlides>0)if(o.settings.infiniteLoop)t=o.children.length/m();else for(var e=0,i=0;e0&&o.settings.moveSlides<=f()?o.settings.moveSlides:f()},S=function(){if(o.children.length>o.settings.maxSlides&&o.active.last&&!o.settings.infiniteLoop){if("horizontal"==o.settings.mode){var t=o.children.last(),e=t.position();b(-(e.left-(o.viewport.width()-t.width())),"reset",0)}else if("vertical"==o.settings.mode){var i=o.children.length-o.settings.minSlides,e=o.children.eq(i).position();b(-e.top,"reset",0)}}else{var e=o.children.eq(o.active.index*m()).position();o.active.index==x()-1&&(o.active.last=!0),void 0!=e&&("horizontal"==o.settings.mode?b(-e.left,"reset",0):"vertical"==o.settings.mode&&b(-e.top,"reset",0))}},b=function(t,e,i,s){if(o.usingCSS){var n="vertical"==o.settings.mode?"translate3d(0, "+t+"px, 0)":"translate3d("+t+"px, 0, 0)";r.css("-"+o.cssPrefix+"-transition-duration",i/1e3+"s"),"slide"==e?(r.css(o.animProp,n),r.bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",function(){r.unbind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd"),D()})):"reset"==e?r.css(o.animProp,n):"ticker"==e&&(r.css("-"+o.cssPrefix+"-transition-timing-function","linear"),r.css(o.animProp,n),r.bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",function(){r.unbind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd"),b(s.resetValue,"reset",0),N()}))}else{var a={};a[o.animProp]=t,"slide"==e?r.animate(a,i,o.settings.easing,function(){D()}):"reset"==e?r.css(o.animProp,t):"ticker"==e&&r.animate(a,speed,"linear",function(){b(s.resetValue,"reset",0),N()})}},w=function(){for(var e="",i=x(),s=0;i>s;s++){var n="";o.settings.buildPager&&t.isFunction(o.settings.buildPager)?(n=o.settings.buildPager(s),o.pagerEl.addClass("bx-custom-pager")):(n=s+1,o.pagerEl.addClass("bx-default-pager")),e+='"}o.pagerEl.html(e)},T=function(){o.settings.pagerCustom?o.pagerEl=t(o.settings.pagerCustom):(o.pagerEl=t('
    '),o.settings.pagerSelector?t(o.settings.pagerSelector).html(o.pagerEl):o.controls.el.addClass("bx-has-pager").append(o.pagerEl),w()),o.pagerEl.on("click","a",I)},C=function(){o.controls.next=t(''+o.settings.nextText+""),o.controls.prev=t(''+o.settings.prevText+""),o.controls.next.bind("click",y),o.controls.prev.bind("click",z),o.settings.nextSelector&&t(o.settings.nextSelector).append(o.controls.next),o.settings.prevSelector&&t(o.settings.prevSelector).append(o.controls.prev),o.settings.nextSelector||o.settings.prevSelector||(o.controls.directionEl=t('
    '),o.controls.directionEl.append(o.controls.prev).append(o.controls.next),o.controls.el.addClass("bx-has-controls-direction").append(o.controls.directionEl))},E=function(){o.controls.start=t('"),o.controls.stop=t('"),o.controls.autoEl=t('
    '),o.controls.autoEl.on("click",".bx-start",k),o.controls.autoEl.on("click",".bx-stop",M),o.settings.autoControlsCombine?o.controls.autoEl.append(o.controls.start):o.controls.autoEl.append(o.controls.start).append(o.controls.stop),o.settings.autoControlsSelector?t(o.settings.autoControlsSelector).html(o.controls.autoEl):o.controls.el.addClass("bx-has-controls-auto").append(o.controls.autoEl),A(o.settings.autoStart?"stop":"start")},P=function(){o.children.each(function(){var e=t(this).find("img:first").attr("title");void 0!=e&&(""+e).length&&t(this).append('
    '+e+"
    ")})},y=function(t){o.settings.auto&&r.stopAuto(),r.goToNextSlide(),t.preventDefault()},z=function(t){o.settings.auto&&r.stopAuto(),r.goToPrevSlide(),t.preventDefault()},k=function(t){r.startAuto(),t.preventDefault()},M=function(t){r.stopAuto(),t.preventDefault()},I=function(e){o.settings.auto&&r.stopAuto();var i=t(e.currentTarget),s=parseInt(i.attr("data-slide-index"));s!=o.active.index&&r.goToSlide(s),e.preventDefault()},q=function(e){var i=o.children.length;return"short"==o.settings.pagerType?(o.settings.maxSlides>1&&(i=Math.ceil(o.children.length/o.settings.maxSlides)),o.pagerEl.html(e+1+o.settings.pagerShortSeparator+i),void 0):(o.pagerEl.find("a").removeClass("active"),o.pagerEl.each(function(i,s){t(s).find("a").eq(e).addClass("active")}),void 0)},D=function(){if(o.settings.infiniteLoop){var t="";0==o.active.index?t=o.children.eq(0).position():o.active.index==x()-1&&o.carousel?t=o.children.eq((x()-1)*m()).position():o.active.index==o.children.length-1&&(t=o.children.eq(o.children.length-1).position()),t&&("horizontal"==o.settings.mode?b(-t.left,"reset",0):"vertical"==o.settings.mode&&b(-t.top,"reset",0))}o.working=!1,o.settings.onSlideAfter(o.children.eq(o.active.index),o.oldIndex,o.active.index)},A=function(t){o.settings.autoControlsCombine?o.controls.autoEl.html(o.controls[t]):(o.controls.autoEl.find("a").removeClass("active"),o.controls.autoEl.find("a:not(.bx-"+t+")").addClass("active"))},W=function(){1==x()?(o.controls.prev.addClass("disabled"),o.controls.next.addClass("disabled")):!o.settings.infiniteLoop&&o.settings.hideControlOnEnd&&(0==o.active.index?(o.controls.prev.addClass("disabled"),o.controls.next.removeClass("disabled")):o.active.index==x()-1?(o.controls.next.addClass("disabled"),o.controls.prev.removeClass("disabled")):(o.controls.prev.removeClass("disabled"),o.controls.next.removeClass("disabled")))},H=function(){o.settings.autoDelay>0?setTimeout(r.startAuto,o.settings.autoDelay):r.startAuto(),o.settings.autoHover&&r.hover(function(){o.interval&&(r.stopAuto(!0),o.autoPaused=!0)},function(){o.autoPaused&&(r.startAuto(!0),o.autoPaused=null)})},L=function(){var e=0;if("next"==o.settings.autoDirection)r.append(o.children.clone().addClass("bx-clone"));else{r.prepend(o.children.clone().addClass("bx-clone"));var i=o.children.first().position();e="horizontal"==o.settings.mode?-i.left:-i.top}b(e,"reset",0),o.settings.pager=!1,o.settings.controls=!1,o.settings.autoControls=!1,o.settings.tickerHover&&!o.usingCSS&&o.viewport.hover(function(){r.stop()},function(){var e=0;o.children.each(function(){e+="horizontal"==o.settings.mode?t(this).outerWidth(!0):t(this).outerHeight(!0)});var i=o.settings.speed/e,s="horizontal"==o.settings.mode?"left":"top",n=i*(e-Math.abs(parseInt(r.css(s))));N(n)}),N()},N=function(t){speed=t?t:o.settings.speed;var e={left:0,top:0},i={left:0,top:0};"next"==o.settings.autoDirection?e=r.find(".bx-clone").first().position():i=o.children.first().position();var s="horizontal"==o.settings.mode?-e.left:-e.top,n="horizontal"==o.settings.mode?-i.left:-i.top,a={resetValue:n};b(s,"ticker",speed,a)},O=function(){o.touch={start:{x:0,y:0},end:{x:0,y:0}},o.viewport.bind("touchstart",X)},X=function(t){if(o.working)t.preventDefault();else{o.touch.originalPos=r.position();var e=t.originalEvent;o.touch.start.x=e.changedTouches[0].pageX,o.touch.start.y=e.changedTouches[0].pageY,o.viewport.bind("touchmove",Y),o.viewport.bind("touchend",V)}},Y=function(t){var e=t.originalEvent,i=Math.abs(e.changedTouches[0].pageX-o.touch.start.x),s=Math.abs(e.changedTouches[0].pageY-o.touch.start.y);if(3*i>s&&o.settings.preventDefaultSwipeX?t.preventDefault():3*s>i&&o.settings.preventDefaultSwipeY&&t.preventDefault(),"fade"!=o.settings.mode&&o.settings.oneToOneTouch){var n=0;if("horizontal"==o.settings.mode){var r=e.changedTouches[0].pageX-o.touch.start.x;n=o.touch.originalPos.left+r}else{var r=e.changedTouches[0].pageY-o.touch.start.y;n=o.touch.originalPos.top+r}b(n,"reset",0)}},V=function(t){o.viewport.unbind("touchmove",Y);var e=t.originalEvent,i=0;if(o.touch.end.x=e.changedTouches[0].pageX,o.touch.end.y=e.changedTouches[0].pageY,"fade"==o.settings.mode){var s=Math.abs(o.touch.start.x-o.touch.end.x);s>=o.settings.swipeThreshold&&(o.touch.start.x>o.touch.end.x?r.goToNextSlide():r.goToPrevSlide(),r.stopAuto())}else{var s=0;"horizontal"==o.settings.mode?(s=o.touch.end.x-o.touch.start.x,i=o.touch.originalPos.left):(s=o.touch.end.y-o.touch.start.y,i=o.touch.originalPos.top),!o.settings.infiniteLoop&&(0==o.active.index&&s>0||o.active.last&&0>s)?b(i,"reset",200):Math.abs(s)>=o.settings.swipeThreshold?(0>s?r.goToNextSlide():r.goToPrevSlide(),r.stopAuto()):b(i,"reset",200)}o.viewport.unbind("touchend",V)},Z=function(){var e=t(window).width(),i=t(window).height();(a!=e||l!=i)&&(a=e,l=i,r.redrawSlider(),o.settings.onSliderResize.call(r,o.active.index))};return r.goToSlide=function(e,i){if(!o.working&&o.active.index!=e)if(o.working=!0,o.oldIndex=o.active.index,o.active.index=0>e?x()-1:e>=x()?0:e,o.settings.onSlideBefore(o.children.eq(o.active.index),o.oldIndex,o.active.index),"next"==i?o.settings.onSlideNext(o.children.eq(o.active.index),o.oldIndex,o.active.index):"prev"==i&&o.settings.onSlidePrev(o.children.eq(o.active.index),o.oldIndex,o.active.index),o.active.last=o.active.index>=x()-1,o.settings.pager&&q(o.active.index),o.settings.controls&&W(),"fade"==o.settings.mode)o.settings.adaptiveHeight&&o.viewport.height()!=v()&&o.viewport.animate({height:v()},o.settings.adaptiveHeightSpeed),o.children.filter(":visible").fadeOut(o.settings.speed).css({zIndex:0}),o.children.eq(o.active.index).css("zIndex",o.settings.slideZIndex+1).fadeIn(o.settings.speed,function(){t(this).css("zIndex",o.settings.slideZIndex),D()});else{o.settings.adaptiveHeight&&o.viewport.height()!=v()&&o.viewport.animate({height:v()},o.settings.adaptiveHeightSpeed);var s=0,n={left:0,top:0};if(!o.settings.infiniteLoop&&o.carousel&&o.active.last)if("horizontal"==o.settings.mode){var a=o.children.eq(o.children.length-1);n=a.position(),s=o.viewport.width()-a.outerWidth()}else{var l=o.children.length-o.settings.minSlides;n=o.children.eq(l).position()}else if(o.carousel&&o.active.last&&"prev"==i){var d=1==o.settings.moveSlides?o.settings.maxSlides-m():(x()-1)*m()-(o.children.length-o.settings.maxSlides),a=r.children(".bx-clone").eq(d);n=a.position()}else if("next"==i&&0==o.active.index)n=r.find("> .bx-clone").eq(o.settings.maxSlides).position(),o.active.last=!1;else if(e>=0){var c=e*m();n=o.children.eq(c).position()}if("undefined"!=typeof n){var g="horizontal"==o.settings.mode?-(n.left-s):-n.top;b(g,"slide",o.settings.speed)}}},r.goToNextSlide=function(){if(o.settings.infiniteLoop||!o.active.last){var t=parseInt(o.active.index)+1;r.goToSlide(t,"next")}},r.goToPrevSlide=function(){if(o.settings.infiniteLoop||0!=o.active.index){var t=parseInt(o.active.index)-1;r.goToSlide(t,"prev")}},r.startAuto=function(t){o.interval||(o.interval=setInterval(function(){"next"==o.settings.autoDirection?r.goToNextSlide():r.goToPrevSlide()},o.settings.pause),o.settings.autoControls&&1!=t&&A("stop"))},r.stopAuto=function(t){o.interval&&(clearInterval(o.interval),o.interval=null,o.settings.autoControls&&1!=t&&A("start"))},r.getCurrentSlide=function(){return o.active.index},r.getCurrentSlideElement=function(){return o.children.eq(o.active.index)},r.getSlideCount=function(){return o.children.length},r.redrawSlider=function(){o.children.add(r.find(".bx-clone")).outerWidth(u()),o.viewport.css("height",v()),o.settings.ticker||S(),o.active.last&&(o.active.index=x()-1),o.active.index>=x()&&(o.active.last=!0),o.settings.pager&&!o.settings.pagerCustom&&(w(),q(o.active.index))},r.destroySlider=function(){o.initialized&&(o.initialized=!1,t(".bx-clone",this).remove(),o.children.each(function(){void 0!=t(this).data("origStyle")?t(this).attr("style",t(this).data("origStyle")):t(this).removeAttr("style")}),void 0!=t(this).data("origStyle")?this.attr("style",t(this).data("origStyle")):t(this).removeAttr("style"),t(this).unwrap().unwrap(),o.controls.el&&o.controls.el.remove(),o.controls.next&&o.controls.next.remove(),o.controls.prev&&o.controls.prev.remove(),o.pagerEl&&o.settings.controls&&o.pagerEl.remove(),t(".bx-caption",this).remove(),o.controls.autoEl&&o.controls.autoEl.remove(),clearInterval(o.interval),o.settings.responsive&&t(window).unbind("resize",Z))},r.reloadSlider=function(t){void 0!=t&&(n=t),r.destroySlider(),d()},d(),this}}(jQuery); \ No newline at end of file diff --git a/assets/js/cropper.js b/assets/js/cropper.js new file mode 100644 index 0000000..36dd510 --- /dev/null +++ b/assets/js/cropper.js @@ -0,0 +1,424 @@ +/** + * Zira project. + * Image cropper + * (c)2015 http://dro1d.ru + * + * Usage: + * $(document).ready(function(){ + * $('img').cropper([options]); + * }); + */ + +(function($){ + Cropper = function(element, options) { + this.container_class = 'image-cropper'; + this.selector_class = 'image-cropper-selector'; + this.resizer_class = 'image-cropper-resizer'; + this.previewer_class = 'image-cropper-preview'; + this.custom_previewer_class = 'image-cropper-preview-custom'; + this.body_on_resize_class = 'image-cropper-resizing'; + this.body_on_dragging_class = 'image-cropper-dragging'; + this.events = {}; + this.disabled = false; + + var defaults = { + 'src_w': null, // source image container width + 'src_h': null, // source image container height + 'dst_w': 100, // preview image container width + 'dst_h': 100, // preview image container height + 'sel_w': null, // cropping box width on start + 'sel_h': null, // cropping box height on start + 'sel_mw': null, // cropping box min width + 'sel_mh': null, // cropping box min height + 'res_s': 10, // resizing box size + 'fixed': true, // keep aspect ratio + 'preview': true, // preview result image + 'preview_m': 7, // preview box margin + 'previewer': null, // custom preview container id + 'input_x': null, // x-offset storage input id + 'input_y': null, // y-offset storage input id + 'input_w': null, // width storage input id + 'input_h': null, // height storage input id + 'block_mode': false + }; + if(typeof(options)!="undefined") { + this.options = $.extend(defaults, options); + } else { + this.options = defaults; + } + + var src = $(element).attr('src'); + if (!this.options.src_w) this.options.src_w = $(element).width(); + if (!this.options.src_h) this.options.src_h = $(element).height(); + if (!this.options.block_mode) { + $(element).after('
    '); + this.container = $(element).next('.'+this.container_class); + $(this.container).children('img').load(this.bind(this,this.initialize)); + $(this.container).children('img').css({ + 'width': this.options.src_w, + 'height': this.options.src_h + }); + this.source = $(this.container).children('img'); + $(element).remove(); + $(this.container).children('img').attr('src',src); + } else { + if ($(element).parent().css('position')=='static') $(element).parent().css('position','relative'); + $(element).after('
    '); + this.container = $(element).next('.'+this.container_class); + $(this.container).css({ + 'position': 'absolute', + 'left': $(element).offset().left - $(element).parent().offset().left, + 'top': $(element).offset().top - $(element).parent().offset().top + }); + this.source = $(element); + this.initialize(); + } + }; + + Cropper.prototype.initialize = function() { + $(this.container).css({ + 'width':this.options.src_w, + 'height':this.options.src_h + }); + this.container_x = $(this.container).offset().left; + this.container_y = $(this.container).offset().top; + + if (!this.options.sel_w) this.options.sel_w = this.options.dst_w; + if (!this.options.sel_h) this.options.sel_h = this.options.dst_h; + if (!this.options.sel_mw) this.options.sel_mw = this.options.sel_w; + if (!this.options.sel_mh) this.options.sel_mh = this.options.sel_h; + if (this.options.sel_w>this.options.src_w) this.options.sel_w = this.options.src_w; + if (this.options.sel_h>this.options.src_h) this.options.sel_h = this.options.src_h; + if (this.options.sel_mw>this.options.sel_w) this.options.sel_mw = this.options.sel_w; + if (this.options.sel_mh>this.options.sel_h) this.options.sel_mh = this.options.sel_h; + $(this.container).append('
    '); + this.selector = $(this.container).children('.'+this.selector_class); + $(this.selector).css({ + 'width':this.options.sel_w, + 'height':this.options.sel_h, + 'left': (this.options.src_w-this.options.sel_w)/2, + 'top': (this.options.src_h-this.options.sel_h)/2 + }); + this.selector_w = this.options.sel_w; + this.selector_h = this.options.sel_h; + + if (this.options.input_w && + this.options.input_h && + this.options.input_x && + this.options.input_y + ) { + var input_w = $('#'+this.options.input_w).val(); + var input_h = $('#'+this.options.input_h).val(); + var input_x = $('#'+this.options.input_x).val(); + var input_y = $('#'+this.options.input_y).val(); + if (input_w.length && input_h.length && input_x.length && input_y.length) { + input_w = parseFloat(input_w) * this.options.src_w / 100; + input_h = parseFloat(input_h) * this.options.src_h / 100; + input_x = parseFloat(input_x) * this.options.src_w / 100; + input_y = parseFloat(input_y) * this.options.src_h / 100; + $(this.selector).css({ + 'width':input_w, + 'height':input_h, + 'left': input_x, + 'top': input_y + }); + this.selector_w = input_w; + this.selector_h = input_h; + } + } + this.selector_x = $(this.selector).offset().left; + this.selector_y = $(this.selector).offset().top; + + $(this.selector).append('
    '); + this.resizer = $(this.selector).children('.'+this.resizer_class); + this.resizer_w = this.options.res_s; + this.resizer_h = this.options.res_s; + $(this.resizer).css({ + 'width': this.resizer_w, + 'height': this.resizer_h, + 'right': -(this.resizer_w/2), + 'bottom': -(this.resizer_h/2) + }); + this.resizer_x = $(this.resizer).offset().left; + this.resizer_y = $(this.resizer).offset().top; + + if (this.options.preview) { + if (!this.options.previewer) { + $(this.container).append('
    '); + this.previewer = $(this.container).children('.'+this.previewer_class); + $(this.previewer).css({ + 'width':this.options.dst_w, + 'height':this.options.dst_h, + 'right': -this.options.dst_w-this.options.preview_m, + 'top': 0 + }); + } else { + this.previewer = $('#'+this.options.previewer); + $(this.previewer).addClass(this.custom_previewer_class).html(''); + $(this.previewer).css({ + 'width':this.options.dst_w, + 'height':this.options.dst_h + }); + if ($(this.previewer).css('position') == 'static') { + $(this.previewer).css('position','relative'); + } + } + + $(this.previewer).children('img').load(this.bind(this,this.update)); + $(this.previewer).children('img').attr('src',$(this.source).attr('src')); + } else { + this.previewer = null; + } + + this.dragging = false; + this.resizing = false; + this.dragX = 0; + this.dragY = 0; + + this.touchesEnabled = false; + this.bindEvents(); + }; + + Cropper.prototype.updateOffsets = function() { + this.container_x = $(this.container).offset().left; + this.container_y = $(this.container).offset().top; + this.selector_x = $(this.selector).offset().left; + this.selector_y = $(this.selector).offset().top; + this.resizer_x = $(this.resizer).offset().left; + this.resizer_y = $(this.resizer).offset().top; + }; + + Cropper.prototype.onTouchStartEvent = function(e) { + this.touchesEnabled = true; + e.pageX = e.originalEvent.touches[0].pageX; + e.pageY = e.originalEvent.touches[0].pageY; + this.onMouseDown(e); + }; + + Cropper.prototype.onTouchMoveEvent = function(e) { + e.pageX = e.originalEvent.touches[0].pageX; + e.pageY = e.originalEvent.touches[0].pageY; + this.onMouseMove(e); + }; + + Cropper.prototype.onTouchEndEvent = function(e) { + this.onMouseUp(e); + }; + + Cropper.prototype.onMouseDownEvent = function(e) { + if (this.touchesEnabled) return; + this.onMouseDown(e); + }; + + Cropper.prototype.onMouseMoveEvent = function(e) { + if (this.touchesEnabled) return; + this.onMouseMove(e); + }; + + Cropper.prototype.onMouseUpEvent = function(e) { + if (this.touchesEnabled) return; + this.onMouseUp(e); + }; + + Cropper.prototype.onMouseLeaveEvent = function(e) { + $('body').trigger('mouseup'); + }; + + Cropper.prototype.bindEvents = function() { + this.events['touchstart'] = this.bind(this, this.onTouchStartEvent); + this.events['touchmove'] = this.bind(this, this.onTouchMoveEvent); + this.events['touchend'] = this.bind(this, this.onTouchEndEvent); + this.events['mousedown'] = this.bind(this, this.onMouseDownEvent); + this.events['mousemove'] = this.bind(this, this.onMouseMoveEvent); + this.events['mouseup'] = this.bind(this, this.onMouseUpEvent); + this.events['mouseleave'] = this.bind(this, this.onMouseLeaveEvent); + + $('body').bind('touchstart', this.events['touchstart']); + $('body').bind('touchmove', this.events['touchmove']); + $('body').bind('touchend', this.events['touchend']); + $('body').mousedown(this.events['mousedown']); + $('body').mousemove(this.events['mousemove']); + $('body').mouseup(this.events['mouseup']); + $('body').mouseleave(this.events['mouseleave']); + }; + + Cropper.prototype.unbindEvents = function() { + $('body').unbind('touchstart', this.events['touchstart']); + $('body').unbind('touchmove', this.events['touchmove']); + $('body').unbind('touchend', this.events['touchend']); + $('body').unbind('mousedown', this.events['mousedown']); + $('body').unbind('mousemove', this.events['mousemove']); + $('body').unbind('mouseup', this.events['mouseup']); + $('body').unbind('mouseleave', this.events['mouseleave']); + }; + + Cropper.prototype.bind = function(object, method) { + return function(arg) { + return method.call(object,arg); + } + }; + + Cropper.prototype.onMouseDown = function(e) { + if (this.disabled) return; + this.updateOffsets(); + if ( + e.pageX > this.resizer_x && + e.pageX < this.resizer_x + this.resizer_w && + e.pageY > this.resizer_y && + e.pageY < this.resizer_y + this.resizer_h + ) { + this.resizing = true; + this.dragging = false; + this.dragX = e.pageX; + this.dragY = e.pageY; + e.stopPropagation(); + e.preventDefault(); + $('body').addClass(this.body_on_resize_class); + }else if ( + e.pageX > this.selector_x && + e.pageX < this.selector_x + this.selector_w && + e.pageY > this.selector_y && + e.pageY < this.selector_y + this.selector_h + ) { + this.dragging = true; + this.resizing = false; + this.dragX = e.pageX; + this.dragY = e.pageY; + e.stopPropagation(); + e.preventDefault(); + $('body').addClass(this.body_on_dragging_class); + } else if ( + e.pageX > this.container_x && + e.pageX < this.container_x + this.options.src_w && + e.pageY > this.container_y && + e.pageY < this.container_y + this.options.src_h + ) { + this.dragging = false; + this.resizing = false; + e.stopPropagation(); + e.preventDefault(); + } else { + this.dragging = false; + } + }; + + Cropper.prototype.onMouseMove = function(e) { + if (this.dragging || this.resizing) { + var dx = e.pageX - this.dragX; + var dy = e.pageY - this.dragY; + if (this.dragging) { + this.moveSelector(dx, dy); + } else if (this.resizing) { + this.resizeSelector(dx, dy); + } + this.dragX += dx; + this.dragY += dy; + } + }; + + Cropper.prototype.onMouseUp = function(e) { + if (this.dragging || this.resizing) { + this.resizer_x = $(this.resizer).offset().left; + this.resizer_y = $(this.resizer).offset().top; + this.dragging = false; + this.resizing = false; + $('body').removeClass(this.body_on_resize_class); + } + }; + + Cropper.prototype.moveSelector = function(dx, dy) { + var x = this.selector_x - this.container_x + dx; + var y = this.selector_y - this.container_y + dy; + + if (x<0) x=0; + if (y<0) y=0; + if (x>this.options.src_w-this.selector_w) x=this.options.src_w-this.selector_w; + if (y>this.options.src_h-this.selector_h) y=this.options.src_h-this.selector_h; + + $(this.selector).css({ + 'left': x, + 'top': y + }); + + this.selector_x = x + this.container_x; + this.selector_y = y + this.container_y; + + this.update(); + }; + + Cropper.prototype.resizeSelector = function(dx, dy) { + this.selector_w += dx; + this.selector_h += dy; + + if (this.selector_wthis.container_x+this.options.src_w) { + this.selector_w = this.container_x+this.options.src_w-this.selector_x; + } + if (this.selector_y+this.selector_h>this.container_y+this.options.src_h) { + this.selector_h = this.container_y+this.options.src_h-this.selector_y; + } + + if (this.options.fixed) { + var selector_w = this.selector_h * this.options.sel_w / this.options.sel_h; + var selector_h = this.selector_h; + if (this.selector_x+selector_w>this.container_x+this.options.src_w) { + selector_h = this.selector_w * this.options.sel_h / this.options.sel_w; + selector_w = this.selector_w; + } + this.selector_w = selector_w; + this.selector_h = selector_h; + } + + $(this.selector).css({ + 'width': this.selector_w, + 'height': this.selector_h + }); + + this.update(); + }; + + Cropper.prototype.getRect = function() { + return { + x: ((this.selector_x - this.container_x) / this.options.src_w * 100).toFixed(2), + y: ((this.selector_y - this.container_y) / this.options.src_h * 100).toFixed(2), + w: (this.selector_w / this.options.src_w * 100).toFixed(2), + h: (this.selector_h / this.options.src_h * 100).toFixed(2) + }; + }; + + Cropper.prototype.update = function() { + var rect = this.getRect(); + if (this.options.input_w) $('#'+this.options.input_w).val(rect.w); + if (this.options.input_h) $('#'+this.options.input_h).val(rect.h); + if (this.options.input_x) $('#'+this.options.input_x).val(rect.x); + if (this.options.input_y) $('#'+this.options.input_y).val(rect.y); + if (this.options.preview) this.preview(rect); + }; + + Cropper.prototype.preview = function(rect) { + var width = Math.round(this.options.dst_w * 100 / rect.w); + var height = Math.round(this.options.dst_h * 100 / rect.h); + var left = -Math.round(rect.x * width / 100); + var top = -Math.round(rect.y * height / 100); + + $(this.previewer).children('img').css({ + 'width': width, + 'height': height, + 'left': left, + 'top': top + }); + }; + + Cropper.prototype.destroy = function() { + $(this.container).remove(); + this.unbindEvents(); + }; + + $.fn.cropper = function(options) { + if (!$(this).attr('src')) { + throw 'Cropper should be attached to image'; + } + return new Cropper($(this), options); + }; +})(jQuery); \ No newline at end of file diff --git a/assets/js/dash.js b/assets/js/dash.js new file mode 100644 index 0000000..92acae3 --- /dev/null +++ b/assets/js/dash.js @@ -0,0 +1,249 @@ +(function($) { + function radians(degrees) { + return (Math.PI/180)*degrees; + } + function drawClock(ctx, canvas_size, unix_timestamp) { + ctx.clearRect(0, 0, canvas_size, canvas_size); + + var centerX = canvas_size / 2; + var centerY = canvas_size / 2; + var offset = canvas_size / 40; + var radius = Math.min(centerX, centerY) - offset; + + var grd=ctx.createRadialGradient(centerX, centerY,0,centerX, centerY, radius); + grd.addColorStop(0,"#ffffff"); + grd.addColorStop(1,"#E6E6E8"); + + ctx.beginPath(); + ctx.strokeStyle = "#F8F4F4"; + ctx.lineWidth = 1; + ctx.fillStyle = grd; + ctx.arc(centerX, centerY, canvas_size / 2 - 2, 0, Math.PI*2, false); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + + ctx.beginPath(); + ctx.strokeStyle = "#dedede"; + ctx.lineWidth = 1; + ctx.arc(centerX, centerY, canvas_size / 2 - 1, 0, Math.PI*2, false); + ctx.closePath(); + ctx.stroke(); + + ctx.fillStyle = "#444444"; + ctx.font = "16px Arial"; + for (var i=0; i<12; i++) { + var a = i * 360 / 12; + var size = radius - (canvas_size / 12); + var x = centerX + size * Math.sin(radians(a)); + var y = centerY - size * Math.cos(radians(a)); + var txt = i>0 ? i.toString() : 12; + var txt_w = ctx.measureText(txt).width; + ctx.moveTo(x,y); + ctx.fillText(txt, x - txt_w/2, y+8); + } + + drawArrows(ctx, canvas_size, unix_timestamp); + } + + function drawArrows(ctx, canvas_size, unix_timestamp) { + var centerX = canvas_size / 2; + var centerY = canvas_size / 2; + var offset = canvas_size / 40; + var radius = Math.min(centerX, centerY) - offset; + + var grd=ctx.createRadialGradient(centerX, centerY,0,centerX, centerY, radius); + grd.addColorStop(0,"#ffffff"); + grd.addColorStop(1,"#E6E6E6"); + + ctx.beginPath(); + ctx.fillStyle = grd; + ctx.arc(centerX, centerY, radius - canvas_size / 7, 0, Math.PI*2, false); + ctx.closePath(); + ctx.fill(); + + var h = unix_timestamp%86400/3600; + var _h = h % 12; + var m = unix_timestamp%3600/60; + var s = unix_timestamp%60; + + var f_h = 9; + var digitsY = centerY - radius / 3 + f_h; + if (_h<=3 || _h>=9) digitsY = centerY + radius / 3; + + ctx.font = "12px Arial"; + var t_h = Math.floor(h).toString(); + var t_m = Math.floor(m).toString(); + var t_s = Math.floor(s).toString(); + if (t_h.length==1) t_h = '0'+t_h; + if (t_m.length==1) t_m = '0'+t_m; + if (t_s.length==1) t_s = '0'+t_s; + var txt = t_h+':'+t_m+':'+t_s; + //var txt_w = ctx.measureText(txt).width; + var txt_w = 47; + ctx.fillStyle = "#789789"; + ctx.fillText(txt,centerX - txt_w / 2,digitsY); + + var logoY = centerY - radius / 3 + f_h; + if (_h>3 && _h<9) logoY = centerY + radius / 3; + + ctx.font = "10px Arial"; + var logo = 'Z'+' '+'i'+' '+'r'+' '+'a'; + var logo_w = ctx.measureText(logo).width; + ctx.fillStyle = "#789944"; + ctx.fillText(logo,centerX - logo_w / 2,logoY); + + var a1 = _h * 360 / 12; + var a2 = m * 360 / 60; + var a3 = s * 360 / 60; + + var offset1 = canvas_size / 3.5; + var offset2 = canvas_size / 4.5; + var offset3 = canvas_size / 6; + var size1 = radius - offset1; + var size2 = radius - offset2; + var size3 = radius - offset3; + var x1 = centerX + size1 * Math.sin(radians(a1)); + var y1 = centerY - size1 * Math.cos(radians(a1)); + var x2 = centerX + size2 * Math.sin(radians(a2)); + var y2 = centerY - size2 * Math.cos(radians(a2)); + var x3 = centerX + size3 * Math.sin(radians(a3)); + var y3 = centerY - size3 * Math.cos(radians(a3)); + + ctx.beginPath(); + ctx.strokeStyle = "#777777"; + ctx.lineWidth = canvas_size / 18; + ctx.lineWidth = 4; + ctx.lineCap="round"; + ctx.moveTo(centerX, centerY); + ctx.lineTo(x1, y1); + ctx.moveTo(centerX, centerY); + ctx.closePath(); + ctx.stroke(); + + ctx.beginPath(); + ctx.strokeStyle = "#98008B"; + ctx.lineWidth = canvas_size / 26; + ctx.lineWidth = 3; + ctx.lineCap="round"; + ctx.moveTo(centerX, centerY); + ctx.lineTo(x2, y2); + ctx.moveTo(centerX, centerY); + ctx.closePath(); + ctx.stroke(); + + ctx.beginPath(); + ctx.lineWidth = 1; + ctx.strokeStyle = "#028BEA"; + ctx.moveTo(centerX, centerY); + ctx.lineTo(x3, y3); + ctx.moveTo(centerX, centerY); + ctx.closePath(); + ctx.stroke(); + + ctx.beginPath(); + ctx.lineWidth = canvas_size / 75; + ctx.strokeStyle = "#028BEA"; + ctx.fillStyle = "#A1D4F8"; + ctx.arc(centerX, centerY, radius / 10, 0, Math.PI*2, false); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + } + + dashboard_local_clock = function(update) { + var canvas = $('#dashboard_local_clock').get(0); + + if (typeof(dashboard_local_clock.ctx)=="undefined") { + if (!canvas.getContext) dashboard_local_clock.ctx = null; + dashboard_local_clock.ctx = canvas.getContext('2d'); + } + if (!dashboard_local_clock.ctx) return; + + var canvas_size = Math.min(canvas.width, canvas.height); + + var date = new Date(); + var unix_timestamp = date.getTime() / 1000; + var timezone_offset = date.getTimezoneOffset() * 60; + var local_timestamp = Math.floor(unix_timestamp - timezone_offset); + + if (typeof(update)=="undefined" || !update) { + drawClock(dashboard_local_clock.ctx, canvas_size, local_timestamp); + } else { + drawArrows(dashboard_local_clock.ctx, canvas_size, local_timestamp); + } + }; + + dashboard_remote_clock = function(update) { + if (typeof(dashboard_remote_clock.start_timestamp)=="undefined") return; + if (typeof(dashboard_remote_clock.remote_timestamp)=="undefined") return; + + var canvas = $('#dashboard_remote_clock').get(0); + + if (typeof(dashboard_remote_clock.ctx)=="undefined") { + if (!canvas.getContext) dashboard_remote_clock.ctx = null; + dashboard_remote_clock.ctx = canvas.getContext('2d'); + } + if (!dashboard_remote_clock.ctx) return; + + var canvas_size = Math.min(canvas.width, canvas.height); + + var date = new Date(); + var unix_timestamp = Math.floor(date.getTime() / 1000); + var remote_timestamp = Math.floor(dashboard_remote_clock.remote_timestamp + unix_timestamp - dashboard_remote_clock.start_timestamp); + + if (typeof(update)=="undefined" || !update) { + drawClock(dashboard_remote_clock.ctx, canvas_size, remote_timestamp); + } else { + drawArrows(dashboard_remote_clock.ctx, canvas_size, remote_timestamp); + } + }; + + dashboard_clock = function() { + if (typeof(dashboard_clock.update)=="undefined") { + dashboard_clock.update = false; + } + //dashboard_local_clock(dashboard_clock.update); + dashboard_remote_clock(dashboard_clock.update); + dashboard_clock.update = true; + }; + + dashboard_notification = function(message, callback) { + var last = $('.dashboard-notification:last-child'); + $('body').append('
    '+message+'
    '); + + var t = 60; + if ($(last).length>0) { + t = $(last).offset().top + $(last).outerHeight() + 10; + } + + var dn = $('.dashboard-notification:last-child'); + $(dn).css({ + 'top': t, + 'left': ($(window).width() - $(dn).outerWidth()) / 2 + //'left': $(window).width() - $(dn).outerWidth() - $('#dashboard-sidebar').outerWidth() - 20 + }).fadeIn(); + + $(dn).click(function() { + desk_call(callback); + $(dn).children('.dashboard-notification-close').trigger('click'); + }); + + $(dn).children('.dashboard-notification-close').click(function(e){ + e.stopPropagation(); + e.preventDefault(); + $(this).parent('.dashboard-notification').fadeOut(200, function(){ + $(this).remove(); + }); + }); + + $(window).unbind('resize',dashboard_notification_update_position).resize(dashboard_notification_update_position); + }; + + dashboard_notification_update_position = function() { + $('.dashboard-notification').css({ + 'left': ($(window).width() - $('.dashboard-notification').outerWidth()) / 2 + //'left': $(window).width() - $('.dashboard-notification').outerWidth() - $('#dashboard-sidebar').outerWidth() - 20 + }); + } +})(jQuery); \ No newline at end of file diff --git a/assets/js/dash/blocks.js b/assets/js/dash/blocks.js new file mode 100644 index 0000000..b218070 --- /dev/null +++ b/assets/js/dash/blocks.js @@ -0,0 +1,43 @@ +var dash_blocks_install = function() { + var selected = desk_window_selected(this); + if (selected && typeof(selected.items)!="undefined" && selected.items.length>0) { + desk_window_request(this, url('dash/system/blocks'),{'blocks':selected.items}); + } +}; + +var dash_blocks_select = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length>0) { + this.disableItemsByProperty('typo','install'); + for (var i=0; i0) { + $(this.element).find('.cache-infobar').append('
    '+t('Information')+':
    '); + $(this.element).find('.cache-infobar').append('
    '); + for (var i=0; i'+response[i]+'
    '); + } + } + })); + }),1000); + } +}; + +var dash_cache_clear = function() { + desk_window_request(this, url('dash/system/cache'), {}); +}; \ No newline at end of file diff --git a/assets/js/dash/comments.js b/assets/js/dash/comments.js new file mode 100644 index 0000000..76bd7a0 --- /dev/null +++ b/assets/js/dash/comments.js @@ -0,0 +1,75 @@ +var dash_comments_select = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length>0) { + this.disableItemsByProperty('typo','activate'); + for (var i=0; i0) { + $(this.element).find('.comment-infobar').append('
    '+t('Information')+':
    '); + $(this.element).find('.comment-infobar').append('
    '); + for (var i=0; i'+response[i]+'
    '); + } + } + })); + }),1000); + } +}; + +var dash_comments_preview = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + desk_message(t('Comment')+':
    '+selected[0].title.replace(/\r\n/g,'
    ')+'
    '); + } +}; + +var dash_comments_activate = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length>0) { + desk_window_request(this, url('dash/comments/activate'), desk_window_selected(this)); + } +}; + +var dash_comments_edit = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + desk_multi_prompt(t('Comment'), this.bind(this, function(comment){ desk_window_request(this, url('dash/comments/edit'),{'comment':comment, 'item':selected[0].data}); })); $('#zira-multi-prompt-dialog textarea[name=modal-input]').val(selected[0].title); + } +}; + +var dash_comments_open = function() { + var selected = this.getSelectedContentItems(); + if (selected.length==1 && typeof(selected[0].page)!="undefined") { + window.location.href=url(selected[0].page); + } +}; + +var dash_comments_view = function() { + var selected = this.getSelectedContentItems(); + if (selected.length==1 && typeof(selected[0].page)!="undefined") { + var data = {'url':[selected[0].page]}; + desk_call(dash_comments_web, null, {'data':data}); + } +}; + +var dash_comments_load = function() { + for (var i=0; i'+t('Initialization')+' ... 
    '); + // keydown event + $(this.content).find('#dashboard-console').keydown(this.bind(this,function(e){ + if (this.isDisabled() || this.isMinimized()) return; + if (!this.keys.ctrl_pressed && (e.keyCode==37 || e.keyCode==38 || e.keyCode==39 || e.keyCode==40 || e.keyCode==8 || e.keyCode==13)) { + e.stopPropagation();e.preventDefault(); + } + var cmd_prefix = $(this.content).find('#dashboard-console-line .dashboard-console-cmd-prefix'); + var cmd_suffix = $(this.content).find('#dashboard-console-line .dashboard-console-cmd-suffix'); + var txt_prefix = $(cmd_prefix).text(); + var txt_suffix = $(cmd_suffix).text(); + if (e.keyCode!=90 && e.keyCode!=17 && e.keyCode!=37 && e.keyCode!=39) { + this.captured_prefix = null; + this.captured_suffix = null; + } + // ctrl+z + if (!this.hide_input && e.keyCode==90 && this.keys.ctrl_pressed) { + if (this.captured_prefix!==null && this.captured_suffix!==null) { + $(cmd_prefix).html(this.captured_prefix); + $(cmd_suffix).html(this.captured_suffix); + this.captured_prefix = null; + this.captured_suffix = null; + } + // arrow left + } else if (!this.hide_input && e.keyCode==37 && txt_prefix.length>0) { + var c = txt_prefix.substr(-1); + $(cmd_suffix).prepend(c); + $(cmd_prefix).text(txt_prefix.substr(0,txt_prefix.length-1)); + // arrow right + } else if (!this.hide_input && e.keyCode==39 && txt_suffix.length>0) { + var c = txt_suffix.substr(0,1); + $(cmd_prefix).append(c); + $(cmd_suffix).text(txt_suffix.substr(1)); + // arrow up + } else if (!this.hide_input && e.keyCode==38 && this.execs.length>0 && this.execs.length>this.exec_index) { + this.exec_index++; + $(cmd_prefix).text(this.execs[this.execs.length-this.exec_index]); + $(cmd_suffix).text(''); + // arrow down + } else if (!this.hide_input && e.keyCode==40 && this.execs.length>0 && this.exec_index>1) { + this.exec_index--; + $(cmd_prefix).text(this.execs[this.execs.length-this.exec_index]); + $(cmd_suffix).text(''); + // backspace and delete (check selected text first) + } else if (e.keyCode==8 || e.keyCode==46) { + try { // delete selected text + if (this.hide_input) throw 'ignore'; + if (!window.getSelection().isCollapsed){ + var range = window.getSelection().getRangeAt(0); + if ($(range.startContainer).parents('.dashboard-console-cmd-prefix').length>0 || $(range.startContainer).parents('.dashboard-console-cmd-suffix').length>0 || $(range.endContainer).parents('.dashboard-console-cmd-prefix').length>0 || $(range.endContainer).parents('.dashboard-console-cmd-suffix').length>0){ + var startRange = range.cloneRange(); + var endRange = range.cloneRange(); + startRange.collapse(true); + endRange.collapse(false); + startRange.insertNode($('').get(0)); + endRange.insertNode($('').get(0)); + window.getSelection().removeAllRanges(); + var marker1 = $(this.content).find('#dashboard-console-line #dashboard-console-range-marker-start'); + var marker2 = $(this.content).find('#dashboard-console-line #dashboard-console-range-marker-end'); + if ($(marker1).parents('#dashboard-console-caret').length>0) $(marker1).appendTo(cmd_prefix); + if ($(marker2).parents('#dashboard-console-caret').length>0) $(marker2).appendTo(cmd_prefix); + if (txt_suffix.length>0){ + $(cmd_prefix).append($(cmd_suffix).html()); + $(cmd_suffix).html(''); + this.exec_index=0; + } + var p1 = $(cmd_prefix).html().indexOf(''); + if (p1<0) p1=0; + $(this.content).find('#dashboard-console-line #dashboard-console-range-marker-start').remove(); + var p2 = $(cmd_prefix).html().indexOf(''); + $(this.content).find('#dashboard-console-line #dashboard-console-range-marker-end').remove(); + var html_prefix = $(cmd_prefix).html(); + if (p2<0) p2 = html_prefix.length; + var html1 = html_prefix.substr(0,p1); + var html2 = html_prefix.substr(p2); + $(cmd_prefix).html(html1+html2); + } + return; + } + } catch(err) {} + // backspace if text is not selected + if (e.keyCode==8 && txt_prefix.length>0) $(cmd_prefix).text(txt_prefix.substr(0,txt_prefix.length-1)); + if (this.hide_input && e.keyCode==8 && this.hidden_input.length>0) this.hidden_input=this.hidden_input.substr(0,this.hidden_input.length-1); + // delete if text is not selected + else if (e.keyCode==46 && txt_suffix.length>0) $(cmd_suffix).text(txt_suffix.substr(1)); + // enter + } else if (e.keyCode==13) { + var dir = ''; + if (typeof(this.options.data.mode)!="undefined" && this.options.data.mode!='sh') dir = this.options.data.mode; + else if (typeof(this.options.data.cd)!="undefined" && this.options.data.cd!==null) dir = this.options.data.cd; + var _dir = dir.split('/').slice(-1).toString(); + if (_dir.length==0) _dir='/'; + var sign = '$'; + if (typeof(this.options.data.mode)!="undefined" && this.options.data.mode!='sh') sign = '>'; + if (!this.hide_input) $(this.content).find('#dashboard-console-line').before('
    '+_dir+' '+sign+' '+txt_prefix+txt_suffix+'
    '); + $(cmd_prefix).text(''); + $(cmd_suffix).text(''); + var cons = $(this.content).find('#dashboard-console'); + $(cons).scrollTop($(cons).get(0).scrollHeight); + if (!this.hide_input) { + this.options.data.exec=(txt_prefix+txt_suffix); + this.exec = this.options.data.exec; + this.options.data.secret = dash_console_encrypt(this.options.data.exec+this.options.data.mode+this.secret); + } else { + this.options.data.exec = dash_console_encrypt(this.hidden_input); + this.options.data.code = 'password'; + } + if (this.options.data.exec.length>0) { + $(this.content).find('#dashboard-console #dashboard-console-line').hide(); + if (this.exec_index>0 && this.execs[this.execs.length-1]!=this.options.data.exec) this.exec_index--; + if (this.exec_index>0) this.execs = this.execs.slice(0,this.execs.length-this.exec_index); + if (!this.hide_input && (this.execs.length==0 || this.execs[this.execs.length-1]!=this.options.data.exec)) this.execs.push(this.options.data.exec); + this.exec_index=0; + this.hidden_input=''; + this.loadBody(); + } + // ctrl + v + } else if (this.keys.ctrl_pressed && e.keyCode==86 && $(this.content).find('#dashboard-console #dashboard-console-clipboard').length==0) { + $(this.content).find('#dashboard-console').append(''); + $(this.content).find('#dashboard-console #dashboard-console-clipboard').focus(); + } + })); + // keypress event + $(this.content).find('#dashboard-console').keypress(this.bind(this,function(e){ + if (this.isDisabled() || this.isMinimized()) return; + if (e.which!=99 && e.which!=118) { e.stopPropagation();e.preventDefault(); } + if (e.altKey || e.ctrlKey) return; + var cmd_prefix = $(this.content).find('#dashboard-console-line .dashboard-console-cmd-prefix'); + var cmd_suffix = $(this.content).find('#dashboard-console-line .dashboard-console-cmd-suffix'); + var txt_prefix = $(cmd_prefix).text(); + var txt_suffix = $(cmd_suffix).text(); + if (e.which>0 && e.which!=13 && e.which!=8){ + var c = String.fromCharCode(e.which); + if (!this.hide_input) $(cmd_prefix).append(c); + else { this.hidden_input+=c; $(cmd_prefix).append('*'); } + var cons = $(this.content).find('#dashboard-console'); + $(cons).scrollTop($(cons).get(0).scrollHeight); + } + })); + // paste event + $(this.content).find('#dashboard-console').bind('paste',this.bind(this,function(e){ + this.captured_prefix = $(this.content).find('#dashboard-console-line .dashboard-console-cmd-prefix').html(); + this.captured_suffix = $(this.content).find('#dashboard-console-line .dashboard-console-cmd-suffix').html(); + var clipboard = $(this.content).find('#dashboard-console #dashboard-console-clipboard'); + if ($(clipboard).length>0){ + try { + var c = e.originalEvent.clipboardData.getData('text/plain'); + if (!this.hide_input) $(this.content).find('#dashboard-console-line .dashboard-console-cmd-prefix').append(c); + else { this.hidden_input+=c; $(this.content).find('#dashboard-console-line .dashboard-console-cmd-prefix').append('*'.repeat(c.length));} + var cons = $(this.content).find('#dashboard-console'); + $(cons).scrollTop($(cons).get(0).scrollHeight); + } catch(err){} + $(clipboard).remove(); + } + $(this.content).find('#dashboard-console').focus(); + })); +}; + +var dash_console_load = function() { + if (typeof(this.options.data.code)!="undefined" && this.options.data.code=='secret') { + this.secret = this.options.data.result; + this.options.data.exec = this.exec; + this.options.data.secret = dash_console_encrypt(this.options.data.exec+this.options.data.mode+this.secret); + this.options.data.result=null; + this.options.data.code=null; + this.hidden_input=''; + this.loadBody(); + } else if (typeof(this.options.data.code)!="undefined" && this.options.data.code=='password') { + $(this.content).find('#dashboard-console #dashboard-console-line').show(); + $(this.content).find('#dashboard-console #dashboard-console-caret').css('visibility','visible'); + this.hide_input = true; + $(this.content).find('#dashboard-console #dashboard-console-line .dashboard-console-dir').attr('title','').text(t('Password')); + $(this.content).find('#dashboard-console #dashboard-console-line .dashboard-console-sign').text(':'); + } else { + $(this.content).find('#dashboard-console #dashboard-console-line').show(); + $(this.content).find('#dashboard-console #dashboard-console-caret').css('visibility','visible'); + this.hide_input = false; + $(this.content).find('#dashboard-console #dashboard-console-line .dashboard-console-dir').text(''); + $(this.content).find('#dashboard-console #dashboard-console-line .dashboard-console-sign').text(''); + if (typeof(this.options.data.cd)!="undefined" && this.options.data.cd!==null){ + var _dir = this.options.data.cd.split('/').slice(-1).toString(); + if (_dir.length==0) _dir='/'; + $(this.content).find('#dashboard-console #dashboard-console-line .dashboard-console-dir').attr('title',this.options.data.cd).text(_dir); + } + if (typeof(this.options.data.result)!="undefined" && this.options.data.result!==null){ + $(this.content).find('#dashboard-console-line').before('
    '+this.options.data.result+'
    '); + } + if (typeof(this.options.data.mode)!="undefined" && this.options.data.mode!='sh'){ + $(this.content).find('#dashboard-console #dashboard-console-line .dashboard-console-sign').text('>'); + $(this.content).find('#dashboard-console #dashboard-console-line .dashboard-console-dir').text(this.options.data.mode); + $(this.content).find('#dashboard-console #dashboard-console-line .dashboard-console-dir').attr('title',this.options.data.mode); + } else { + $(this.content).find('#dashboard-console #dashboard-console-line .dashboard-console-sign').text('$'); + } + } + if (typeof(this.options.data.code)!="undefined" && this.options.data.code=='exit'){ + this.getCloseButton().trigger('click'); + } else { + var cons = $(this.content).find('#dashboard-console'); + $(cons).scrollTop($(cons).get(0).scrollHeight); + this.options.data.result=null; + } + this.options.data.code=null; + this.hidden_input=''; +}; + +var dash_console_focus = function() { + $(this.content).find('#dashboard-console #dashboard-console-caret').css('visibility','visible'); + $(this.content).find('#dashboard-console').focus(); +}; + +var dash_console_blur = function() { + $(this.content).find('#dashboard-console #dashboard-console-caret').css('visibility','hidden'); + $(this.content).find('#dashboard-console').blur(); +}; + +var dash_console_encrypt = function(str) { + return md5(encodeURIComponent(str).replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\!/g, '%21').replace(/\*/g, '%2A')); +} \ No newline at end of file diff --git a/assets/js/dash/contacts.js b/assets/js/dash/contacts.js new file mode 100644 index 0000000..aa9de66 --- /dev/null +++ b/assets/js/dash/contacts.js @@ -0,0 +1,13 @@ +var dash_contacts_load = function() { + desk_window_form_init(this); + $(this.content).find('input.picture_option').parent().append(''); + $(this.content).find('input.picture_option').parent().children('.glyphicon').click(this.bind(this, function(){ + desk_file_selector(function(selected){ + if (selected && selected.length>0 && typeof(selected[0].type)!="undefined" && selected[0].type=='image') { + var src = selected[0].data; + var regexp = new RegExp('\\'+desk_ds, 'g'); + $(this.content).find('input.picture_option').val(src.replace(regexp,'/')); + } + }, this); + })); +}; \ No newline at end of file diff --git a/assets/js/dash/cron.js b/assets/js/dash/cron.js new file mode 100644 index 0000000..69c0501 --- /dev/null +++ b/assets/js/dash/cron.js @@ -0,0 +1,12 @@ +var dash_cron_open = function() { + desk_window_request(this, url('cron'), {}, this.bind(this, function(response){ + var output = ''; + if (response && response.length>0) { + for (var i=0; i'; + } + } + this.clearBodyContent(); + this.appendBodyContent(output); + })); +}; \ No newline at end of file diff --git a/assets/js/dash/editor.js b/assets/js/dash/editor.js new file mode 100644 index 0000000..fc2171e --- /dev/null +++ b/assets/js/dash/editor.js @@ -0,0 +1,162 @@ +var dash_editor_text_focus = function() { + $(this.content).find('textarea').focus(); +}; + +var dash_editor_text_load = function() { + this.contentModified = false; + $(this.content).find('textarea').focus(); + $(this.content).find('textarea').eq(0).keyup(this.bind(this, function(){ + var val = $(this.content).find('textarea').eq(0).val(); + this.resetFooterContent(); + this.appendFooterContent(val.length); + this.contentModified = true; + })); + var val = $(this.content).find('textarea').eq(0).val(); + this.resetFooterContent(); + this.appendFooterContent(val.length); +}; + +var dash_editor_html_focus = function() { + var l=''; + if (typeof(this.editor)!="undefined") { + this.editor.focus(); + l = this.editor.getContent().replace(/ /g,'').replace(/<[\s\S]*?>/g,'').length; + } + this.resetFooterContent(); + this.appendFooterContent(l); +}; + +var dash_editor_html_blur = function() { + try { + this.editor.iframeElement.blur(); + } catch(err) {} +}; + +var dash_editor_html_resize = function() { + if (typeof(this.editor)=="undefined") return; + var content_height = $(this.content).height(); + var editor_panel_height = $(this.content).find('.mce-toolbar[role=toolbar]').eq(0).parents('.mce-panel').outerHeight(); + this.editor.theme.resizeTo('100%',content_height-editor_panel_height); +}; + +var dash_editor_html_update = function() { + if (typeof(this.editor)=="undefined") return; + $(this.content).find('textarea[name=content]').val(this.editor.getContent()); +}; + +var dash_editor_html_drop = function(element) { + if (typeof(this.editor)=="undefined") return; + if (element instanceof FileList) return; + if (typeof(element)!="object" || typeof(element.type)=="undefined" || typeof(element.data)=="undefined" || typeof(element.title)=="undefined") return; + if (typeof(element.parent)=="undefined") return; + var html = ''; + if (element.parent=='files' && element.type=='image') { + var width = ''; + var height = ''; + if (typeof(element.image_width)!="undefined") width=element.image_width; + if (typeof(element.image_height)!="undefined") height=element.image_height; + var regexp = new RegExp('\\'+desk_ds, 'g'); + html=''+element.title+''; + } else if (element.parent=='files' && element.type!='folder') { + html=''+element.title+''; + } else if (element.parent=='record' && typeof(element.typo)!="undefined" && element.typo=='record' && typeof(element.page)!="undefined") { + var language = ''; + if (typeof(element.language)!="undefined" && element.language!==null) language = element.language + '/'; + var page = url(language+element.page); + var title = element.tooltip && element.tooltip.length>0 ? element.tooltip : element.title; + html=''+title+''; + } + if (html.length>0){ + this.editor.execCommand('mceInsertContent', false, html); + } +}; + +var dash_editor_html_load = function() { + this.contentModified = false; + tinymce.init({ + selector:'#'+$(this.content).find('.editable').attr('id') , + plugins: 'paste, advlist, link, image, media, table, hr, pagebreak, code, contextmenu', + toolbar: ['desk_save | undo redo | table | bullist numlist | desk_file_selector image media link | outdent indent | hr pagebreak | code', 'styleselect | bold italic underline removeformat | aligncenter alignleft alignright alignjustify '], + menubar: false, + language: dash_editor_language, + paste_word_valid_elements: 'b,strong,i,em,h1,h2,h3,h4,h5,h6,p,ul,ol,li,hr,br,table,tr,td', + paste_filter_drop: false, + convert_urls: false, + statusbar: false, + auto_focus: true, + init_instance_callback: this.bind(this, function (editor) { + this.editor = editor; + this.onResize(); + window.setTimeout(this.bind(this, this.onResize),1000); + var openDialog = editor.windowManager.open; + editor.windowManager.open = function(args, params){ + Desk.disableEvents(); + var modal = openDialog.call(this, args, params); + modal.on('close', function(){ + window.setTimeout(Desk.bind(Desk,Desk.enableEvents,500)); + }); + return modal; + }; + editor.on('focus', this.bind({'desk':Desk,'wnd':this},function(){ + this.desk.focusWindow(this.wnd); + this.wnd.onResize(); + if (this.wnd.isMenuDropdownOpened()) this.wnd.hideMenuDropdown(); + })); + $(editor.getBody()).keydown(this.bind(Desk, function(e){ + if (e.shiftKey && e.keyCode==9) { + this.shift_pressed = true; this.keys_pressed = 1; this.onKeyDown(e); this.keys_pressed = 1; this.onKeyUp(e); + } else if (e.ctrlKey && (e.keyCode==37 || e.keyCode==38 || e.keyCode==39 || e.keyCode==40)) { + this.ctrl_pressed = true; this.keys_pressed = 1; this.onKeyDown(e); this.onKeyUp(e); + } else if (e.ctrlKey && e.keyCode==83) { + this.ctrl_pressed = true; this.keys_pressed = 1; this.onKeyDown(e); this.onKeyUp(e); + } else if (!e.ctrlKey && !e.shiftKe && e.keyCode==27) { + this.keys_pressed = 0; this.onKeyDown(e); this.onKeyUp(e); + } + })); + $(editor.getBody()).keyup(this.bind(this, function(e){ + if (!this.isInitialized() || this.isDisabled() || this.isMinimized()) { + e.stopPropagation(); e.preventDefault(); + } + var l=''; + if (typeof(this.editor)!="undefined") { + l = this.editor.getContent().replace(/ /g,'').replace(/<[\s\S]*?>/g,'').length; + } + this.resetFooterContent(); + this.appendFooterContent(l); + this.contentModified = true; + })); + $(this.editor.getDoc()).unbind('dragover').bind('dragover',this.bind({'desk':Desk,'wnd':this}, function(e){this.desk.focusWindow(this.wnd);})); + $(this.editor.getDoc()).unbind('drop').bind('drop',this.bind(Desk, function(e){this.onDrop(e);})); + }), + content_css: dash_editor_css, + setup: this.bind(this,function(editor){ + editor.addButton('desk_save',{ 'icon': 'save', 'title':t('Save'), 'onclick': this.bind(this,function(){ + desk_window_save(this); + })}); + editor.addButton('desk_file_selector',{ 'icon': 'browse', 'title':t('File manager'), 'onclick': this.bind(this,function(){ + desk_file_selector(this.bind(this,function(elements){ + for (var i=0; i0) html+= ' '; + if (element.type=='image') { + var width = ''; + var height = ''; + if (typeof(element.image_width)!="undefined") width=element.image_width; + if (typeof(element.image_height)!="undefined") height=element.image_height; + var regexp = new RegExp('\\'+desk_ds, 'g'); + html+=''+element.title+''; + } else if (element.type!='folder') html+=''+element.title+''; + if (html.length>0){ + this.editor.execCommand('mceInsertContent', false, html); + } + } + })); + })}); + }) + }); +}; \ No newline at end of file diff --git a/assets/js/dash/files.js b/assets/js/dash/files.js new file mode 100644 index 0000000..e056d6e --- /dev/null +++ b/assets/js/dash/files.js @@ -0,0 +1,206 @@ +var dash_files_load = function() { + $(this.element).find('.filemanager-infobar').html(''); + var item = this.findToolbarItemByProperty('action','level'); + var root = this.options.data.root.split(desk_ds).slice(0,-1); + if (root.length>0) { + this.enableToolbarItem(item); + } else { + this.disableToolbarItem(item); + } +}; + +var dash_files_open = function() { + if (typeof(this.options.data)!="undefined" && typeof(this.options.data.max_upload_size)!="undefined") this.max_upload_size=this.options.data.max_upload_size; else this.max_upload_size=null; + $(this.element).find('.dashwindow-upload-form input[type=file]').change(this.bind(this, function(){ + var root = this.options.data.root; + desk_upload(token(),url('dash/files/xhrupload'), root, $(this.element).find('.dashwindow-upload-form input[type=file]').get(0).files, null, this.max_upload_size, this.className); + })); + this.disableItemsByProperty('action','call'); +}; + +var dash_files_drop = function(element) { + if (element instanceof FileList) { + var root = this.options.data.root; desk_upload(token(),url('dash/files/xhrupload'), root, element, null, this.max_upload_size, this.className); + } else if (typeof(element.parent)!="undefined" && element.parent=='files') { + desk_window_request(this, url('dash/files/copy'),{'path':this.options.data.root, 'file':element.data}); + } +}; + +var dash_files_select = function() { + var selected = this.getSelectedContentItems(); + if (!selected || selected.length!=1) this.disableItemsByProperty('action','call'); + else this.enableItemsByProperty('action','call'); + if (!selected || selected.length!=1 || typeof(selected[0].type)=="undefined" || selected[0].type=='folder') { + this.disableItemsByProperty('typo','download'); + } + if (!selected || selected.length!=1 || typeof(selected[0].type)=="undefined" || selected[0].type!='archive') { + this.disableItemsByProperty('typo','archive'); + } + if (!selected || selected.length!=1 || typeof(selected[0].type)=="undefined" || (selected[0].type!='image' && selected[0].type!='txt' && selected[0].type!='html')) { + this.disableItemsByProperty('action','edit'); + } + if (!selected || selected.length!=1 || typeof(selected[0].type)=="undefined" || selected[0].type=='folder' || selected[0].type=='image'|| selected[0].type=='archive') { + this.disableItemsByProperty('typo','notepad'); + } + if (!selected || selected.length!=1 || typeof(selected[0].type)=="undefined" || selected[0].type!='image') { + this.disableItemsByProperty('typo','show_image'); + } + if (selected && selected.length && selected.length==1 && (typeof(this.info_last_item)=="undefined" || this.info_last_item!=selected[0].data || $(this.element).find('.filemanager-infobar').html().length==0)) { + this.info_last_item = selected[0].data; + $(this.element).find('.filemanager-infobar').html(''); + try { window.clearTimeout(this.timer); } catch(err) {}; + this.timer = window.setTimeout(this.bind(this,function(){ + $(this.element).find('.filemanager-infobar').html(''); + var selected = this.getSelectedContentItems(); + if (!selected || !selected.length || selected.length!=1) return; + desk_post(url('dash/files/info'),{'dirroot':this.options.data.root,'file':selected[0].data, 'token':token()}, this.bind(this, function(response){ + if (response && response.length>0) { + $(this.element).find('.filemanager-infobar').append('
    '+t('Information')+':
    '); + $(this.element).find('.filemanager-infobar').append('
    '); + for (var i=0; i'+response[i]+'
    '); + } + } + })); + }),1000); + } +}; + +var dash_files_up = function() { + var root = this.options.data.root.split(desk_ds).slice(0,-1); + if (root.length>0) { + this.options.data.root=root.join(desk_ds); + this.options.data.page=1; + desk_window_reload(this); + } +}; + +var dash_files_mkdir = function() { + desk_prompt(t('Enter name'), this.bind(this, function(name){ + var root = this.options.data.root; + desk_window_request(this, url('dash/files/mkdir'),{'name':name, 'root':root}); + })); +}; + +var dash_files_new_text_file = function() { + desk_prompt(t('Enter name'), this.bind(this, function(name){ + var root = this.options.data.root; + desk_window_request(this, url('dash/files/textfile'),{'name':name, 'root':root}); + })); +}; + +var dash_files_new_html_file = function() { + desk_prompt(t('Enter name'), this.bind(this, function(name){ + var root = this.options.data.root; + desk_window_request(this, url('dash/files/htmlfile'),{'name':name, 'root':root}); + })); +}; + +var dash_files_rename = function() { + var selected = desk_window_selected(this); + if (typeof(selected.items)!="undefined" && selected.items.length==1) { + desk_prompt(t('Enter name'), this.bind(this, function(name){ + desk_window_request(this, url('dash/files/rename'),{'name':name, 'file':selected.items[0]}); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(selected.items[0].split(desk_ds).slice(-1)[0]); + } +}; + +var dash_files_upload_url = function() { + desk_prompt(t('Enter URL address'),this.bind(this, function(address) { + var root = this.options.data.root; + if (address.length>0) { + desk_window_request(this, url('dash/files/xhruploadsrc'), {'dirroot': root, 'url': address}); + } + })); +}; + +var dash_files_download = function() { + var selected = this.getSelectedContentItems(); + if (selected.length==1 && typeof(selected[0].type)!="undefined" && selected[0].type!='folder') { + var a=document.createElement('a'); + var regexp = new RegExp('\\'+desk_ds, 'g'); + a.href=baseUrl(selected[0].data.replace(regexp, '/')); + a.download=selected[0].data.split(desk_ds).slice(-1)[0]; + document.body.appendChild(a); + HTMLElementClick.call(a); + document.body.removeChild(a); + } +}; + +var dash_files_copy = function() { + var selected = desk_window_selected(this); + if (typeof(selected.items)!="undefined" && selected.items.length==1) { + desk_prompt(t('Enter folder path'), this.bind(this, function(path){ + desk_window_request(this, url('dash/files/copy'),{'path':path, 'file':selected.items[0]}); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(selected.items[0].split(desk_ds).slice(0,-1).join(desk_ds)); + } +}; + +var dash_files_move = function() { + var selected = desk_window_selected(this); + if (typeof(selected.items)!="undefined" && selected.items.length==1) { + desk_prompt(t('Enter folder path'), this.bind(this, function(path){ + desk_window_request(this, url('dash/files/move'),{'path':path, 'file':selected.items[0]}); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(selected.items[0].split(desk_ds).slice(0,-1).join(desk_ds)); + } +}; + +var dash_files_pack = function() { + var selected = desk_window_selected(this); + if (typeof(selected.items)!="undefined" && selected.items.length>0) { + desk_prompt(t('Enter archive name'), this.bind(this, function(name){ + var root = this.options.data.root; + desk_window_request(this, url('dash/files/pack'),{'name':name, 'files':selected.items, 'dirroot': root}); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(selected.items[0].split(desk_ds).slice(-1)[0].split('.')[0]); + } +}; + +var dash_files_unpack = function() { + var selected = this.getSelectedContentItems(); + if (selected.length==1 && typeof(selected[0].type)!="undefined" && selected[0].type=='archive') { + desk_prompt(t('Enter folder path'), this.bind(this, function(path){ + desk_window_request(this, url('dash/files/unpack'),{'dirroot':path, 'file':selected[0].data}); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(this.options.data.root); + } +}; + +var dash_files_notepad = function() { + var selected = this.getSelectedContentItems(); + if (!selected || selected.length!=1) return; + var data=selected[0].data; + desk_text_editor(data); +}; + +var dash_files_show_image = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].image_url)!="undefined" && selected[0].image_url.length>0) { + $('body').append(''); + $('#dashwindow-filemanager-zoomer-lightbox').trigger('click'); + $('#dashwindow-filemanager-zoomer-lightbox').remove(); + } +}; + +var dash_files_edit = function() { + try { window.clearTimeout(this.timer); } catch(err) {}; + var selected = this.getSelectedContentItems(); + if (!selected || selected.length!=1) return; + var data=selected[0].data; + if (typeof(selected[0].type)!="undefined" && selected[0].type=='folder') { + this.options.data.root=data; + this.options.data.page=1; + desk_window_reload(this); + } else if (typeof(selected[0].type)!="undefined" && selected[0].type=='archive') { + desk_call(dash_files_unpack, this); + } else if (typeof(selected[0].type)!="undefined" && selected[0].type=='txt') { + desk_text_editor(data); + } else if (typeof(selected[0].type)!="undefined" && selected[0].type=='html') { + desk_html_editor(data); + } else if (typeof(selected[0].type)!="undefined" && selected[0].type=='image') { + desk_image_editor(data); + } +}; \ No newline at end of file diff --git a/assets/js/dash/groups.js b/assets/js/dash/groups.js new file mode 100644 index 0000000..c68a593 --- /dev/null +++ b/assets/js/dash/groups.js @@ -0,0 +1,85 @@ +var dash_groups_load = function() { + for (var i=0; i0) { + desk_window_request(this, url('dash/groups/deactivate'),{'groups':selected.items}); + } +}; + +var dash_groups_activate = function() { + var selected = desk_window_selected(this); + if (selected && typeof(selected.items)!="undefined" && selected.items.length>0) { + desk_window_request(this, url('dash/groups/activate'),{'groups':selected.items}); + } +}; + +var dash_groups_select = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length>0) { + this.disableItemsByProperty('typo','deactivate'); + for (var i=0; i
    '); + this.options.data.image=$(this.content).find('img'); + $(this.options.data.image).parent('div').css({'display':'table-cell','height':'100%','textAlign':'center','verticalAlign':'middle'}); + $(this.options.data.image).parent('div').parent('div').css({'display':'table-row'}); + $(this.options.data.image).parent('div').parent('div').parent('div').css({'display':'table','width':'100%','height':'100%'}); + this.enableItemsByProperty('action','zoom'); + this.enableItemsByProperty('action','resize'); + this.enableItemsByProperty('action','reload'); + this.enableItemsByProperty('action','crop'); + this.enableItemsByProperty('action','save'); + this.enableItemsByProperty('action','watermark'); + this.updateTitle(this.options.data.file); + this.resetFooterContent(); + this.appendFooterContent(this.options.data.image_width+'x'+this.options.data.image_height+'px'); + }); + var regexp = new RegExp('\\'+desk_ds, 'g'); + this.options.data.image.src=baseUrl(this.options.data.file.replace(regexp,'/'))+'?t='+(new Date().getTime()); + })); +}; + +var dash_image_close = function() { + if (typeof(this.options.data)=="undefined" || typeof(this.options.data.file)=="undefined") return; + desk_window_request(this,url('dash/image/close'),{'file':this.options.data.file}); +}; + +var dash_image_resize = function() { + if (typeof(this.cropper)!="undefined" && this.cropper!=null) { + this.cropper.destroy(); + this.cropper = null; + this.disableItemsByProperty('action','cut'); + this.disableItemsByProperty('action','ratio'); + } +}; + +var dash_image_focus = function() { + if (typeof(this.cropper)=="undefined" || this.cropper===null) return; + this.cropper.disabled = false; +}; + +var dash_image_blur = function() { + if (typeof(this.cropper)=="undefined" || this.cropper===null) return; + this.cropper.disabled = true; +}; + +var dash_image_save = function() { + desk_confirm(t('Replace image ?'), this.bind(this, function(){ + desk_window_request(this, url('dash/image/save'), {'file': this.options.data.file}, this.bind(this, function(response){ + if (!response || !response.message) return; + desk_window_reload_all(dash_image_files_wnd); + })); + })); +}; + +var dash_image_zoom_in = function() { + if (typeof(this.cropper)!="undefined" && this.cropper!=null) { + this.cropper.destroy(); + this.cropper = null; + this.disableItemsByProperty('action','cut'); + this.disableItemsByProperty('action','ratio'); + } + var width = $(this.options.data.image).width(); + var height = $(this.options.data.image).height(); + $(this.options.data.image).css({'width':width*2,'height':height*2}); +}; + +var dash_image_zoom_out = function() { + if (typeof(this.cropper)!="undefined" && this.cropper!=null) { + this.cropper.destroy(); + this.cropper = null; + this.disableItemsByProperty('action','cut'); + this.disableItemsByProperty('action','ratio'); + } + var width = $(this.options.data.image).width(); + var height = $(this.options.data.image).height(); + if (width<10 || height<10) return; + $(this.options.data.image).css({'width':width/2,'height':height/2}); +}; + +var dash_image_change_width = function() { + if (typeof(this.cropper)!="undefined" && this.cropper!=null) { + this.cropper.destroy(); + this.cropper = null; + this.disableItemsByProperty('action','cut'); + this.disableItemsByProperty('action','ratio'); + } + desk_prompt(t('Image width'), this.bind(this, function(width){ + var _width = parseInt(width); + if (_width<=0) return; + desk_window_request(this, url('dash/image/width'),{'width':_width, 'file':this.options.data.file}, this.bind(this, function(response){ + if (!response || !response.width || !response.height) return; + this.options.data.image_width=response.width; + this.options.data.image_height=response.height; + $(this.options.data.image).css({'width':response.width,'height':response.height}); + if (response.src) $(this.options.data.image).attr('src',response.src); + this.resetFooterContent(); + this.appendFooterContent(this.options.data.image_width+'x'+this.options.data.image_height+'px'); + }), function(){ + desk_error(t('An error occurred')); + }); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(this.options.data.image_width); +}; + +var dash_image_change_height = function() { + if (typeof(this.cropper)!="undefined" && this.cropper!=null) { + this.cropper.destroy(); + this.cropper = null; + this.disableItemsByProperty('action','cut'); + this.disableItemsByProperty('action','ratio'); + } + desk_prompt(t('Image height'), this.bind(this, function(height){ + var _height = parseInt(height); + if (_height<=0) return; + desk_window_request(this, url('dash/image/height'),{'height':_height, 'file':this.options.data.file}, this.bind(this, function(response){ + if (!response || !response.width || !response.height) return; + this.options.data.image_width=response.width; + this.options.data.image_height=response.height; + $(this.options.data.image).css({'width':response.width,'height':response.height}); + if (response.src) $(this.options.data.image).attr('src',response.src); + this.resetFooterContent(); + this.appendFooterContent(this.options.data.image_width+'x'+this.options.data.image_height+'px'); + }), function(){ + desk_error(t('An error occurred')); + }); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(this.options.data.image_height); +}; + +var dash_image_crop_width = function() { + if (typeof(this.cropper)!="undefined" && this.cropper!=null) { + this.cropper.destroy(); + this.cropper = null; + this.disableItemsByProperty('action','cut'); + this.disableItemsByProperty('action','ratio'); + } + desk_prompt(t('Image width'), this.bind(this, function(width){ + var _width = parseInt(width); + if (_width<=0) return; + desk_window_request(this, url('dash/image/cropwidth'),{'width':_width, 'file':this.options.data.file}, this.bind(this, function(response){ + if (!response || !response.width || !response.height) return; + this.options.data.image_width=response.width; + this.options.data.image_height=response.height; + $(this.options.data.image).css({'width':response.width,'height':response.height}); + if (response.src) $(this.options.data.image).attr('src',response.src); + this.resetFooterContent(); + this.appendFooterContent(this.options.data.image_width+'x'+this.options.data.image_height+'px'); + }), function(){ + desk_error(t('An error occurred')); + }); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(this.options.data.image_width); +}; + +var dash_image_crop_height = function() { + if (typeof(this.cropper)!="undefined" && this.cropper!=null) { + this.cropper.destroy(); + this.cropper = null; + this.disableItemsByProperty('action','cut'); + this.disableItemsByProperty('action','ratio'); + } + desk_prompt(t('Image height'), this.bind(this, function(height){ + var _height = parseInt(height); + if (_height<=0) return; + desk_window_request(this, url('dash/image/cropheight'),{'height':_height, 'file':this.options.data.file}, this.bind(this, function(response){ + if (!response || !response.width || !response.height) return; + this.options.data.image_width=response.width; + this.options.data.image_height=response.height; + $(this.options.data.image).css({'width':response.width,'height':response.height}); + if (response.src) $(this.options.data.image).attr('src',response.src); + this.resetFooterContent(); + this.appendFooterContent(this.options.data.image_width+'x'+this.options.data.image_height+'px'); + }), function(){ + desk_error(t('An error occurred')); + }); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(this.options.data.image_height); +}; + +var dash_image_reload = function() { + if (typeof(this.cropper)!="undefined" && this.cropper!=null) { + this.cropper.destroy(); + this.cropper = null; + this.disableItemsByProperty('action','cut'); + this.disableItemsByProperty('action','ratio'); + } + desk_window_request(this, url('dash/image/open'), {'file':this.options.data.file}, this.bind(this, function(response){ + if (!response || !response.width || !response.height || !response.src) return; + this.options.data.image_width=response.width; + this.options.data.image_height=response.height; + $(this.options.data.image).css({'width':response.width,'height':response.height}); + $(this.options.data.image).attr('src',response.src); + this.resetFooterContent(); + this.appendFooterContent(this.options.data.image_width+'x'+this.options.data.image_height+'px'); + })); +}; + +var dash_image_crop = function() { + if (typeof(this.cropper)!="undefined" && this.cropper!=null) { + this.cropper.destroy(); + this.cropper = null; + this.disableItemsByProperty('action','cut'); + this.disableItemsByProperty('action','ratio'); + } else { + this.enableItemsByProperty('action','cut'); + this.enableItemsByProperty('action','ratio'); + this.disableItemsByProperty('typo','0_0'); + this.cropper = $(this.options.data.image).cropper({'preview':false,'block_mode':true,'fixed':false,'sel_w':$(this.options.data.image).width()/2,'sel_h':$(this.options.data.image).height()/2,'sel_mw':10,'sel_mh':10}); + $(this.content).unbind('dblclick').on('dblclick','.image-cropper-selector',this.bind(this, function(){ + desk_call(dash_image_cut, this); + })); + } +}; + +var dash_image_aspect_ratio = function(element) { + if (!this.cropper) return; + this.cropper.destroy(); + var id = $(element).attr('id'); + var item = this.findToolbarItemByProperty('id',id); + if (!item.typo) return; + var ratio=item.typo.split('_'); + if (ratio.length!=2) return; + ratio[0]=parseInt(ratio[0]); + ratio[1]=parseInt(ratio[1]); + this.enableItemsByProperty('action','ratio'); + this.disableItemsByProperty('typo',item.typo); + if (!ratio[0] || !ratio[1]) { + this.cropper = $(this.options.data.image).cropper({'preview':false,'block_mode':true,'fixed':false,'sel_w':$(this.options.data.image).width()/2,'sel_h':$(this.options.data.image).height()/2,'sel_mw':10,'sel_mh':10}); + } else { + var w, h; + if (this.options.data.image_width/this.options.data.image_height > ratio[0]/ratio[1]) { + h = $(this.options.data.image).height()/2; + w = (h * ratio[0]) / ratio[1]; + } else { + w = $(this.options.data.image).width()/2; + h = (w * ratio[1]) / ratio[0]; + } + this.cropper = $(this.options.data.image).cropper({'preview':false,'block_mode':true,'fixed':true,'sel_w':w,'sel_h':h,'sel_mw':10,'sel_mh':10}); + } +}; + +var dash_image_cut = function() { + if (!this.cropper) return; + var rect = this.cropper.getRect(); + this.cropper.destroy(); + this.cropper = null; + this.disableItemsByProperty('action','cut'); + this.disableItemsByProperty('action','ratio'); + desk_window_request(this, url('dash/image/crop'), {'file': this.options.data.file, 'width': rect.w, 'height': rect.h, 'left': rect.x, 'top': rect.y}, this.bind(this, function(response){ + if (!response || !response.width || !response.height || !response.src) return; + this.options.data.image_width=response.width; + this.options.data.image_height=response.height; + $(this.options.data.image).css({'width':response.width,'height':response.height}); + $(this.options.data.image).attr('src',response.src); + this.resetFooterContent(); + this.appendFooterContent(this.options.data.image_width+'x'+this.options.data.image_height+'px'); + })); +}; + +var dash_image_save_as = function() { + desk_prompt(t('Enter name'), this.bind(this, function(name){ + if (!name || name.length==0) return; + desk_window_request(this, url('dash/image/saveas'), {'file': this.options.data.file, 'name': name}, this.bind(this, function(response){ + if (!response || !response.message) return; + desk_window_reload_all(dash_image_files_wnd); + })); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(this.options.data.file.split(desk_ds).slice(-1)[0].split('.').slice(0)[0]); +}; + +var dash_image_watermark = function() { + desk_window_request(this, url('dash/image/watermark'), {'file': this.options.data.file}, this.bind(this, function(response){ + if (!response || !response.width || !response.height || !response.src) return; + this.options.data.image_width=response.width; + this.options.data.image_height=response.height; + $(this.options.data.image).css({'width':response.width,'height':response.height}); + $(this.options.data.image).attr('src',response.src); + this.resetFooterContent(); + this.appendFooterContent(this.options.data.image_width+'x'+this.options.data.image_height+'px'); + })); +}; + +var desk_image_editor = function(file) { + try { + var data = {'file':file}; + desk_call(dash_image_wnd, null, {'data':data}); + } catch(e) { + desk_error(t('An error occurred')); + } +}; \ No newline at end of file diff --git a/assets/js/dash/languages.js b/assets/js/dash/languages.js new file mode 100644 index 0000000..5860b2c --- /dev/null +++ b/assets/js/dash/languages.js @@ -0,0 +1,75 @@ +var dash_languages_load = function() { + for (var i=0; i0) { + $(this.element).find('.logs-infobar').append('
    '+t('Information')+':
    '); + $(this.element).find('.logs-infobar').append('
    '); + for (var i=0; i'+response[i]+''); + } + } + })); + }),1000); + } +}; \ No newline at end of file diff --git a/assets/js/dash/mailing.js b/assets/js/dash/mailing.js new file mode 100644 index 0000000..3e72b56 --- /dev/null +++ b/assets/js/dash/mailing.js @@ -0,0 +1,80 @@ +var dash_mailing_load = function() { + desk_window_form_init(this); + var users = this.findToolbarItemByProperty('action','users'); + if (users) { + $(users.element).text(t('Message')+' ('+this.options.data.users+')'); + } + var subscribers = this.findToolbarItemByProperty('action','subscribers'); + if (subscribers) { + $(subscribers.element).text(t('Email')+' ('+this.options.data.subscribers+')'); + } + var type = $(this.content).find('.dash-mailing-type').eq(0).val(); + if (type == 'email') { + this.enableItemsByProperty('action','users'); + } else if (type == 'message') { + this.enableItemsByProperty('action','subscribers'); + } + $(this.content).find('.dash-mailing-subject').unbind('keyup').keyup(this.bind(this,function(e){ + var subject_l = $(this.content).find('.dash-mailing-subject').eq(0).val().length; + var message_l = $(this.content).find('.dash-mailing-message').eq(0).val().length; + if (subject_l>0 && message_l>0){ + this.enableItemsByProperty('action','mail'); + } else { + this.disableItemsByProperty('action','mail'); + } + })); + $(this.content).find('.dash-mailing-message').unbind('keyup').keyup(this.bind(this,function(e){ + var subject_l = $(this.content).find('.dash-mailing-subject').eq(0).val().length; + var message_l = $(this.content).find('.dash-mailing-message').eq(0).val().length; + if (subject_l>0 && message_l>0){ + this.enableItemsByProperty('action','mail'); + } else { + this.disableItemsByProperty('action','mail'); + } + $(this.content).find('.dash-mailing-message').eq(0).parent().children('.help-block').text(message_l); + })); + this.mail = function(){ + $(this.content).find('.dash-mailing-offset').eq(0).val(this.options.data.offset); + var data = desk_window_content(this); + desk_window_request(this, url('dash/system/mailing'), data, this.bind(this, function(response){ + if (!response || typeof(response.error)!="undefined") { + desk_modal_progress_hide(); + return; + } + if (response.left>0){ + this.options.data.offset = ++response.offset; + desk_modal_progress_update(Math.round((response.sent / response.total)*100)); + desk_window_request.finish_callback = this.bind(this, this.mail); + } else { + this.options.data.offset = 0; + desk_modal_progress_hide(); + if (response.type=='email'){ + desk_message(t('Successfully finished. Emails sent:')+' '+response.sent); + } else if (response.type=='message'){ + desk_message(t('Successfully finished. Messages sent:')+' '+response.sent); + } + } + })); + }; +}; + +var dash_mailing_type_email = function() { + this.enableItemsByProperty('action','users'); + this.disableItemsByProperty('action','subscribers'); + $(this.content).find('.dash-mailing-type').eq(0).val('email'); +}; + +var dash_mailing_type_message = function() { + this.enableItemsByProperty('action','subscribers'); + this.disableItemsByProperty('action','users'); + $(this.content).find('.dash-mailing-type').eq(0).val('message'); +}; + +var dash_mialing_send = function() { + var subject = $(this.content).find('.dash-mailing-subject').eq(0).val(); + var message = $(this.content).find('.dash-mailing-message').eq(0).val(); + if (subject.length>0 && message.length>0) { + desk_modal_progress(); + this.mail(); + } +}; \ No newline at end of file diff --git a/assets/js/dash/menu.js b/assets/js/dash/menu.js new file mode 100644 index 0000000..6f77075 --- /dev/null +++ b/assets/js/dash/menu.js @@ -0,0 +1,239 @@ +var dash_menu_open = function() { + this.nested_level = 0; + this.previous = []; + desk_call(dash_menu_drag, this); +}; + +var dash_menu_load = function() { + var sidebarItem; + var menu = this.options.data.menu; + if (menu == dash_menu_primary_id || menu == dash_menu_secondary_id) { + sidebarItem = this.findSidebarItemByProperty('typo','topmenu'); + } else if (menu == dash_menu_footer_id) { + sidebarItem = this.findSidebarItemByProperty('typo','bottommenu'); + } + if (sidebarItem) { + $(sidebarItem.element).addClass('active'); + } + if (this.options.data.parent) { + this.enableItemsByProperty('action','level'); + } else { + this.disableItemsByProperty('action','level'); + } + for (var i=0; i this.dragStartY) { + $(this.content).find('#'+this.dragOverItem).parent('li').after(tmp); + } else { + $(this.content).find('#'+this.dragOverItem).parent('li').before(tmp); + } + $(this.content).find('li.tmp-drag-widget-item').replaceWith($(this.content).find('#'+this.dragStartItem).parent('li')); + this.dragReplaced = true; + } + })); + $(this.content).bind('drop',this.bind(this,function(e){ + if (this.isDisabled()) return; + var dragged = []; + var orders = []; + for (var i=0; i1 && orders.length>1) { + desk_window_request(this, url('dash/menu/drag'),{'items':dragged,'orders':orders}); + } + })); + $(this.content).bind('dragend',this.bind(this,function(e){ + $(this.content).find('#'+this.dragStartItem).parent('li').css('opacity',1); + this.isContentDragging = false; + this.dragStartY = null; + this.dragStartItem = null; + this.dragOverItem = null; + this.dragReplaced = false; + $(this.content).find('li.tmp-drag-widget-item').remove(); + })); +}; + +var dash_menu_drop = function(element) { + if (!(element instanceof FileList) && typeof(element.parent)!="undefined" && (element.parent=='record' || element.parent=='category')) { + var data = {'type':element.parent, 'item':element.data, 'menu':this.options.data.menu, 'parent':this.options.data.parent}; + desk_window_request(this, url('dash/menu/drop'),data); + } +}; + +var dash_menu_child = function() { + if (this.nested_level) return; + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + this.previous.push(this.options.data.parent); + this.options.data.parent = selected[0].data; + desk_window_reload(this); + this.nested_level++; + } +}; + +var dash_menu_secondary = function() { + if (this.options.data.menu != dash_menu_primary_id) return; + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + this.options.data.menu = dash_menu_secondary_id; + this.previous.push(this.options.data.parent); + this.options.data.parent = selected[0].data; + this.nested_level = 0; + desk_window_reload(this); + } +}; + +var dash_menu_up = function() { + if (this.previous.length==0) return; + if (this.options.data.menu == dash_menu_secondary_id && !this.nested_level) { + this.options.data.menu=dash_menu_primary_id; + } else { + this.nested_level--; + } + this.options.data.parent=this.previous.pop(); + if (this.options.data.menu == dash_menu_primary_id && this.options.data.parent) { + this.nested_level++; + } + desk_window_reload(this); +}; + +var dash_menu_page = function() { + var selected = this.getSelectedContentItems(); + if (selected.length==1 && typeof(selected[0].url)!="undefined" && selected[0].url.indexOf('#')!=0 && selected[0].url!='javascript:void(0)') { + window.location.href=selected[0].url; + } +}; + +var dash_menu_view = function() { + var selected = this.getSelectedContentItems(); + if (selected.length==1 && typeof(selected[0].url)!="undefined" && selected[0].url.indexOf('#')!=0 && selected[0].url.indexOf('http')!=0 && selected[0].url!='javascript:void(0)') { + var data = {'url':[selected[0].url]}; + desk_call(dash_menu_web_wnd, null, {'data':data}) + } +}; \ No newline at end of file diff --git a/assets/js/dash/meta.js b/assets/js/dash/meta.js new file mode 100644 index 0000000..0b5e63c --- /dev/null +++ b/assets/js/dash/meta.js @@ -0,0 +1,13 @@ +var dash_meta_load = function() { + desk_window_form_init(this); + $(this.content).find('input.logo_option').parent().append(''); + $(this.content).find('input.logo_option').parent().children('.glyphicon').click(this.bind(this, function(){ + desk_file_selector(function(selected){ + if (selected && selected.length>0 && typeof(selected[0].type)!="undefined" && selected[0].type=='image') { + var src = selected[0].data; + var regexp = new RegExp('\\'+desk_ds, 'g'); + $(this.content).find('input.logo_option').val(src.replace(regexp,'/')); + } + }, this); + })); +}; \ No newline at end of file diff --git a/assets/js/dash/modules.js b/assets/js/dash/modules.js new file mode 100644 index 0000000..ea773cb --- /dev/null +++ b/assets/js/dash/modules.js @@ -0,0 +1,61 @@ +var dash_modules_select = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + this.disableItemsByProperty('typo','deactivate'); + if (typeof(selected[0].activated)!="undefined" && selected[0].activated) { + this.enableItemsByProperty('typo','deactivate'); + } + this.disableItemsByProperty('typo','activate'); + this.disableItemsByProperty('typo','install'); + this.disableItemsByProperty('typo','uninstall'); + if (typeof(selected[0].activated)!="undefined" && !selected[0].activated) { + if (typeof(selected[0].installable)=="undefined" || !selected[0].installable || typeof(selected[0].installed)=="undefined" || selected[0].installed) this.enableItemsByProperty('typo','activate'); + if (typeof(selected[0].installable)!="undefined" && selected[0].installable) { + if (typeof(selected[0].installed)!="undefined" && !selected[0].installed) this.enableItemsByProperty('typo','install'); + if (typeof(selected[0].installed)!="undefined" && selected[0].installed) this.enableItemsByProperty('typo','uninstall'); + } + } + } +}; + +var dash_modules_load = function() { + for (var i=0; i'); + $(this.content).find('input.watermark_option').parent().children('.glyphicon').click(this.bind(this, function(){ + desk_file_selector(function(selected){ + if (selected && selected.length>0 && typeof(selected[0].type)!="undefined" && selected[0].type=='image') { + var src = selected[0].data; + var regexp = new RegExp('\\'+desk_ds, 'g'); + $(this.content).find('input.watermark_option').val(src.replace(regexp,'/')); + } + }, this); + })); +}; \ No newline at end of file diff --git a/assets/js/dash/recordhtml.js b/assets/js/dash/recordhtml.js new file mode 100644 index 0000000..899bbec --- /dev/null +++ b/assets/js/dash/recordhtml.js @@ -0,0 +1,42 @@ +var dash_recordhtml_load = function() { + this.draftContent = $(this.content).find('textarea[name=content]').val(); + this.saveDraft = function(){ + if (typeof(this.editor)=="undefined") return; + if (typeof(this.contentModified)!="undefined" && !this.contentModified) return; + var content = this.editor.getContent(); + if (content.length==0) return; + if (content == this.draftContent) return; + this.draftContent = content; + this.setTitle('glyphicon glyphicon-floppy-open'); + desk_post(url('dash/records/savedraft'),{'item':this.options.data.items[0],'content':content, 'token':token()}, this.bind(this, function(response){ + if (response && typeof(response.success)!="undefined" && response.success) { + if ($(this.content).length==0) return; + this.setTitle(); + var l=''; + if (typeof(this.editor)!="undefined") { + l = this.editor.getContent().replace(/ /g,'').replace(/<[\s\S]*?>/g,'').length; + } + this.resetFooterContent(); + this.appendFooterContent(l+''+t('saved to drafts')+''); + $('#dashpanel-container nav').removeClass('disabled'); + } + }), function(){ + $('#dashpanel-container nav').addClass('disabled'); + }); + }; + this.timer = window.setInterval(this.bind(this, this.saveDraft),dash_record_draft_interval); + if (this.options.data.draft) { + window.setTimeout(this.bind(this, function(){ + desk_confirm(t('Load saved draft ?'), this.bind(this,function(){ + desk_window_request(this,url('dash/records/draft'),{'item':this.options.data.draft}, this.bind(this, function(response){ + if (response && typeof(response.draft)!="undefined") { + $(this.content).find('textarea[name=content]').val(response.draft); + this.draftContent = response.draft; + if (typeof(this.editor)=="undefined") return; + this.editor.setContent(response.draft); + } + })); + })); + }), 1000); + } +}; \ No newline at end of file diff --git a/assets/js/dash/recordimages.js b/assets/js/dash/recordimages.js new file mode 100644 index 0000000..eec0744 --- /dev/null +++ b/assets/js/dash/recordimages.js @@ -0,0 +1,32 @@ +var dash_recordimages_desc = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].description)!="undefined") { + desk_prompt(t('Enter description'), this.bind(this, function(desc){ + desk_window_request(this,url('dash/records/imagedesc'),{'description':desc, 'item':selected[0].data}); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(selected[0].description); + } +}; + +var dash_recordimages_drop = function(element) { + if (element instanceof FileList) return; + if (typeof(element.parent)=="undefined" || element.parent!='files') return; + if (typeof(element)!="object" || typeof(element.type)=="undefined" || element.type!='image' || typeof(element.data)=="undefined") return; + desk_window_request(this, url('dash/records/addimage'),{'images':[element.data], 'item':this.options.data.items[0]}); +}; + +var dash_recordimages_add = function() { + desk_file_selector(this.bind(this,function(elements){ + if (!elements || elements.length==0) return; + var images = []; + for (var i=0; i0) { + this.enableToolbarItem(item); + } else { + this.disableToolbarItem(item); + } + for (var i=0; i0) { + $(this.element).find('.record-infobar').append('
    '+t('Information')+':
    '); + $(this.element).find('.record-infobar').append('
    '); + for (var i=0; i'+response[i]+''); + } + } + })); + }),1000); + } +}; + +var dash_records_drop = function(element) { + if (element instanceof FileList) return; + if (typeof(element.parent)!="undefined" && element.parent=='record') { + desk_window_request(this, url('dash/records/copy'),{'root':this.options.data.root, 'item':element.data}); + } +}; + +var dash_records_up = function() { + var root = this.options.data.root.split('/').slice(0,-1); + if (root.length>0) { + this.options.data.root=root.join('/'); + this.options.data.search=''; + desk_window_reload(this); + this.options.data.page=1; + } +}; + +var dash_records_edit = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined") { + if (selected[0].typo == 'category') { + var data = { + 'data':desk_window_selected(this,1), + 'reload': this.className, + 'onClose':function(){ + desk_window_reload_all(this.options.reload); + } + }; + data.data.root = this.options.data.root; + desk_call(dash_records_category_wnd, null, data); + } else if (selected[0].typo == 'record') { + desk_call(dash_records_open_record, this); + } + } +}; + +var dash_records_delete = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length>0) { + var data = {'items':[],'types':[]}; + for (var i=0; i0 && name.substr(0,1)!='/') name = '/'+name; + if (name == this.options.data.root) return; + desk_window_request(this, url('dash/records/move'),{'root':name, 'item':selected[0].data}); + })); + var root = this.options.data.root; + if (root.substr(0,1)=='/') root = root.substr(1); + $('#zira-prompt-dialog input[name=modal-input]').val(root); + } +}; + +var dash_records_create_record = function() { + var data = { + data:{}, + 'reload': this.className, + 'onClose':function(){ + desk_window_reload_all(this.options.reload); + } + }; + data.data.root = this.options.data.root; + data.data.language = this.options.data.language; + desk_call(dash_records_record_wnd, null, data); +}; + +var dash_records_create_category = function() { + var data = { + data:{}, + 'reload': this.className, + 'onClose':function(){ + desk_window_reload_all(this.options.reload); + } + }; + data.data.root = this.options.data.root; + desk_call(dash_records_category_wnd, null, data); +}; + +var dash_records_open_category = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].category)!="undefined") { + this.options.data.root = this.options.data.root+'/'+selected[0].category; + this.options.data.search=''; + this.options.data.page=1; + this.loadBody(); + } +}; + +var dash_records_category_settings = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo == 'category') { + var data = {'data':desk_window_selected(this,1)}; + desk_call(dash_records_category_settings_wnd, null, data); + } +}; + +var dash_records_category_widget = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo == 'category') { + desk_window_request(this, url('dash/records/widget'),{'item':selected[0].data}); + } +}; + +var dash_records_open_record = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo=='record') { + var data = { + data:{}, + 'reload': this.className, + 'onClose':function(){ + desk_window_reload_all(this.options.reload); + } + }; + data.data.root = this.options.data.root; + data.data.language = this.options.data.language; + data.data.items = desk_window_selected(this,1); + desk_call(dash_records_record_wnd, null, data); + } +}; + +var dash_records_record_text = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo=='record') { + var data = {'items':[selected[0].data]}; + desk_call(dash_records_record_text_wnd, null, {'data':data}); + } +}; + +var dash_records_record_html = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo=='record') { + var data = {'items':[selected[0].data]}; + desk_call(dash_records_record_html_wnd, null, {'data':data}); + } +}; + +var dash_records_desc = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].description)!="undefined" && typeof(selected[0].typo)!="undefined") { + if (selected[0].typo == 'category') { + desk_prompt(t('Enter description'), this.bind(this, function(desc){ + desk_window_request(this, url('dash/system/description'),{'type': 'category', 'description':desc, 'item':selected[0].data}); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(selected[0].description); + } else if (selected[0].typo == 'record') { + desk_multi_prompt(t('Enter description'), this.bind(this, function(desc){ + desk_window_request(this, url('dash/records/description'),{'description':desc, 'item':selected[0].data}); + })); + $('#zira-multi-prompt-dialog textarea[name=modal-input]').val(selected[0].description); + } + } +}; + +var dash_records_record_image = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo=='record') { + desk_file_selector(this.bind(this,function(elements){ + if (!elements || elements.length==0) return; + var element = elements[0]; + if (element instanceof FileList) return; + if (typeof(element)!="object" || typeof(element.type)=="undefined" || element.type!='image' || typeof(element.data)=="undefined") return; + if (typeof(element.parent)=="undefined" || element.parent!='files') return; + desk_window_request(this, url('dash/records/image'),{'image':element.data, 'item':selected[0].data}); + })); + } +}; + +var dash_records_seo = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined") { + var data = {'items':[selected[0].data]}; + if (selected[0].typo == 'category') { + desk_call(dash_records_category_meta_wnd, null, { + 'data':data, + 'reload': this.className, + 'onClose':function(){ + desk_window_reload_all(this.options.reload); + } + }); + } else if (selected[0].typo == 'record') { + desk_call(dash_records_record_meta_wnd, null, { + 'data':data, + 'reload': this.className, + 'onClose':function(){ + desk_window_reload_all(this.options.reload); + } + }); + } + } +}; + +var dash_records_record_page = function() { + var selected = this.getSelectedContentItems(); + if (selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo=='record' && typeof(selected[0].page)!="undefined") { + var language = ''; + if (typeof(selected[0].language)!="undefined" && selected[0].language!==null) language = selected[0].language + '/'; + window.location.href=url(language+selected[0].page); + } +}; + +var dash_records_record_view = function() { + var selected = this.getSelectedContentItems(); + if (selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo=='record' && typeof(selected[0].page)!="undefined") { + var language = ''; + if (typeof(selected[0].language)!="undefined" && selected[0].language!==null) language = selected[0].language + '/'; + var data = {'url':[language+selected[0].page]}; + desk_call(dash_records_web_wnd, null, {'data':data}); + } +}; + +var dash_records_record_publish = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo=='record') { + var data = {'item':selected[0].data}; + desk_window_request(this, url('dash/records/publish'), data); + } +}; + +var dash_records_record_front = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo=='record') { + var data = {'item':selected[0].data}; + desk_window_request(this, url('dash/records/frontpage'), data); + } +}; + +var dash_records_record_gallery = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo=='record') { + var data = {'items':[selected[0].data]}; + desk_call(dash_records_record_images_wnd, null, {'data':data}); + } +}; + +var dash_records_record_slider = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].typo)!="undefined" && selected[0].typo=='record') { + var data = {'items':[selected[0].data]}; + desk_call(dash_records_record_slides_wnd, null, {'data':data}); + } +}; + +var dash_records_language = function(element) { + var language = this.options.data.language; + var id = $(element).attr('id'); + var item = this.findMenuItemByProperty('id',id); + if (item && typeof(item.language)!="undefined") { + if (item.language!=language) { + this.options.data.language=item.language; + desk_window_reload(this); + $(element).parents('ul').find('.glyphicon-ok').removeClass('glyphicon-ok').addClass('glyphicon-filter'); + $(element).find('.glyphicon').removeClass('glyphicon-filter').addClass('glyphicon-ok'); + } else { + this.options.data.language=''; + desk_window_reload(this); + $(element).parents('ul').find('.glyphicon-ok').removeClass('glyphicon-ok').addClass('glyphicon-filter'); + } + } +}; \ No newline at end of file diff --git a/assets/js/dash/recordslides.js b/assets/js/dash/recordslides.js new file mode 100644 index 0000000..58f3657 --- /dev/null +++ b/assets/js/dash/recordslides.js @@ -0,0 +1,32 @@ +var dash_recordslides_desc = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].description)!="undefined") { + desk_prompt(t('Enter description'), this.bind(this, function(desc){ + desk_window_request(this, url('dash/records/slidedesc'),{'description':desc, 'item':selected[0].data}); + })); + $('#zira-prompt-dialog input[name=modal-input]').val(selected[0].description); + } +}; + +var dash_recordslides_drop = function(element) { + if (element instanceof FileList) return; + if (typeof(element.parent)=="undefined" || element.parent!='files') return; + if (typeof(element)!="object" || typeof(element.type)=="undefined" || element.type!='image' || typeof(element.data)=="undefined") return; + desk_window_request(this, url('dash/records/addslide'),{'images':[element.data], 'item':this.options.data.items[0]}); +}; + +var dash_recordslides_add = function() { + desk_file_selector(this.bind(this,function(elements){ + if (!elements || elements.length==0) return; + var images = []; + for (var i=0; i'+t('saved to drafts')+''); + $('#dashpanel-container nav').removeClass('disabled'); + } + }), function(){ + $('#dashpanel-container nav').addClass('disabled'); + }); + }; + this.timer = window.setInterval(this.bind(this, this.saveDraft),dash_record_draft_interval); + if (this.options.data.draft) { + desk_confirm(t('Load saved draft ?'), this.bind(this,function(){ + desk_window_request(this,url('dash/records/draft'),{'item':this.options.data.draft}, this.bind(this, function(response){ + if (response && typeof(response.draft)!="undefined") { + $(this.content).find('textarea[name=content]').val(response.draft); + this.draftContent = response.draft; + } + })); + })); + } +}; \ No newline at end of file diff --git a/assets/js/dash/selector.js b/assets/js/dash/selector.js new file mode 100644 index 0000000..602945a --- /dev/null +++ b/assets/js/dash/selector.js @@ -0,0 +1,54 @@ +var dash_selector_body_item_callback = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].type)!="undefined" && selected[0].type=='folder') { + desk_window_edit_item(this); + } else { + desk_window_close(this); + } +}; + +var dash_selector_select = function() { + var selected = this.getSelectedContentItems(); + this.disableItemsByProperty('action','select'); + if (selected && selected.length>0) { + for (var i=0; i0 && typeof(callback)!="undefined") { + if (typeof(object) == "undefined") object = this; + callback.call(object, selected); + if ((object instanceof DashWindow) && object != this) { + object.focus(); + object.setZ(this.getZ()); + } + } + } + }; + desk_call(dash_selector_wnd, null, data); + } catch(e) { + desk_error(t('An error occurred')); + } +}; \ No newline at end of file diff --git a/assets/js/dash/system.js b/assets/js/dash/system.js new file mode 100644 index 0000000..af25f25 --- /dev/null +++ b/assets/js/dash/system.js @@ -0,0 +1,41 @@ +var dash_system_dump = function() { + var a=document.createElement('a'); + a.href=url('dash/system/dump'); + document.body.appendChild(a); + HTMLElementClick.call(a); + document.body.removeChild(a); +}; + +var dash_system_cache = function() { + desk_window_request(this, url('dash/system/cache'), {}); +}; + +var dash_system_files = function() { + desk_window_request(this, url('dash/system/tree'),{},this.bind(this, function(response){ + if (response && response.length>0) { + var content = '
      '; + for (var i=0; i'+response[i]+''; + } + content += '
    '; + if ($(this.content).find('.system-options-list').length==0) { + this.clearBodyContent(); + this.appendBodyContent(content); + } else { + $(this.content).find('.system-options-list').replaceWith(content); + } + } + })); +}; + +var dash_system_load = function() { + $.get(baseUrl('dash/index/ping'),{}, this.bind(this, function(){ + $(this.content).find('#sys-info-clean-url-option').parent().children('.glyphicon').removeClass('glyphicon-question-sign').addClass('glyphicon-ok-sign system-ok'); + $(this.content).find('#sys-info-clean-url-option').text(t('supported')); + }),'json').fail(this.bind(this, function(){ + $(this.content).find('#sys-info-clean-url-option').parent().children('.glyphicon').removeClass('glyphicon-question-sign').addClass('glyphicon-warning-sign system-warning'); + $(this.content).find('#sys-info-clean-url-option').text(t('not supported')); + })); +}; \ No newline at end of file diff --git a/assets/js/dash/text.js b/assets/js/dash/text.js new file mode 100644 index 0000000..71e59b1 --- /dev/null +++ b/assets/js/dash/text.js @@ -0,0 +1,12 @@ +var dash_text_load = function() { + this.updateTitle(this.options.data.file); +}; + +var desk_text_editor = function(file) { + try { + var data = {'file':file}; + desk_call(dash_text_wnd, null, {'data':data}); + } catch(e) { + desk_error(t('An error occurred')); + } +}; \ No newline at end of file diff --git a/assets/js/dash/themes.js b/assets/js/dash/themes.js new file mode 100644 index 0000000..4295959 --- /dev/null +++ b/assets/js/dash/themes.js @@ -0,0 +1,29 @@ +var dash_themes_select = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + this.disableItemsByProperty('typo','activate'); + if (typeof(selected[0].activated)!="undefined" && !selected[0].activated) { + this.enableItemsByProperty('typo','activate'); + } + this.disableItemsByProperty('typo','preview'); + if (typeof(selected[0].src)!="undefined" && selected[0].src.length>0 && selected[0].src.indexOf(dash_themes_blank_src)!=0) { + this.enableItemsByProperty('typo','preview'); + } + } +}; + +var dash_themes_activate = function() { + var selected = desk_window_selected(this); + if (selected && typeof(selected.items)!="undefined" && selected.items.length==1) { + desk_window_request(this, url('dash/system/theme'),{'theme':selected.items[0]}); + } +}; + +var dash_themes_preview = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].src)!="undefined" && selected[0].src.length>0 && selected[0].src.indexOf(dash_themes_blank_src)!=0) { + $('body').append(''); + $('#dashwindow-theme-preview-lightbox').trigger('click'); + $('#dashwindow-theme-preview-lightbox').remove(); + } +}; \ No newline at end of file diff --git a/assets/js/dash/translates.js b/assets/js/dash/translates.js new file mode 100644 index 0000000..025ca4b --- /dev/null +++ b/assets/js/dash/translates.js @@ -0,0 +1,19 @@ +var dash_translates_create = function() { + desk_multi_prompt(t('Enter string to translate'),this.bind(this, function(str) { + if (str.length>0) { + desk_window_request(this, url('dash/languages/addstring'), {'string': str,'language': this.options.data.items[0]}); + } + })); +}; + +var dash_translates_edit = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + desk_multi_prompt(t('Enter translate'),this.bind(this, function(str) { + if (str.length>0) { + desk_window_request(this, url('dash/languages/translate'), {'strid': selected[0].data,'translate': str,'language': this.options.data.items[0]}); + } + })); + $('#zira-multi-prompt-dialog textarea[name=modal-input]').val(selected[0].tooltip); + } +}; \ No newline at end of file diff --git a/assets/js/dash/user.js b/assets/js/dash/user.js new file mode 100644 index 0000000..ae946bc --- /dev/null +++ b/assets/js/dash/user.js @@ -0,0 +1,75 @@ +var dash_user_load = function() { + desk_window_form_init(this); + zira_datepicker($(this.content).find('.dash-datepicker')); + $(this.sidebar).find('.dashwindow-userthumb-selector').click(this.bind(this,function(){ + desk_call(dash_user_image_select, this); + })); + if ($(this.content).find('input.dashwindow-user-image').val().length>0) { + $(this.sidebar).find('.dashwindow-userthumb-delete').removeClass('disabled'); + this.enableItemsByProperty('action','noimage'); + } + $(this.sidebar).find('.dashwindow-userthumb-delete').click(this.bind(this,function(){ + desk_call(dash_user_delete_image, this); + })); + if ($(this.content).find('input.dashwindow-user-verified').val()==dash_user_status_verified) { + var verified = this.findToolbarItemByProperty('action','verified'); + if (verified) $(verified.element).addClass('active').children('.glyphicon').removeClass('glyphicon-ban-circle').addClass('glyphicon-ok'); + } + if ($(this.content).find('input.dashwindow-user-active').val()==dash_user_status_active) { + var active = this.findToolbarItemByProperty('action','active'); + if (active) $(active.element).addClass('active').children('.glyphicon').removeClass('glyphicon-ban-circle').addClass('glyphicon-ok'); + } +}; + +var dash_user_drop = function(element) { + if (!(element instanceof FileList) && typeof(element.parent)!="undefined" && element.parent=='files' && typeof(element.type)!="undefined" && element.type=='image') { + var src = element.data; + var regexp = new RegExp('\\'+desk_ds, 'g'); + $(this.sidebar).find('.dashwindow-userthumb-selector').attr('src',baseUrl(src.replace(regexp,'/'))); + $(this.content).find('input.dashwindow-user-image').val(src); + $(this.sidebar).find('.dashwindow-userthumb-delete').removeClass('disabled'); + this.enableItemsByProperty('action','noimage'); + } +}; + +var dash_user_image_select = function() { + desk_file_selector(function(selected){ + if (selected && selected.length>0 && typeof(selected[0].type)!="undefined" && selected[0].type=='image') { + var src = selected[0].data; + var regexp = new RegExp('\\'+desk_ds, 'g'); + $(this.element).find('.dashwindow-userthumb-selector').attr('src',baseUrl(src.replace(regexp,'/')).replace(desk_ds,'/')); + $(this.content).find('input.dashwindow-user-image').val(src); + $(this.sidebar).find('.dashwindow-userthumb-delete').removeClass('disabled'); + this.enableItemsByProperty('action','noimage'); + } + }, this); +}; + +var dash_user_verified = function() { + var verified = this.findToolbarItemByProperty('action','verified'); + if ($(this.content).find('input.dashwindow-user-verified').val()==dash_user_status_verified) { + if (verified) $(verified.element).removeClass('active').children('.glyphicon').removeClass('glyphicon-ok').addClass('glyphicon-ban-circle'); + $(this.content).find('input.dashwindow-user-verified').val(dash_user_status_not_verified); + } else { + if (verified) $(verified.element).addClass('active').children('.glyphicon').removeClass('glyphicon-ban-circle').addClass('glyphicon-ok'); + $(this.content).find('input.dashwindow-user-verified').val(dash_user_status_verified); + } +}; + +var dash_user_active = function() { + var active = this.findToolbarItemByProperty('action','active'); + if ($(this.content).find('input.dashwindow-user-active').val()==dash_user_status_active) { + if (active) $(active.element).removeClass('active').children('.glyphicon').removeClass('glyphicon-ok').addClass('glyphicon-ban-circle'); + $(this.content).find('input.dashwindow-user-active').val(dash_user_status_not_active); + } else { + if (active) $(active.element).addClass('active').children('.glyphicon').removeClass('glyphicon-ban-circle').addClass('glyphicon-ok'); + $(this.content).find('input.dashwindow-user-active').val(dash_user_status_active); + } +}; + +var dash_user_delete_image = function() { + $(this.sidebar).find('.dashwindow-userthumb-selector').attr('src',dash_user_profile_nophoto_src); + $(this.content).find('input.dashwindow-user-image').val(''); + $(this.sidebar).find('.dashwindow-userthumb-delete').addClass('disabled'); + this.disableItemsByProperty('action','noimage'); +}; \ No newline at end of file diff --git a/assets/js/dash/users.js b/assets/js/dash/users.js new file mode 100644 index 0000000..8a37c05 --- /dev/null +++ b/assets/js/dash/users.js @@ -0,0 +1,121 @@ +var dash_users_delete_image = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].data)!="undefined") { + desk_window_request(this, url('dash/users/noimage'),{'user_id':selected[0].data}); + } +}; + +var dash_users_deactivate = function() { + var selected = desk_window_selected(this); + if (selected && typeof(selected.items)!="undefined" && selected.items.length>0) { + desk_window_request(this, url('dash/users/deactivate'),{'users':selected.items}); + } +}; + +var dash_users_activate = function() { + var selected = desk_window_selected(this); + if (selected && typeof(selected.items)!="undefined" && selected.items.length>0) { + desk_window_request(this, url('dash/users/activate'),{'users':selected.items}); + } +}; + +var dash_users_select = function() { + var selected = this.getSelectedContentItems(); + if (!selected || selected.length!=1 || typeof(selected[0].src)=="undefined" || selected[0].src==dash_user_profile_nophoto_src) { + this.disableItemsByProperty('typo','noimage'); + } + if (!selected || selected.length!=1 || typeof(selected[0].avatar)=="undefined" || selected[0].avatar.length==0) { + this.disableItemsByProperty('typo','show_avatar'); + } + if (!selected || selected.length!=1 || typeof(selected[0].activated)=="undefined" || selected[0].activated!=dash_user_status_active) { + this.disableItemsByProperty('typo','view_profile'); + } + if (selected && selected.length>0) { + this.disableItemsByProperty('typo','deactivate'); + for (var i=0; i0) { + $(this.element).find('.user-infobar').append('
    '+t('Information')+':
    '); + $(this.element).find('.user-infobar').append('
    '); + for (var i=0; i'+response[i]+''); + } + } + })); + }),1000); + } +}; + +var dash_users_show_avatar = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1 && typeof(selected[0].avatar)!="undefined" && selected[0].avatar.length>0) { + $('body').append(''); + $('#dashwindow-user-avatar-lightbox').trigger('click'); + $('#dashwindow-user-avatar-lightbox').remove(); + } +}; + +var dash_users_edit = function() { + try { window.clearTimeout(this.timer); } catch(err) {}; + desk_window_edit_item(this); +}; + +var dash_users_groups = function() { + desk_call(dash_users_group_wnd, null); +}; + +var dash_users_group_filter = function(element) { + var group_id = this.options.data.group_id; + var id = $(element).attr('id'); + var item = this.findMenuItemByProperty('id',id); + if (item && typeof(item.group_id)!="undefined") { + if (item.group_id!=group_id) { + this.options.data.group_id=item.group_id; + desk_window_reload(this); + $(element).parents('ul').find('.glyphicon-ok').removeClass('glyphicon-ok').addClass('glyphicon-filter'); + $(element).find('.glyphicon').removeClass('glyphicon-filter').addClass('glyphicon-ok'); + } else { + this.options.data.group_id=0; + desk_window_reload(this); + $(element).parents('ul').find('.glyphicon-ok').removeClass('glyphicon-ok').addClass('glyphicon-filter'); + } + } +}; + +var dash_users_view_profile = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + window.location.href=url('user/'+selected[0].data); + } +}; + +var dash_users_load = function() { + $(this.element).find('.user-infobar').html(''); + for (var i=0; i0) { + desk_window_request(this, url('dash/widgets/deactivate'),{'widgets':selected.items}); + } +}; + +var dash_widgets_activate = function() { + var selected = desk_window_selected(this); + if (selected && typeof(selected.items)!="undefined" && selected.items.length>0) { + desk_window_request(this, url('dash/widgets/activate'),{'widgets':selected.items}); + } +}; + +var dash_widgets_select = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length>0) { + this.disableItemsByProperty('typo','copy'); + this.disableItemsByProperty('action','delete'); + for (var i=0; i0) { + changed = this.options.bodyItems[i-1]; + break; + } + } + if (!changed) return; + var sorted_widgets = [selected_item.data, changed.data]; + desk_window_request(this, url('dash/widgets/sort'),{'widgets':sorted_widgets}); + } +}; + +var dash_widgets_down = function() { + var selected = this.getSelectedContentItems(); + if (selected && selected.length==1) { + var selected_item = selected[0]; + var changed = false; + for (var i=0; i this.dragStartY) { + $(this.content).find('#'+this.dragOverItem).parent('li').after(tmp); + } else { + $(this.content).find('#'+this.dragOverItem).parent('li').before(tmp); + } + $(this.content).find('li.tmp-drag-widget-item').replaceWith($(this.content).find('#'+this.dragStartItem).parent('li')); + this.dragReplaced = true; + } + })); + $(this.content).bind('drop',this.bind(this,function(e){ + if (this.isDisabled()) return; + var dragged = []; + var orders = []; + for (var i=0; i1 && orders.length>1) { + desk_window_request(this, url('dash/widgets/drag'),{'widgets':dragged,'orders':orders}); + } + })); + $(this.content).bind('dragend',this.bind(this,function(e){ + $(this.content).find('#'+this.dragStartItem).parent('li').css('opacity',1); + this.isContentDragging = false; + this.dragStartY = null; + this.dragStartItem = null; + this.dragOverItem = null; + this.dragReplaced = false; + $(this.content).find('li.tmp-drag-widget-item').remove(); + })); +}; + +var dash_widgets_drop = function(element) { + if (!(element instanceof FileList) && typeof(element.parent)!="undefined" && element.parent=='files' && typeof(element.type)!="undefined" && (element.type=='txt' || element.type=='html' || element.type=='image')) { + var path = element.data; + desk_window_request(this, url('dash/widgets/block'),{'path':path}); + } +}; \ No newline at end of file diff --git a/assets/js/desk-window.js b/assets/js/desk-window.js new file mode 100644 index 0000000..d08bc37 --- /dev/null +++ b/assets/js/desk-window.js @@ -0,0 +1,2943 @@ +var DashWindow = function(id, className, options) { + this.window_class = 'dashboard-window'; + this.header_class = 'dashboard-window-header'; + this.footer_class = 'dashboard-window-footer'; + this.sidebar_class = 'dashboard-window-sidebar'; + this.content_class = 'dashboard-window-content'; + this.menu_class = 'dashboard-window-menu'; + this.menu_list_class = 'dashboard-window-menu-list'; + this.menu_list_item_class = 'dashboard-window-menu-list-item'; + this.menu_list_item_link_class = 'dashboard-window-menu-list-item-link'; + this.window_resizer_class = 'dashboard-window-resizer'; + this.sidebar_resizer_class = 'dashboard-sidebar-resizer'; + this.close_button_class = 'dashboard-window-close-button'; + this.maximize_button_class = 'dashboard-window-maximize-button'; + this.minimize_button_class = 'dashboard-window-minimize-button'; + this.maximized_window_class = 'dashboard-window-maximized'; + this.minimized_window_class = 'dashboard-window-minimized'; + this.focused_window_class = 'dashboard-window-focused'; + this.animating_window_class = 'dashboard-window-animating'; + this.nosidebar_window_class = 'dashboard-window-nosidebar'; + this.title_text_class = 'dashboard-window-title'; + this.toolbar_class = 'dashboard-window-toolbar'; + this.notoolbar_window_class = 'dashboard-window-notoolbar'; + this.noresize_window_class = 'dashboard-window-noresize'; + this.sidebar_content_wrapper_class = 'dashboard-sidebar-content-wrapper'; + this.body_content_wrapper_class = 'dashboard-body-content-wrapper'; + this.body_full_content_wrapper_class = 'dashboard-body-full-content-wrapper'; + this.footer_content_wrapper_class = 'dashboard-footer-content-wrapper'; + this.dashwindow_content_icon_class = 'dashwindow-content-icon'; + this.dashwindow_content_icon_folder_class = 'dashwindow-content-icon-folder'; + this.dashwindow_content_icon_file_class = 'dashwindow-content-icon-file'; + this.dashwindow_content_icon_archive_class = 'dashwindow-content-icon-archive'; + this.dashwindow_content_icon_txt_class = 'dashwindow-content-icon-txt'; + this.dashwindow_content_icon_html_class = 'dashwindow-content-icon-html'; + this.dashwindow_content_icon_blank_class = 'dashwindow-content-icon-blank'; + this.dashwindow_content_list_class = 'dashwindow-content-list'; + this.dashwindow_content_grid_class = 'dashwindow-content-grid'; + this.disabled_window_class = 'dashboard-window-disabled'; + this.loading_window_class = 'dashboard-window-loading'; + this.loader_class = 'dashboard-window-loader'; + this.context_menu_class = 'dashboard-window-contextmenu'; + this.highlight_class = 'dashboard-window-highlight'; + this.blink_class = 'dashboard-window-blink'; + this.body_item_images_class = 'dashboard-window-body-item-image'; + this.dashwindow_content_noselect_class = 'dashboard-window-noselect-content'; + this.moving_window_class = 'dashboard-window-moving'; + + this.id = id; + this.className = className; + this.initialized = false; + this.maximized = false; + this.minimized = false; + this.disabled = false; + this.touchesEnabled = false; + this.loading = false; + + var defaults = { + 'container': 'body', + 'edge_top': 0, + 'edge_bottom': 0, + 'edge_left': 0, + 'edge_right': 0, + 'top': null, + 'left': null, + 'right': null, + 'bottom': null, + 'width': null, + 'height': null, + 'auto': false, + 'auto_ratio': 4/3, + 'auto_margin': 50, + 'auto_min_width': 640, + 'auto_min_height': 480, + 'auto_max_width': 800, + 'auto_max_height': 600, + 'resize': true, + 'resize_min_width': 400, + 'resize_min_height': 300, + 'min_options_to_window': true, + 'sidebar_resize_min_width': 100, + 'minimized_width': 250, + 'animate': true, + 'animation_duration': 100, + 'maximized': false, + 'sidebar': true, + 'sidebar_width': null, + 'toolbar': true, + 'viewSwitcher': false, + 'bodyViewList': false, + 'maximize_on_move': true, + 'maximize_top_offset': 50, + 'maximize_left_offset': 5, + 'maximize_right_offset': 5, + 'icon_class': 'glyphicon glyphicon-th-large', + 'title': null, + 'menuItems': [], + 'toolbarItems': [], + 'toolbarContent': '', + 'sidebarItems': [], + 'sidebarContent': '', + 'bodyItems': [], + 'bodyContent': '', + 'bodyFullContent': '', + 'footerContent': '', + 'contextMenuItems': [], + 'onOpen': null, + 'onLoad': null, + 'onFocus': null, + 'onSelect': null, + 'onClose': null, + 'onBlur': null, + 'onDrop': null, + 'onResize': null, + 'load': null, + 'data': null, + 'nocache': false, + 'help_url': null + }; + + if(typeof(options)!="undefined") { + this.options = $.extend(defaults, options); + } else { + this.options = defaults; + } + + this.setWindowScroll(); + this.setWindowRect(); + this.checkSizeOptions(); + + if (this.options.width!==null) { + if (this.options.auto_min_width>this.options.width) { + this.options.auto_min_width=this.options.width; + } + if (this.options.resize_min_width>this.options.width) { + this.options.resize_min_width=this.options.width; + } + } + if (this.options.height!==null) { + if (this.options.auto_min_height>this.options.height) { + this.options.auto_min_height=this.options.height; + } + if (this.options.resize_min_height>this.options.height) { + this.options.resize_min_height=this.options.height; + } + } + + this.create(); + this.createMenu(); + this.body_view_list = this.options.bodyViewList; + if (this.toolbar!==null) { + this.createToolbar(); + this.appendToolbarContent(this.options.toolbarContent); + } + if (this.sidebar!==null) { + this.createSidebarItems(this.options.sidebarItems); + this.appendSidebarContent(this.options.sidebarContent); + this.updateSidebarResizerPosition(); + } + this.createBodyItems(this.options.bodyItems); + this.appendBodyContent(this.options.bodyContent); + this.appendBodyFullContent(this.options.bodyFullContent); + this.appendFooterContent(this.options.footerContent); + this.createContextMenu(); + + if (this.options.bodyItems.length>0 && this.options.bodyContent.length==0 && this.options.bodyFullContent.length==0) { + $(this.content).addClass(this.dashwindow_content_noselect_class); + } + + this.clicked = false; + this.moving = false; + this.window_resizing = false; + this.sidebar_resizing = false; + this.z = 0; + this.selected = []; + this.content_clicked = false; + this.item_clicked = false; + this.minimized_array = null; + this.menu_clicked = false; + this.menu_opened = false; + this.context_menu_opened = false; + this.focusedElement = null; + this.keys = null; + + if (this.options.maximized) { + this.initialized = true; + this.maximize(true, false, this.onInitialize); + } else if (!this.options.animate) { + this.initialized = true; + this.onInitialize(); + } else { + this.animateOpening(); + } +}; + +DashWindow.prototype.bind = function(object, method) { + return function(arg) { + return method.call(object,arg); + } +}; + +DashWindow.prototype.getId = function() { + return this.id; +}; + +DashWindow.prototype.getClass = function() { + return this.className; +}; + +DashWindow.prototype.setClicked = function(clicked) { + this.clicked = clicked; +}; + +DashWindow.prototype.setMoving = function(moving) { + this.moving = moving; + $(this.element).removeClass(this.moving_window_class); + if (this.moving) { + $(this.element).addClass(this.moving_window_class); + } +}; + +DashWindow.prototype.setWindowResizing = function(resizing) { + this.window_resizing = resizing; +}; + +DashWindow.prototype.setSidebarResizing = function(resizing) { + this.sidebar_resizing = resizing; +}; + +DashWindow.prototype.setZ = function(z) { + this.z = z; + this.updateZ(); +}; + +DashWindow.prototype.getZ = function() { + return this.z +}; + +DashWindow.prototype.updateZ = function() { + $(this.element).css('zIndex', this.z); +}; + +DashWindow.prototype.setContentClicked = function(clicked) { + this.content_clicked = clicked; +}; + +DashWindow.prototype.isContentClicked = function() { + return this.content_clicked; +}; + +DashWindow.prototype.setItemClicked = function(clicked) { + this.item_clicked = clicked; +}; + +DashWindow.prototype.isItemClicked = function() { + return this.item_clicked; +}; + +DashWindow.prototype.setKeysArr = function(keys) { + this.keys = keys; +}; + +DashWindow.prototype.focus = function() { + if (!this.focused && this.options.onFocus !== null) { + this.options.onFocus.call(this); + } + this.focused = true; + $(this.element).addClass(this.focused_window_class); + if (this.focusedElement!==null) $(this.focusedElement).focus(); +}; + +DashWindow.prototype.isFocused = function() { + return this.focused; +}; + +DashWindow.prototype.blur = function(exec_callback) { + if (typeof(exec_callback)=="undefined") exec_callback = false; + this.focused = false; + $(this.element).removeClass(this.focused_window_class); + if (exec_callback) { + if (this.options.onBlur !== null) this.options.onBlur.call(this); + if (this.options.bodyItems.length==0 && (this.options.bodyContent.length>0 || this.options.bodyFullContent.length>0)) { + var focusedElement = $(this.content).find(':focus'); + if ($(focusedElement).length > 0) this.focusedElement = focusedElement; + } + } +}; + +DashWindow.prototype.disableWindow = function() { + this.disabled = true; + $(this.element).addClass(this.disabled_window_class); +}; + +DashWindow.prototype.enableWindow = function() { + this.disabled = false; + $(this.element).removeClass(this.disabled_window_class); +}; + +DashWindow.prototype.setTouchesEnabled = function(enabled) { + this.touchesEnabled = enabled; +}; + +DashWindow.prototype.setMinimizedArray = function(arr) { + this.minimized_array = arr; +}; + +DashWindow.prototype.isInitialized = function() { + return this.initialized; +}; + +DashWindow.prototype.isTouchesEnabled = function() { + return this.touchesEnabled; +}; + +DashWindow.prototype.isMinimized = function() { + return this.minimized; +}; + +DashWindow.prototype.isMaximized = function() { + return this.maximized; +}; + +DashWindow.prototype.isDisabled = function() { + return this.disabled; +}; + +DashWindow.prototype.highlightWindow = function() { + $(this.element).addClass(this.highlight_class); +}; + +DashWindow.prototype.unhighlightWindow = function() { + $(this.element).removeClass(this.highlight_class); +}; + +DashWindow.prototype.blinkWindow = function(iter) { + if (typeof(iter)=="undefined") iter=0; + if (iter%2==0) { + $(this.element).addClass(this.blink_class) + } else { + $(this.element).removeClass(this.blink_class); + } + if (iter>=5) { + $(this.element).removeClass(this.blink_class); + return; + } + window.setTimeout(this.bind(this, function(){ + this.blinkWindow(++iter); + }),this.options.animation_duration); +}; + +DashWindow.prototype.setWindowScroll = function() { + this.window_scroll_left = $(window).scrollLeft(); + this.window_scroll_top = $(window).scrollTop(); +}; + +DashWindow.prototype.setWindowRect = function() { + this.window_width = $(window).width(); + this.window_height = $(window).height(); + this.window_top = this.options.edge_top; + this.window_bottom = this.options.edge_bottom; + this.window_left = this.options.edge_left; + this.window_right = this.options.edge_right; + this.window_inner_width = this.window_width - this.window_left - this.window_right; + this.window_inner_height = this.window_height - this.window_top - this.window_bottom; +}; + +DashWindow.prototype.checkSizeOptions = function() { + if (!this.options.min_options_to_window) return; + if (this.options.auto_min_width>this.window_width-2*this.options.auto_margin) { + this.options.auto_min_width=this.window_width-2*this.options.auto_margin; + } + if (this.options.auto_min_height>this.window_height-2*this.options.auto_margin) { + this.options.auto_min_height=this.window_height-2*this.options.auto_margin; + } + if (this.options.resize_min_width>this.window_width) { + this.options.resize_min_width=this.window_width; + } + if (this.options.resize_min_height>this.window_height) { + this.options.resize_min_height=this.window_height; + } + if (this.options.sidebar_resize_min_width>this.window_width/2) { + this.options.sidebar_resize_min_width=this.window_width/2; + } +}; + +DashWindow.prototype.create = function() { + $(this.options.container).append('
    '); + this.element = $('#'+this.id); + if (this.options.auto) { + this.autoSize(); + this.autoPosition(); + } + if (!this.options.resize) { + $(this.element).addClass(this.noresize_window_class); + } + this.updateOuterSize(); + this.updatePosition(); + $(this.element).append('
    '); + $(this.element).append('
    '); + if (this.options.toolbar) { + $(this.element).append('
    '); + this.toolbar = $(this.element).children('.'+this.toolbar_class); + this.options.toolbar_height = $(this.toolbar).outerHeight(); + } else { + this.toolbar = null; + $(this.element).addClass(this.notoolbar_window_class); + this.options.toolbar_height = 0; + } + if (this.options.sidebar) { + $(this.element).append('
    '); + this.sidebar = $(this.element).children('.'+this.sidebar_class); + } else { + this.sidebar = null; + $(this.element).addClass(this.nosidebar_window_class); + } + $(this.element).append('
    '); + $(this.element).append('
    '); + this.header = $(this.element).children('.'+this.header_class); + this.menu = $(this.element).children('.'+this.menu_class); + this.content = $(this.element).children('.'+this.content_class); + this.footer = $(this.element).children('.'+this.footer_class); + $(this.header).append(''); + $(this.header).append(''); + $(this.header).append(''); + this.close_button = $(this.header).children('.'+this.close_button_class); + this.minimize_button = $(this.header).children('.'+this.minimize_button_class); + this.maximize_button = $(this.header).children('.'+this.maximize_button_class); + this.createWindowResizer(); + if (this.sidebar!==null) { + if (this.options.sidebar_width===null) { + this.options.sidebar_width = $(this.sidebar).outerWidth(); + } + if (this.options.sidebar_width>this.options.width/2) { + this.options.sidebar_width = this.options.width/2; + } + this.setSidebarWidth(this.options.sidebar_width); + if (this.options.sidebar_resize_min_width>this.options.sidebar_width) { + this.options.sidebar_resize_min_width=this.options.sidebar_width; + } + this.createSidebarResizer(); + } + $(this.header).append('
    '); + if (this.options.title!==null) { + this.setTitle(); + } + this.createLoader(); + this.options.header_height = $(this.header).outerHeight(); + this.options.menu_height = $(this.menu).outerHeight(); + this.options.footer_height = $(this.footer).outerHeight(); + this.options.window_resizer_width = $(this.window_resizer).outerWidth(); + this.options.window_resizer_height = $(this.window_resizer).outerHeight(); + this.updateInnerSize(); + this.updateWindowResizerPosition(); +}; + +DashWindow.prototype.setTitle = function(icon, text) { + if (typeof(icon)=="undefined") icon = this.options.icon_class; + if (typeof(text)=="undefined") text = this.options.title; + var title = $(this.header).children('.'+this.title_text_class); + if ($(title).length>0) { + $(title).html(' '+text); + $(title).attr('title', text); + } +}; + +DashWindow.prototype.updateTitle = function(text) { + this.options.title = text; + this.setTitle(); +}; + +DashWindow.prototype.createLoader = function() { + $(this.menu).append('
    '); +}; + +DashWindow.prototype.createSidebarResizer = function() { + $(this.content).append('
    '); + this.sidebar_resizer = $(this.content).children('.'+this.sidebar_resizer_class); + this.options.sidebar_resizer_width = $(this.sidebar_resizer).outerWidth(); +}; + +DashWindow.prototype.createWindowResizer = function() { + $(this.footer).append('
    '); + this.window_resizer = $(this.footer).children('.'+this.window_resizer_class); +}; + +DashWindow.prototype.animateOpening = function() { + $(this.element).addClass(this.animating_window_class); + $(this.element).css({ + 'width': this.options.width, + 'height': this.options.height, + 'left': this.options.left, + 'top': -this.options.height, + 'opacity': 0 + }).animate({ + 'width': this.options.width, + 'height': this.options.height, + 'left': this.options.left, + 'top': this.options.top, + 'opacity': 1 + },{ + 'duration': this.options.animation_duration, + 'progress': this.bind(this,function(){ + var t = (new Date()).getTime(); + if (typeof(this.animation_progress_time)!="undefined" && t-this.animation_progress_time<50) return; + this.animation_progress_time = t; + var h = $(this.element).height() - this.options.header_height - this.options.menu_height - this.options.toolbar_height - this.options.footer_height; + if (this.sidebar!==null) $(this.sidebar).css('height', h); + $(this.content).css('height', h); + }), + 'always': this.bind(this,function(){ + this.onResize(); + this.initialized = true; + $(this.element).removeClass(this.animating_window_class); + this.onInitialize(); + }) + }); +}; + +DashWindow.prototype.onInitialize = function() { + this.disableEditItems(); + this.disableDeleteItems(); + if (this.options.onOpen!==null) { + this.options.onOpen.call(this); + } + this.loadBody(); +}; + +DashWindow.prototype.loadBody = function() { + if (this.options.load!==null) { + this.load(this.options.load); + } +}; + +DashWindow.prototype.autoSize = function() { + if (this.window_width>this.window_height) { + this.options.height = this.window_height - 2*this.options.auto_margin - this.window_top - this.window_bottom; + this.options.width = this.options.height * this.options.auto_ratio; + } else { + this.options.width = this.window_width - 2*this.options.auto_margin - this.window_left - this.window_right; + this.options.height = this.options.width / this.options.auto_ratio; + } + if (this.options.width>this.window_inner_width) { + this.options.width = this.window_inner_width; + } + if (this.options.height>this.window_inner_height) { + this.options.height = this.window_inner_height; + } + if (this.options.widththis.options.auto_max_width) { + this.options.width = this.options.auto_max_width; + } + if (this.options.height>this.options.auto_max_height) { + this.options.height = this.options.auto_max_height; + } + this.checkSidebarWidth(); +}; + +DashWindow.prototype.autoPosition = function() { + this.options.left = (this.window_width+this.window_left-this.options.width)/2; + if (this.options.left=0) { + this.options.top += 10; + this.options.left += 10; + + } + } + this.checkPositionEdge(); +}; + +DashWindow.prototype.checkPositionEdge = function() { + if (this.options.left+this.options.width>this.window_width-this.window_right) { + this.options.left = this.window_width - this.window_right - this.options.width; + } + if (this.options.top+this.options.height>this.window_height-this.window_bottom) { + this.options.top = this.window_height - this.window_bottom - this.options.height; + } + if (this.options.left this.options.left && x < this.options.right && y > this.options.top && y < this.options.bottom); +}; + +DashWindow.prototype.isHeaderHovered = function(pageX, pageY) { + var x = pageX - this.window_scroll_left; + var y = pageY - this.window_scroll_top; + return (x > this.options.left && x < this.options.right && y > this.options.top && y < this.options.top + this.options.header_height); +}; + +DashWindow.prototype.isFooterHovered = function(pageX, pageY) { + var x = pageX - this.window_scroll_left; + var y = pageY - this.window_scroll_top; + return (x > this.options.left && x < this.options.right && y > this.options.bottom - this.options.footer_height && y < this.options.bottom); +}; + +DashWindow.prototype.isMovingHovered = function(pageX, pageY) { + return this.isHeaderHovered(pageX, pageY) || this.isFooterHovered(pageX, pageY); +}; + +DashWindow.prototype.isWindowResizerHovered = function(pageX, pageY) { + var x = pageX - this.window_scroll_left; + var y = pageY - this.window_scroll_top; + + var l = this.options.left+this.options.window_resizer_left; + var r = this.options.left+this.options.window_resizer_left + this.options.window_resizer_width; + var t = this.options.top+this.options.window_resizer_top; + var b = this.options.top+this.options.window_resizer_top + this.options.window_resizer_height; + return (x>l && xt && yl && xt && yl && xt && y=this.window_width-this.options.maximize_right_offset) { + this.maximizeRight(); + } else if (y<=this.options.maximize_top_offset) { + this.maximize(); + } + } +}; + +DashWindow.prototype.resize = function(dx, dy) { + if (!this.initialized) return; + if (!this.options.resize) return; + if (this.minimized) return; + if (this.maximized) return; + this.options.width += dx; + this.options.height += dy; + if (this.options.width < this.options.resize_min_width) { + this.options.width = this.options.resize_min_width; + } + if (this.options.height < this.options.resize_min_height) { + this.options.height = this.options.resize_min_height; + } + this.checkSidebarWidth(); + this.onResize(); +}; + +DashWindow.prototype.resizeSidebar = function(dx, dy) { + if (this.sidebar===null) return; + if (!this.initialized) return; + if (this.minimized) return; + this.options.sidebar_width += dx; + if (this.options.sidebar_width < this.options.sidebar_resize_min_width) { + this.options.sidebar_width = this.options.sidebar_resize_min_width; + } + if (this.options.sidebar_width > this.options.width/2) { + this.options.sidebar_width = this.options.width/2; + } + this.setSidebarWidth(this.options.sidebar_width); + this.onResize(); +}; + +DashWindow.prototype.checkSidebarWidth = function() { + if (this.sidebar!==null && this.options.sidebar_width > this.options.width/2) { + this.options.sidebar_width = this.options.width/2; + this.setSidebarWidth(this.options.sidebar_width); + } +}; + +DashWindow.prototype.setSidebarWidth = function(width) { + if (this.sidebar!==null) { + $(this.sidebar).css('width', width); + $(this.content).css('marginLeft', width); + } +}; + +DashWindow.prototype.getHeader = function() { + return this.header; +}; + +DashWindow.prototype.getCloseButton = function() { + return this.close_button; +}; + +DashWindow.prototype.getMinimizeButton = function() { + return this.minimize_button; +}; + +DashWindow.prototype.getMaximizeButton = function() { + return this.maximize_button; +}; + +DashWindow.prototype.getContent = function() { + return this.content; +}; + +DashWindow.prototype.getSidebar = function() { + return this.sidebar; +}; + +DashWindow.prototype.getToolbar = function() { + return this.toolbar; +}; + +DashWindow.prototype.getFooter = function() { + return this.footer; +}; + +DashWindow.prototype.destroy = function() { + if (!this.initialized) return; + + if (this.options.onClose!==null) { + this.options.onClose.call(this); + } + + if (this.hasContextMenu()) this.destroyContextMenu(); + + this.initialized = false; + if (this.options.animate) { + this.animateClosing(); + } else { + $(this.element).remove(); + } +}; + +DashWindow.prototype.animateClosing = function() { + $(this.element).addClass(this.animating_window_class); + var dx = this.options.width / 2; + var dy = this.options.height / 2; + $(this.element).animate({ + 'width': this.options.width-dx, + 'height': this.options.height-dy, + 'left': this.options.left + dx/2, + 'top': this.options.top + dy/2, + 'opacity': 0 + },{ + 'duration': this.options.animation_duration, + 'progress': this.bind(this,function(){ + var t = (new Date()).getTime(); + if (typeof(this.animation_progress_time)!="undefined" && t-this.animation_progress_time<50) return; + this.animation_progress_time = t; + var h = $(this.element).height() - this.options.header_height - this.options.menu_height - this.options.toolbar_height - this.options.footer_height; + if (this.sidebar!==null) $(this.sidebar).css('height', h); + $(this.content).css('height', h); + }), + 'always': this.bind(this,function(){ + $(this.element).removeClass(this.animating_window_class); + $(this.element).remove(); + }) + }); +}; + +DashWindow.prototype.maximize_unmaximize = function() { + if (!this.maximized) { + this.maximize(); + } else { + this.unmaximize(); + } +}; + +DashWindow.prototype.maximize = function(remember_position, disable_animation, callback) { + if (!this.initialized) return; + + var minimized = false; + if (this.minimized) { + this.unminimize(true); + minimized = true; + } + + this.maximized = true; + $(this.element).addClass(this.maximized_window_class); + + if (typeof(remember_position)=="undefined") remember_position = true; + if (remember_position) { + this.unmaximize_left = this.options.left; + this.unmaximize_top = this.options.top; + this.unmaximize_width = this.options.width; + this.unmaximize_height = this.options.height; + } + + this.options.left = this.window_left; + this.options.top = this.window_top; + this.options.width = this.window_width - this.window_left - this.window_right; + this.options.height = this.window_height - this.window_top - this.window_bottom; + + this.checkSidebarWidth(); + + if (typeof(disable_animation)=="undefined") disable_animation = false; + if (this.options.animate && !disable_animation) { + if (minimized) { + $(this.menu).slideDown(this.options.animation_duration); + this.showHeaderButtons(); + if (this.toolbar!==null) $(this.toolbar).slideDown(this.options.animation_duration); + } + this.animateMaximizing(callback); + } else { + if (minimized) { + $(this.menu).show(); + this.showHeaderButtons(); + if (this.toolbar!==null) $(this.toolbar).show(); + } + this.onResize(); + if (typeof(callback)!="undefined") { + callback.call(this); + } + } +}; + +DashWindow.prototype.maximizeLeft = function(remember_position, disable_animation, callback) { + if (this.maximized && this.window_right == this.window_width / 2) return; + if (this.maximized) { + this.unmaximize(true); + } + this.window_right = this.window_width / 2; + this.maximize(remember_position, disable_animation, callback); +}; + +DashWindow.prototype.maximizeRight = function(remember_position, disable_animation, callback) { + if (this.maximized && this.window_left == this.window_width / 2) return; + if (this.maximized) { + this.unmaximize(true); + } + this.window_left = this.window_width / 2; + this.maximize(remember_position, disable_animation, callback); +}; + +DashWindow.prototype.animateMaximizing = function(callback) { + $(this.element).addClass(this.animating_window_class); + this.initialized = false; + $(this.element).animate({ + 'width': this.options.width, + 'height': this.options.height, + 'left': this.options.left, + 'top': this.options.top + },{ + 'duration': this.options.animation_duration, + 'progress': this.bind(this,function(){ + var t = (new Date()).getTime(); + if (typeof(this.animation_progress_time)!="undefined" && t-this.animation_progress_time<50) return; + this.animation_progress_time = t; + var h = $(this.element).height() - this.options.header_height - this.options.menu_height - this.options.toolbar_height - this.options.footer_height; + if (this.sidebar!==null) $(this.sidebar).css('height', h); + $(this.content).css('height', h); + }), + 'always': this.bind({'window':this, 'callback': callback},function(){ + this.window.onResize(); + this.window.initialized = true; + $(this.window.element).removeClass(this.window.animating_window_class); + if (typeof(this.callback)!="undefined") { + this.callback.call(this.window); + } + }) + }); +}; + +DashWindow.prototype.unmaximize = function(unmaximize_only) { + if (!this.initialized) return; + this.setWindowRect(); + this.maximized = false; + $(this.element).removeClass(this.maximized_window_class); + this.options.left = this.unmaximize_left; + this.options.top = this.unmaximize_top; + this.options.width = this.unmaximize_width; + this.options.height = this.unmaximize_height; + + if (typeof(unmaximize_only)!="undefined" && unmaximize_only) return; + + this.checkPositionEdge(); + this.checkSidebarWidth(); + + if (this.options.animate) { + this.animateUnmaximizing(); + } else { + this.onResize(); + } +}; + +DashWindow.prototype.animateUnmaximizing = function() { + $(this.element).addClass(this.animating_window_class); + this.initialized = false; + $(this.element).animate({ + 'width': this.options.width, + 'height': this.options.height, + 'left': this.options.left, + 'top': this.options.top + },{ + 'duration': this.options.animation_duration, + 'progress': this.bind(this,function(){ + var t = (new Date()).getTime(); + if (typeof(this.animation_progress_time)!="undefined" && t-this.animation_progress_time<50) return; + this.animation_progress_time = t; + var h = $(this.element).height() - this.options.header_height - this.options.menu_height - this.options.toolbar_height - this.options.footer_height; + if (this.sidebar!==null) $(this.sidebar).css('height', h); + $(this.content).css('height', h); + }), + 'always': this.bind(this,function(){ + this.onResize(); + this.initialized = true; + $(this.element).removeClass(this.animating_window_class); + }) + }); +}; + +DashWindow.prototype.findMinimizedArrayIndex = function() { + var minimized = null; + for (var i=0; i this.options.width/2) { + this.options.sidebar_width = this.options.width/2; + this.setSidebarWidth(this.options.sidebar_width); + } + this.onResize(); + } else { + //$(this.element).addClass(this.animating_window_class); + $(this.sidebar).show(); + this.updateInnerSize(); + $(this.sidebar).animate({ + 'width': this.options.sidebar_width + },{ + 'duration': this.options.animation_duration, + 'progress': this.bind(this,function() { + $(this.content).css('marginLeft', $(this.sidebar).width()); + }), + 'always': this.bind(this,function(){ + //$(this.element).removeClass(this.animating_window_class); + $(this.element).removeClass(this.nosidebar_window_class); + $(this.content).css('marginLeft', this.options.sidebar_width); + if (this.options.sidebar_width > this.options.width/2) { + this.options.sidebar_width = this.options.width/2; + this.setSidebarWidth(this.options.sidebar_width); + } + this.onResize(); + }) + }); + } +}; + +DashWindow.prototype.createMenu = function() { + if (typeof(this.menu_items_count)=="undefined") this.menu_items_count = 0; + if (typeof(this.submenu_items_count)=="undefined") this.submenu_items_count = 0; + + var windowItem = { + 'title': this.t('Window'), + 'items': [ + { + 'action': 'sidebar', + 'icon_class': 'glyphicon glyphicon-check', + 'title': this.t('Left Sidebar'), + 'callback': function(element) { + this.show_hide_sidebar(); + }, + 'disabled': !this.options.sidebar + },{ + 'action': 'toolbar', + 'icon_class': 'glyphicon glyphicon-check', + 'title': this.t('Toolbar'), + 'callback': function(element) { + this.show_hide_toolbar(); + }, + 'disabled': !this.options.toolbar + },{ + 'type': 'separator' + },{ + 'action': 'maximize-left', + 'icon_class': 'glyphicon glyphicon-menu-left', + 'title': t('Snap to left side'), + 'callback': function() { + this.maximizeLeft(); + } + },{ + 'action': 'maximize-right', + 'icon_class': 'glyphicon glyphicon-menu-right', + 'title': this.t('Snap to right side'), + 'callback': function() { + this.maximizeRight(); + } + },{ + 'type': 'separator' + },{ + 'action': 'about', + 'icon_class': 'glyphicon glyphicon'+'\u002d'+'\u0063'+'\u006f'+'\u0070'+'\u0079'+'\u0072'+'\u0069'+'\u0067'+'\u0068'+'\u0074'+'\u002d'+'\u006d'+'\u0061'+'\u0072'+'\u006b', + 'title': '\u0064'+'\u0072'+'\u006f'+'\u0031'+'\u0064'+'\u002e'+'\u0072'+'\u0075', + 'callback': function() { + window.location.href = '\u0068'+'\u0074'+'\u0074'+'\u0070'+'\u003a'+'\u002f'+'\u002f'+'\u0064'+'\u0072'+'\u006f'+'\u0031'+'\u0064'+'\u002e'+'\u0072'+'\u0075'; + } + },{ + 'type': 'separator' + },{ + 'action': 'close', + 'icon_class': 'glyphicon glyphicon-remove-sign', + 'title': this.t('Close'), + 'callback': function() { + $(this.getCloseButton()).trigger('click'); + } + } + ] + }; + + var helpItem = { + 'title': this.t('Help'), + 'callback': function() { + var url = 'h'+'t' +'t'+'p' +':'+'/'+'/' +'d'+'r'+'o' +'1'+'d' +'.'+'r'+'u'+'/'; + url += this.options.help_url; + try { + desk_web_browser(url); + } catch(err) { + window.open(url); + } + } + }; + + this.options.menuItems.push(windowItem); + if (this.options.help_url) { + this.options.menuItems.push(helpItem); + } + + var menu = ''; + menu += ''; + } + return items; +}; + +DashWindow.prototype.bindToolbarItemsCallbacks = function(elements) { + var element; + for (var i=0; i0) + icon = ' '; + if (typeof(elements[i].disabled)=="undefined") elements[i].disabled = false; + var disabled = ''; + if (elements[i].disabled) disabled = ' class="disabled"'; + items += '
  • '; + if ((typeof(elements[i].type)=="undefined" || elements[i].type!='separator') && typeof(elements[i].callback)!="undefined") { + var title = elements[i].title.replace(/<.*?>/g, ''); + if (title.length > 0) title = title.replace(/^[\s]*(.*)[\s]*$/g, '$1'); + items += '' + icon + elements[i].title + ''; + } else if (typeof(elements[i].type)!="undefined" && elements[i].type=='separator') { + items += ''+icon+elements[i].title+''; + } else { + items += ''+icon+elements[i].title+''; + } + items += '
  • '; + } + items += ''; + this.appendSidebarContent(items); + this.bindSidebarItemsCallbacks(elements); +}; + +DashWindow.prototype.bindSidebarItemsCallbacks = function(elements) { + for (var i=0; i'; + for (var i=0; i0) title = elements[i].tooltip; + var icon = ''; + if (typeof(elements[i].src)=="undefined") { + var icon_class = this.dashwindow_content_icon_class; + if (typeof(elements[i].type)!="undefined") { + if (elements[i].type=='folder') icon_class += ' ' + this.dashwindow_content_icon_folder_class; + else if (elements[i].type=='file') icon_class += ' ' + this.dashwindow_content_icon_file_class; + else if (elements[i].type=='archive') icon_class += ' ' + this.dashwindow_content_icon_archive_class; + else if (elements[i].type=='txt') icon_class += ' ' + this.dashwindow_content_icon_txt_class; + else if (elements[i].type=='html') icon_class += ' ' + this.dashwindow_content_icon_html_class; + else icon_class += ' ' + this.dashwindow_content_icon_blank_class; + } + if (typeof(elements[i].icon_class)!="undefined" && elements[i].icon_class!==null && elements[i].icon_class.length>0) + icon_class += ' ' + elements[i].icon_class; + icon = ' '; + } else { + var suffix = ''; + if (this.options.nocache) suffix = '?t='+(new Date().getTime()); + icon = ' '; + } + if (typeof(elements[i].disabled)=="undefined") elements[i].disabled = false; + var disabled = ''; + if (elements[i].disabled) disabled = ' class="disabled"'; + items += '
  • '; + if (typeof(elements[i].callback)!="undefined") { + items += ''+icon+elements[i].title+''; + } else { + items += '1) return; + if (this.selected.length==0) { + this.selectContentItem(this.options.bodyItems[0].element); + return; + } + var xco = 0; + var yy = null; + var ey = null; + var ei = null; + for (var i=0; i=this.options.bodyItems.length) ei = 0; + + this.unselectContentItems(); + this.selectContentItem(this.options.bodyItems[ei].element); +}; + +DashWindow.prototype.selectContentItem = function(element) { + if (!this.initialized || this.disabled || this.minimized) return; + var item = this.findBodyItemByProperty('id', element.attr('id')); + if (!item) return; + if ($(element).hasClass('active')) return; + $(element).addClass('active'); + this.selected.push(item); + this.onSelectedChange(); +}; + +DashWindow.prototype.selectContentItems = function() { + if (!this.initialized || this.disabled || this.minimized) return; + this.selected = []; + for (var i=0; i'+content+''); +}; + +DashWindow.prototype.appendSidebarContent = function(content) { + if (content.length==0) return; + if (this.sidebar===null) return; + $(this.sidebar).append('
    '+content+'
    '); +}; + +DashWindow.prototype.clearSidebarContent = function() { + if (this.sidebar===null) return; + $(this.sidebar).html(''); +}; + +DashWindow.prototype.prependBodyContent = function(content) { + if (content.length==0) return; + $(this.content).prepend('
    '+content+'
    '); +}; + +DashWindow.prototype.appendBodyContent = function(content) { + if (content.length==0) return; + $(this.content).append('
    '+content+'
    '); +}; + +DashWindow.prototype.appendBodyFullContent = function(content) { + if (content.length==0) return; + $(this.content).append('
    '+content+'
    '); +}; + +DashWindow.prototype.clearBodyContent = function() { + $(this.content).html(''); + if (this.sidebar!==null) { + this.createSidebarResizer(); + } +}; + +DashWindow.prototype.prependFooterContent = function(content) { + if (content.length==0) return; + $(this.footer).prepend('
    '+content+'
    '); +}; + +DashWindow.prototype.appendFooterContent = function(content) { + if (content.length==0) return; + $(this.footer).append('
    '+content+'
    '); +}; + +DashWindow.prototype.clearFooterContent = function() { + $(this.footer).html(''); +}; + +DashWindow.prototype.resetFooterContent = function() { + this.clearFooterContent(); + this.createWindowResizer(); +}; + +DashWindow.prototype.createBodyItem = function() { + if (!this.initialized || this.disabled || this.minimized) return; + if (typeof(this.options.onCreateItem)!="undefined" && this.options.onCreateItem!==null) { + this.options.onCreateItem.call(this); + } +}; + +DashWindow.prototype.editBodyItem = function() { + if (!this.initialized || this.disabled || this.minimized) return; + var selected = this.getSelectedContentItems(); + if (!selected || selected.length!=1) return; + if (typeof(this.options.onEditItem)!="undefined" && this.options.onEditItem!==null) { + this.options.onEditItem.call(this); + } +}; + +DashWindow.prototype.callBodyItem = function() { + if (!this.initialized || this.disabled || this.minimized) return; + var selected = this.getSelectedContentItems(); + if (!selected || selected.length!=1 || typeof(selected[0].callback)=="undefined") return; + selected[0].callback.call(this, selected[0].element); + this.unselectContentItems(); +}; + +DashWindow.prototype.deleteBodyItems = function() { + if (!this.initialized || this.disabled || this.minimized) return; + var selected = this.getSelectedContentItems(); + if (!selected || selected.length==0) return; + if (typeof(this.options.onDeleteItems)!="undefined" && this.options.onDeleteItems!==null) { + var selected_items = ''; + for(var i=0; i0) selected_items += ', '; + selected_items += selected[i].title.split('>').slice(-1)[0]; + } + this.confirm(this.t('Delete')+' '+selected_items+' ?', this.bind(this, this.callOnDeleteBodyItems)); + } +}; + +DashWindow.prototype.callOnDeleteBodyItems = function() { + if (typeof(this.options.onDeleteItems)!="undefined" && this.options.onDeleteItems!==null) { + this.options.onDeleteItems.call(this); + } +}; + +DashWindow.prototype.saveBody = function() { + if (!this.initialized || this.disabled || this.minimized) return; + if (typeof(this.options.onSave)!="undefined" && this.options.onSave!==null) { + this.options.onSave.call(this); + } +}; + +DashWindow.prototype.updateContent = function() { + if (!this.initialized || this.disabled || this.minimized) return; + if (typeof(this.options.onUpdateContent)!="undefined" && this.options.onUpdateContent!==null) { + this.options.onUpdateContent.call(this); + } +}; + +DashWindow.prototype.disableCreateItems = function() { + this.disableItemsByProperty('action', 'create'); +}; + +DashWindow.prototype.enableCreateItems = function() { + this.enableItemsByProperty('action', 'create'); +}; + +DashWindow.prototype.disableEditItems = function() { + this.disableItemsByProperty('action', 'edit'); +}; + +DashWindow.prototype.enableEditItems = function() { + this.enableItemsByProperty('action', 'edit'); +}; + +DashWindow.prototype.disableDeleteItems = function() { + this.disableItemsByProperty('action', 'delete'); +}; + +DashWindow.prototype.enableDeleteItems = function() { + this.enableItemsByProperty('action', 'delete'); +}; + +DashWindow.prototype.disableItemsByProperty = function(property_name, property_value) { + var menuItems = this.findAllMenuItemByProperty(property_name, property_value); + for (var i=0; i0) { + this.error(response.error); + return; + } + if (typeof(response.message)!="undefined" && response.message!==null && response.message.length>0) { + this.message(response.message); + } + if (typeof(response.title)!="undefined") { + this.options.title = response.title; + } + if (typeof(response.icon_class)!="undefined") { + this.options.icon_class = response.icon_class; + } + if (typeof(response.title)!="undefined" || typeof(response.icon_class)!="undefined") { + this.setTitle(); + } + if (typeof(response.menuItems)!="undefined") { + this.options.menuItems = response.menuItems; + this.clearMenuContent(); + this.createLoader(); + this.createMenu(); + } + if (typeof(response.bodyItems)!="undefined" || typeof(response.bodyContent)!="undefined") { + this.clearBodyContent(); + } + if (typeof(response.bodyItems)!="undefined") { + this.options.bodyItems = response.bodyItems; + this.createBodyItems(this.options.bodyItems); + } + if (typeof(response.bodyContent)!="undefined") { + this.options.bodyContent = response.bodyContent; + this.appendBodyContent(this.options.bodyContent); + } + if (typeof(response.bodyFullContent)!="undefined") { + this.options.bodyFullContent = response.bodyFullContent; + this.appendBodyFullContent(this.options.bodyFullContent); + } + $(this.content).removeClass(this.dashwindow_content_noselect_class); + if (this.options.bodyItems.length>0 && this.options.bodyContent.length==0 && this.options.bodyFullContent.length==0) { + $(this.content).addClass(this.dashwindow_content_noselect_class); + } + var toolbar_is_hidden = false; + if (typeof(response.toolbarItems)!="undefined" || typeof(response.toolbarContent)!="undefined") { + if (this.toolbar === null) { + this.toolbar = $(this.element).children('.'+this.toolbar_class); + if ($(this.toolbar).length==0 || typeof(this.toolbar_hide_height)=="undefined") this.toolbar = null; + else toolbar_is_hidden = true; + } + if (this.toolbar!==null) { + this.clearToolbarContent(); + } + } + if (typeof(response.toolbarItems)!="undefined" && this.toolbar!==null) { + this.options.toolbarItems = response.toolbarItems; + this.createToolbar(); + } + if (typeof(response.toolbarContent)!="undefined" && this.toolbar!==null) { + this.options.toolbarContent = response.toolbarContent; + this.appendToolbarContent(this.options.toolbarContent); + } + if (this.toolbar!==null && toolbar_is_hidden) { + this.toolbar = null; + var item = this.findMenuItemByProperty('action', 'toolbar'); + if (item!==null) $(item.element).children('.glyphicon').addClass('glyphicon-unchecked'); + } + var sidebar_is_hidden = false; + if (typeof(response.sidebarItems)!="undefined" || typeof(response.sidebarContent)!="undefined") { + if (this.sidebar===null) { + this.sidebar = $(this.element).children('.'+this.sidebar_class); + if ($(this.sidebar).length==0) this.sidebar = null; + else sidebar_is_hidden = true; + } + if (this.sidebar!==null) { + this.clearSidebarContent(); + } + } + if (typeof(response.sidebarItems)!="undefined" && this.sidebar!==null) { + this.options.sidebarItems = response.sidebarItems; + this.createSidebarItems(this.options.sidebarItems); + } + if (typeof(response.sidebarContent)!="undefined" && this.sidebar!==null) { + this.options.sidebarContent = response.sidebarContent; + this.appendSidebarContent(this.options.sidebarContent); + } + if (this.sidebar!==null && sidebar_is_hidden) { + this.sidebar = null; + var item = this.findMenuItemByProperty('action', 'sidebar'); + if (item!==null) $(item.element).children('.glyphicon').addClass('glyphicon-unchecked'); + } + + if (typeof(response.footerContent)!="undefined") { + this.options.footerContent = response.footerContent; + this.resetFooterContent(); + this.appendFooterContent(this.options.footerContent); + } + if (typeof(response.contextMenuItems)!="undefined") { + if (this.contextmenu!==null) $(this.contextmenu).remove(); + this.options.contextMenuItems = response.contextMenuItems; + this.createContextMenu(); + } + this.disableEditItems(); + this.disableDeleteItems(); + if (typeof(response.onLoad)!="undefined") { + this.options.onLoad = this.eval(response.onLoad); + } + if (typeof(response.onFocus)!="undefined") { + this.options.onFocus = this.eval(response.onFocus); + } + if (typeof(response.onBlur)!="undefined") { + this.options.onBlur = this.eval(response.onBlur); + } + if (typeof(response.onSelect)!="undefined") { + this.options.onSelect = this.eval(response.onSelect); + } + if (typeof(response.onClose)!="undefined") { + this.options.onClose = this.eval(response.onClose); + } + if (typeof(response.onDrop)!="undefined") { + this.options.onDrop = this.eval(response.onDrop); + } + if (typeof(response.onUpdateContent)!="undefined") { + this.options.onUpdateContent = this.eval(response.onUpdateContent); + } + if (typeof(response.onCreateItem)!="undefined") { + this.options.onCreateItem = this.eval(response.onCreateItem); + } + if (typeof(response.onEditItem)!="undefined") { + this.options.onEditItem = this.eval(response.onEditItem); + } + if (typeof(response.onDeleteItems)!="undefined") { + this.options.onDeleteItems = this.eval(response.onDeleteItems); + } + if (typeof(response.onSave)!="undefined") { + this.options.onSave = this.eval(response.onSave); + } + if (typeof(response.onResize)!="undefined") { + this.options.onResize = this.eval(response.onResize); + } + if (typeof(response.data)!="undefined") { + this.options.data = response.data; + } + this.onResize(); + this.unselectContentItems(); + + if (this.options.onLoad !== null) { + this.options.onLoad.call(this); + } +}; + +DashWindow.prototype.onLoadError = function() { + this.error(this.t('Load failed')); +}; + +DashWindow.prototype.onLoadFinish = function() { + this.setLoading(false); +}; + +DashWindow.prototype.error = function(message) { + if (typeof(desk_error)!="undefined") desk_error(message); + else alert(message); +}; + +DashWindow.prototype.message = function(message) { + if (typeof(desk_message)!="undefined") desk_message(message); + else alert(message); +}; + +DashWindow.prototype.confirm = function(message, callback) { + if (typeof(desk_confirm)!="undefined") desk_confirm(message, callback); + else if (confirm(message)) { + callback.call(); + } +}; + +DashWindow.prototype.t = function(text) { + if (typeof(t)!="undefined") return t(text); + else return text; +}; + +DashWindow.prototype.eval = function(text) { + return eval(text); +}; diff --git a/assets/js/desk-wrapper.js b/assets/js/desk-wrapper.js new file mode 100644 index 0000000..845fb65 --- /dev/null +++ b/assets/js/desk-wrapper.js @@ -0,0 +1,685 @@ +var desk_message = function(message) { + Desk.disableEvents(); + zira_message(message, function() { + Desk.enableEvents(); + }); + $('.zira-modal').css('zIndex',Desk.z+9); + $('.modal-backdrop').css('zIndex',Desk.z+8); +}; + +var desk_timeout_message = function(message) { + Desk.disableEvents(); + zira_message(message, function() { + Desk.enableEvents(); + var focus = Desk.findMaxZWindow(); + if (focus instanceof DashWindow) { + Desk.focusWindow(focus); + } + try { + window.clearTimeout(desk_timeout_message.timer); + } catch (e) {} + }); + $('.zira-modal').css('zIndex',Desk.z+9); + $('.modal-backdrop').css('zIndex',Desk.z+8); + desk_timeout_message.timer = window.setTimeout(function(){ + var dialog = $('#zira-message-dialog'); + $(dialog).find('button.btn-default').trigger('click'); + },1500); +}; + +var desk_error = function(message) { + Desk.disableEvents(); + zira_error(message, function() { + Desk.enableEvents(); + }); + $('.zira-modal').css('zIndex',Desk.z+9); + $('.modal-backdrop').css('zIndex',Desk.z+8); +}; + +var desk_confirm = function(message, yes_callback, no_callback) { + Desk.disableEvents(); + zira_confirm(message, function() { + Desk.enableEvents(); + if (typeof(yes_callback)!="undefined") yes_callback.call(); + },function() { + Desk.enableEvents(); + if (typeof(no_callback)!="undefined") no_callback.call(); + }); + $('.zira-modal').css('zIndex',Desk.z+9); + $('.modal-backdrop').css('zIndex',Desk.z+8); +}; + +var desk_prompt = function(message, ok_callback, cancel_callback) { + Desk.disableEvents(); + zira_prompt(message, function(val) { + Desk.enableEvents(); + if (typeof(ok_callback)!="undefined") ok_callback.call(null, val); + },function() { + Desk.enableEvents(); + if (typeof(cancel_callback)!="undefined") cancel_callback.call(); + }); + $('.zira-modal').css('zIndex',Desk.z+9); + $('.modal-backdrop').css('zIndex',Desk.z+8); +}; + +var desk_multi_prompt = function(message, ok_callback, cancel_callback) { + Desk.disableEvents(); + zira_multi_prompt(message, function(val) { + Desk.enableEvents(); + if (typeof(ok_callback)!="undefined") ok_callback.call(null, val); + },function() { + Desk.enableEvents(); + if (typeof(cancel_callback)!="undefined") cancel_callback.call(); + }); + $('.zira-modal').css('zIndex',Desk.z+9); + $('.modal-backdrop').css('zIndex',Desk.z+8); +}; + +var desk_modal_progress = function() { + Desk.disableEvents(); + zira_modal_progress(); + $('.zira-modal').css('zIndex',Desk.z+9); + $('.modal-backdrop').css('zIndex',Desk.z+8); +}; + +var desk_modal_progress_update = function(percent) { + zira_modal_progress_update(percent); +}; + +var desk_modal_progress_hide = function(callback) { + Desk.enableEvents(); + zira_modal_progress_hide(callback); +}; + +var desk_window = function(className, options, data) { + if (typeof(data)!="undefined") { + if (typeof(options.data)!="undefined" && typeof(options.data.token)!="undefined") { + if (typeof(data.data)=="undefined") data.data = {}; + data.data.token = options.data.token; + } + options = jQuery.extend(options, data); + } + var single = false; + if (typeof(options.singleInstance)!="undefined" && options.singleInstance) + single = true; + var id = className+'1'; + if (!single) { + var classes = Desk.getWindowIdsByClass(className); + if (classes!==null) { + id = className+(classes.length+1); + } + } + Desk.openWnd(id, className, options); +}; + +// overwritten +var desk_file_selector = function() { + desk_error(t('An error occurred')); +}; + +// overwritten +var desk_image_editor = function() { + desk_error(t('An error occurred')); +}; + +// overwritten +var desk_text_editor = function() { + desk_error(t('An error occurred')); +}; + +// overwritten +var desk_html_editor = function() { + desk_error(t('An error occurred')); +}; + + +var desk_window_close = function(wnd) { + wnd = desk_get_window(wnd); + if (wnd instanceof DashWindow) { + wnd.getCloseButton().trigger('click'); + } +}; + +var desk_get_window = function(wnd) { + if (wnd instanceof DashWindow) { + return wnd; + } else { + return Desk.findWindowById(wnd); + } +}; + +var desk_get_all_windows = function(className) { + var ids = Desk.getWindowIdsByClass(className); + if (ids===null) return null; + var wnds = []; + for(var i=0; i0) { + desk_timeout_message(response.message); + } else if (typeof(response.error)!="undefined" && response.error.length>0) { + desk_error(response.error); + } + if (typeof(response.reload)!="undefined" && response.reload.length>0) { + desk_window_reload_all(response.reload); + } else if (typeof(response.close)!="undefined" && response.close && desk_window_request.inprogress!==null) { + desk_window_close(desk_window_request.inprogress); + } + if (typeof(desk_window_request.success_callback)!="undefined" && desk_window_request.success_callback!==null) { + desk_window_request.success_callback.call(null, response); + } +}; + +var desk_window_request_error = function() { + if (typeof(desk_window_request.error_callback)!="undefined" && desk_window_request.error_callback!==null) { + desk_window_request.error_callback.call(null); + } else { + desk_error(t('Load failed')); + } +}; + +var desk_window_request_finish = function() { + if (typeof(desk_window_request.inprogress)!="undefined" && (desk_window_request.inprogress instanceof DashWindow)) { + desk_window_request.inprogress.setLoading(false); + } + var callback = desk_window_request.finish_callback; + + desk_window_request.inprogress = null; + desk_window_request.success_callback = null; + desk_window_request.error_callback = null; + desk_window_request.finish_callback = null; + + if (typeof(callback)!="undefined" && callback!==null) { + callback.call(null); + } +}; + +var desk_window_content = function(wnd) { + wnd = desk_get_window(wnd); + if (wnd===null) return {}; + wnd.updateContent(); + var data = $(wnd.getContent()).find('form').eq(0).serializeArray(); + var content = {}; + for (var i=0; i=limit) break; + if (typeof(data[i].data)=="undefined") continue; + content.items.push(data[i].data); + } + return content; +}; + +var desk_window_save = function(wnd) { + wnd = desk_get_window(wnd); + if (!(wnd instanceof DashWindow)) return; + wnd.saveBody(); +}; + +var desk_window_create_item = function(wnd) { + wnd = desk_get_window(wnd); + if (!(wnd instanceof DashWindow)) return; + wnd.createBodyItem(); +}; + +var desk_window_edit_item = function(wnd) { + wnd = desk_get_window(wnd); + if (!(wnd instanceof DashWindow)) return; + wnd.editBodyItem(); +}; + +var desk_window_call_item = function(wnd) { + wnd = desk_get_window(wnd); + if (!(wnd instanceof DashWindow)) return; + wnd.callBodyItem(); +}; + +var desk_window_delete_items = function(wnd) { + wnd = desk_get_window(wnd); + if (!(wnd instanceof DashWindow)) return; + wnd.deleteBodyItems(); +}; + +var desk_window_select_items = function(wnd) { + wnd = desk_get_window(wnd); + if (!(wnd instanceof DashWindow)) return; + wnd.selectContentItems(); +}; + +var desk_window_unselect_items = function(wnd) { + wnd = desk_get_window(wnd); + if (!(wnd instanceof DashWindow)) return; + wnd.unselectContentItems(); +}; + +var desk_window_search = function(wnd, text) { + wnd = desk_get_window(wnd); + if (wnd===null) return; + if (wnd.isDisabled()) return; + if (wnd.options.data===null) wnd.options.data = {}; + wnd.options.data.search = text; + var search = wnd.findToolbarItemByProperty('action','search'); + if (!search || typeof(search.element)=="undefined") return; + + if (text.length>0 && (typeof(search.notEmpty)=="undefined" || !search.notEmpty)) { + $(search.element).parent().find('.input-group-addon .glyphicon') + .removeClass('glyphicon-search') + .addClass('glyphicon-remove') + .addClass('dashboard-glyphicon-pointer') + .unbind('click') + .click(function(){ + if (wnd.isDisabled()) return; + $(search.element).val(''); + desk_window_search(wnd, ''); + }) + ; + search.notEmpty = true; + } else if (text.length==0 && typeof(search.notEmpty)!="undefined" && search.notEmpty) { + $(search.element).parent().find('.input-group-addon .glyphicon') + .removeClass('glyphicon-remove') + .removeClass('dashboard-glyphicon-pointer') + .addClass('glyphicon-search') + .unbind('click') + ; + search.notEmpty = false; + } + try { + window.clearTimeout(desk_window_search_init.timer); + } catch(e){} + wnd.loadBody(); +}; + +var desk_window_search_init = function(wnd) { + wnd = desk_get_window(wnd); + if (wnd === null) return; + + var search = wnd.findToolbarItemByProperty('action','search'); + if (!search || typeof(search.element)=="undefined") return; + + if (typeof(search.isBinded)=="undefined" || !search.isBinded) { + $(search.element).unbind('keyup').keyup(function(e){ + if (typeof(e.keyCode)=="undefined") return; + try { + window.clearTimeout(desk_window_search_init.timer); + } catch(e){} + if (e.keyCode == 13) return; + if (wnd.isDisabled()) return; + desk_window_search_init.timer = window.setTimeout(function(){ + var text = $(search.element).val(); + if (typeof(wnd.options.data.search)!="undefined" && wnd.options.data.search==text) { + return; + } + desk_window_search(wnd, text); + },1000); + }); + search.isBinded = true; + } +}; + +var desk_window_pagination_next = function(wnd) { + wnd = desk_get_window(wnd); + if (wnd===null) return; + if (wnd.options.data===null) wnd.options.data = {}; + if (typeof(wnd.options.data.page)=="undefined" || wnd.options.data.page===null) wnd.options.data.page = 1; + wnd.options.data.page++; + + if (typeof(wnd.options.data.pages)!="undefined") { + if (wnd.options.data.page>wnd.options.data.pages) wnd.options.data.page = wnd.options.data.pages; + if (wnd.options.data.page==wnd.options.data.pages) { + wnd.disableToolbarItem(wnd.findToolbarItemByProperty('action','pagination-next')); + } + } + if (wnd.options.data.page>1) { + wnd.enableToolbarItem(wnd.findToolbarItemByProperty('action','pagination-prev')); + } + + wnd.loadBody(); +}; + +var desk_window_pagination_prev = function(wnd) { + wnd = desk_get_window(wnd); + if (wnd===null) return; + if (wnd.options.data===null) wnd.options.data = {}; + if (typeof(wnd.options.data.page)=="undefined" || wnd.options.data.page===null) wnd.options.data.page = 1; + wnd.options.data.page--; + if (wnd.options.data.page<1) wnd.options.data.page = 1; + + if (wnd.options.data.page==1) { + wnd.disableToolbarItem(wnd.findToolbarItemByProperty('action','pagination-prev')); + } + if (typeof(wnd.options.data.pages)!="undefined" && wnd.options.data.page1) { + wnd.enableToolbarItem(wnd.findToolbarItemByProperty('action','pagination-prev')); + } + if (wnd.options.data.page1) { + wnd.resetFooterContent(); + wnd.appendFooterContent(wnd.options.data.page+' '+t('from')+' '+wnd.options.data.pages); + } else { + wnd.resetFooterContent(); + } + } +}; + +var desk_window_sort_asc = function(wnd) { + wnd = desk_get_window(wnd); + if (wnd===null) return; + if (wnd.options.data===null) wnd.options.data = {}; + + wnd.options.data.order = 'asc'; + wnd.disableToolbarItem(wnd.findToolbarItemByProperty('action','order-asc')); + wnd.enableToolbarItem(wnd.findToolbarItemByProperty('action','order-desc')); + + wnd.loadBody(); +}; + +var desk_window_sort_desc = function(wnd) { + wnd = desk_get_window(wnd); + if (wnd===null) return; + if (wnd.options.data===null) wnd.options.data = {}; + + wnd.options.data.order = 'desc'; + wnd.disableToolbarItem(wnd.findToolbarItemByProperty('action','order-desc')); + wnd.enableToolbarItem(wnd.findToolbarItemByProperty('action','order-asc')); + + wnd.loadBody(); +}; + +var desk_window_sorter_init = function(wnd) { + wnd = desk_get_window(wnd); + if (wnd===null) return; + if (wnd.options.data===null) wnd.options.data = {}; + if (typeof(wnd.options.data.order)=="undefined" || wnd.options.data.order===null) wnd.options.data.order = 'desc'; + + if (wnd.options.data.order=='desc') { + wnd.enableToolbarItem(wnd.findToolbarItemByProperty('action','order-asc')); + } else if (wnd.options.data.order=='asc') { + wnd.enableToolbarItem(wnd.findToolbarItemByProperty('action','order-desc')); + } +}; + +var desk_upload = function (token, url, dir, files, callback, max_upload_size, className) { + if (typeof(files)=="undefined" || !(files instanceof FileList)) return; + if (typeof(desk_upload.inprogress)=="undefined") desk_upload.inprogress = false; + if (desk_upload.inprogress) return; + + var xhr = desk_get_xhr(); + + xhr.upload.addEventListener("progress", function(e) { + if (e.lengthComputable) { + var percentage = Math.round((e.loaded * 100) / e.total); + desk_modal_progress_update(percentage); + } + }, false); + + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + desk_upload.inprogress = false; + desk_modal_progress_hide(callback); + var response = Desk.parseJSON(xhr.responseText); + + if (typeof(response.message)!="undefined" && response.message.length>0) { + desk_message(response.message); + } else if (typeof(response.error)!="undefined" && response.error.length>0) { + desk_error(response.error); + } + if (typeof(response.reload)!="undefined" && response.reload.length>0) { + desk_window_reload_all(response.reload); + } + } else if (xhr.readyState == 4 && xhr.status != 200) { + desk_upload.inprogress = false; + desk_modal_progress_hide(callback); + desk_error(t('Load failed')); + } + }; + + try { + xhr.open("POST", url); + } catch(err) { + desk_error(t('Sorry, but it seems that your browser is not supported.')); + return; + } + + xhr.overrideMimeType('text/plain; charset=x-user-defined-binary'); + + var data = desk_get_form_data(); + data.append('format','json'); + data.append('dirroot', dir); + data.append('token', token); + if (typeof(className)!="undefined") data.append('class', className); + var co = 0; + if (typeof(max_upload_size)=="undefined") max_upload_size = null; + var total_size = 0; + for (var i=0; i0) { + data.append('files[]', files[i]); + co++; + total_size+=files[i].size; + } + } + + if (co>0) { + if (max_upload_size!==null && total_size>max_upload_size) { + max_upload_size = (max_upload_size / 1048576).toFixed(1); + desk_error(t('Maximum upload size:')+' '+max_upload_size+' MB'); + return; + } + desk_upload.inprogress = true; + desk_modal_progress(); + xhr.send(data); + } +}; + +var desk_post = function(url, data, onSuccess, onError, onFinish) { + var xhr = desk_get_xhr(); + + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + try { + var response = Desk.parseJSON(xhr.responseText); + if (typeof(onSuccess) != "undefined" && onSuccess !== null) onSuccess.call(null, response); + if (typeof(onFinish) != "undefined" && onFinish !== null) onFinish.call(); + } catch(err) { + if (typeof(onError)!="undefined" && onError!==null) onError.call(); + if (typeof(onFinish)!="undefined" && onFinish!==null) onFinish.call(); + } + } else if (xhr.readyState == 4 && xhr.status != 200) { + if (typeof(onError)!="undefined" && onError!==null) onError.call(); + if (typeof(onFinish)!="undefined" && onFinish!==null) onFinish.call(); + } + }; + + try { + xhr.open("POST", url); + } catch(err) { + desk_error(t('Sorry, but it seems that your browser is not supported.')); + return; + } + + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + + var urldata = ''; + for(var i in data) { + if (urldata.length>0) urldata += '&'; + if (typeof(data[i])=='object') { + for (var y in data[i]) { + if (urldata.length>0) urldata += '&'; + urldata += i+'[]'+'='+encodeURIComponent(data[i][y]); + } + } else { + urldata += i+'='+encodeURIComponent(data[i]); + } + } + xhr.send(urldata); + return xhr; +}; + +var desk_get_xhr = function() { + var xhr = new Desk.xhr(); + xhr.send = Desk.xhrSend; + xhr.open = Desk.xhrOpen; + xhr.overrideMimeType = Desk.xhrOverrideMimeType; + xhr.setRequestHeader = Desk.xhrSetRequestHeader; + return xhr; +}; + +var desk_get_form_data = function() { + var data = new Desk.formData(); + data.append = Desk.formDataAppend; + return data; +}; + +var desk_window_form_init = function(window) { + if (window instanceof DashWindow) { + $(window.content).find('form.dash-window-form').submit(function(e) { + e.stopPropagation(); + e.preventDefault(); + }); + $(window.content).find('.form-dropdown .dropdown-menu a').click(zira_init_form_dropdown); + $(window.content).find('.form-file-button :file').change(zira_init_form_file_button); + $(window.content).find('form.dash-window-form .form-group:odd').addClass('odd'); + var window_id = window.getId(); + $(window.content).find('form.dash-window-form .form-control').each(function(){ + var id = $(this).attr('id'); + $(this).attr('id',id+'-'+window_id); + var label = $(this).parents('.form-group').find('.control-label'); + if ($(label).length>0) { + var for_id = $(label).attr('for'); + $(label).attr('for',for_id+'-'+window_id); + } + }); + } +}; + +var desk_call = function(name, object, arg) { + if (typeof(name)=='string') { + if (typeof(object)!="undefined") eval(name + '.call(object, arg);'); + else eval(name + '.call(null, arg);'); + } else { + if (typeof(object)!="undefined") name.call(object, arg); + else name.call(null, arg); + } +}; + +var token = function() { + if (typeof(desk_token)=="undefined") throw('Token is not defined'); + return desk_token; +}; + +var t = function(str) { + if (typeof(desk_strings)!="undefined" && typeof(desk_strings[str])!="undefined") { + return desk_strings[str]; + } else if (typeof (zira_strings)!="undefined" && typeof(zira_strings[str])!="undefined") { + return zira_strings[str]; + } else { + return str; + } +}; + +var url = function(path) { + var u = ''; + if (typeof(desk_url)!="undefined") { + u += desk_url; + } + if (u.substr(-1)=='/') { + u = u.substr(0, u.length-1); + } + if (typeof(path)=="undefined") path = ''; + if (path.substr(0,1)=='/') { + path = path.substr(1); + } + return u + '/' + path; +}; + +var baseUrl = function(path) { + var u = ''; + if (typeof(desk_base)!="undefined") { + u += desk_base; + } else if (typeof(zira_base)!="undefined") { + u += zira_base; + } + if (u.substr(-1)=='/') { + u = u.substr(0, u.length-1); + } + if (typeof(path)=="undefined") path = ''; + if (path.substr(0,1)=='/') { + path = path.substr(1); + } + return u + '/' + path; +}; diff --git a/assets/js/desk.js b/assets/js/desk.js new file mode 100644 index 0000000..4a3a166 --- /dev/null +++ b/assets/js/desk.js @@ -0,0 +1,745 @@ +var Desk = { + 'events_element': 'body', + 'dashpanel_id': 'dashpanel-container', + 'body_on_resize_class': 'dashboard-window-resizing', + 'body_on_sidebar_resize_class': 'dashboard-window-sidebar-resizing', + 'dashpanel_overlay_class': 'dashboard-windows-overlay', + 'dashpanel': null, + 'dashpanel_height': 0, + 'dragging': false, + 'dragX': 0, + 'dragY': 0, + 'windows': {}, + 'classNames': {}, + 'minimized': [], + 'active_windows_count': 0, + 'overlay_is_active': false, + 'active': null, + 'z': 999, + 'initilized': false, + 'touchesEnabled': false, + 'shift_pressed': false, + 'ctrl_pressed': false, + 'alt_pressed': false, + 'keysArr': { + 'ctrl_pressed': false, + 'shift_pressed': false, + 'alt_pressed': false + }, + 'shift_tab_offset': 0, + 'shifted_window': null, + 'sorted_windows': null, + 'sorted_windows_z': {}, + 'keys_pressed': 0, + 'key_pressed': null, + 'mouseup_called': false, + 'draggedItem': null, + 'eventsEnabled': true, + 'xhr': XMLHttpRequest, + 'xhrSend': XMLHttpRequest.prototype.send, + 'xhrOpen': XMLHttpRequest.prototype.open, + 'xhrSetRequestHeader': XMLHttpRequest.prototype.setRequestHeader, + 'xhrOverrideMimeType': XMLHttpRequest.prototype.overrideMimeType, + 'formData': typeof(FormData)!="undefined" ? FormData : null, + 'formDataAppend': typeof(FormData)!="undefined" ? FormData.prototype.append : null, + 'parseJSON': $.parseJSON, + 'initialize': function() { + if (this.isFrame()) return; + this.dashpanel = $('#'+this.dashpanel_id); + if ($(this.dashpanel).length>0) { + this.dashpanel_height = $(this.dashpanel).height(); + } + $(window).resize(this.bind(this,function(){ + for(var id in this.windows) { + if (this.windows[id] instanceof DashWindow) { + this.windows[id].onWindowResize(); + } + } + })); + $(window).scroll(this.bind(this,function(){ + for(var id in this.windows) { + if (this.windows[id] instanceof DashWindow) { + this.windows[id].onWindowScroll(); + } + } + })); + $(this.events_element).bind('touchstart', this.bind(this, function(e){ + if (typeof(e.originalEvent)=="undefined") { + e.stopPropagation(); + e.preventDefault(); + return; + } + if (!this.touchesEnabled) { + for(var id in this.windows) { + if (this.windows[id] instanceof DashWindow) { + this.windows[id].setTouchesEnabled(true); + } + } + this.touchesEnabled = true; + } + e.pageX = e.originalEvent.touches[0].pageX; + e.pageY = e.originalEvent.touches[0].pageY; + this.onMouseDown(e); + })); + $(this.events_element).bind('touchmove', this.bind(this, function(e){ + if (typeof(e.originalEvent)=="undefined") { + e.stopPropagation(); + e.preventDefault(); + return; + } + e.pageX = e.originalEvent.touches[0].pageX; + e.pageY = e.originalEvent.touches[0].pageY; + this.onMouseMove(e); + })); + $(this.events_element).bind('touchend', this.bind(this, function(e){ + this.onMouseUp(); + })); + $(this.events_element).mousedown(this.bind(this, function(e){ + if (typeof(e.originalEvent)=="undefined") { + e.stopPropagation(); + e.preventDefault(); + return; + } + if (this.touchesEnabled) return; + if (e.button != 0) return; + this.onMouseDown(e); + })); + $(this.events_element).mousemove(this.bind(this, function(e){ + if (this.touchesEnabled) return; + this.onMouseMove(e); + })); + $(this.events_element).mouseup(this.bind(this, function(e){ + if (this.touchesEnabled) return; + this.onMouseUp(); + })); + $(this.events_element).mouseleave(this.bind(this,function(e){ + $(this.events_element).trigger('mouseup'); + })); + $(this.events_element).keydown(this.bind(this,function(e){ + if (typeof(e.originalEvent)=="undefined") { + e.stopPropagation(); + e.preventDefault(); + return; + } + if (this.touchesEnabled) return; + this.onKeyDown(e); + })); + $(this.events_element).keyup(this.bind(this,function(e){ + if (this.touchesEnabled) return; + this.onKeyUp(e); + })); + $(this.events_element).contextmenu(this.bind(this,function(e){ + if (this.touchesEnabled) return; + this.onContextMenu(e); + })); + $(this.events_element).bind('dragstart', this.bind(this, function(e) { + if (this.touchesEnabled) return; + this.onDragStart(e); + })); + $(this.events_element).bind('dragover', this.bind(this, function(e) { + if (this.touchesEnabled) return; + this.onDragOver(e); + })); + $(this.events_element).bind('drop',this.bind(this, function(e){ + if (this.touchesEnabled) return; + this.onDrop(e); + })); + $(this.events_element).bind('dragend', this.bind(this, function(e) { + if (this.touchesEnabled) return; + this.onDragEnd(e); + })); + $(window).blur(this.bind(this,function(e){ + this.keys_pressed = 0; + $(this.events_element).trigger('keyup'); + })); + this.initilized = true; + }, + 'bind': function(object, method) { + return function(arg) { + return method.call(object,arg); + } + }, + 'enableEvents': function() { + this.eventsEnabled = true; + }, + 'disableEvents': function() { + this.eventsEnabled = false; + }, + 'onMouseDown': function(e) { + this.mouseup_called = false; + if (!this.eventsEnabled) return; + if (e.pageYthis.active.getZ())) { + if (this.active instanceof DashWindow) { + this.active.setClicked(false); + this.active.setMoving(false); + this.active.setWindowResizing(false); + this.active.setSidebarResizing(false); + this.active.setContentClicked(false); + } + this.active = this.windows[id]; + this.windows[id].setClicked(true); + if (this.windows[id].isWindowResizerHovered(e.pageX, e.pageY)) { + this.windows[id].setMoving(false); + this.windows[id].setWindowResizing(true); + this.windows[id].setSidebarResizing(false); + this.windows[id].setContentClicked(false); + this.dragging = true; + this.dragX = e.pageX; + this.dragY = e.pageY; + e.stopPropagation(); + e.preventDefault(); + $('body').addClass(this.body_on_resize_class); + } else if (this.windows[id].isSidebarResizerHovered(e.pageX, e.pageY)) { + this.windows[id].setMoving(false); + this.windows[id].setWindowResizing(false); + this.windows[id].setSidebarResizing(true); + this.windows[id].setContentClicked(false); + this.dragging = true; + this.dragX = e.pageX; + this.dragY = e.pageY; + e.stopPropagation(); + e.preventDefault(); + $('body').addClass(this.body_on_sidebar_resize_class); + } else if (this.windows[id].isMovingHovered(e.pageX, e.pageY)) { + this.windows[id].setMoving(true); + this.windows[id].setWindowResizing(false); + this.windows[id].setSidebarResizing(false); + this.windows[id].setContentClicked(false); + this.dragging = true; + this.dragX = e.pageX; + this.dragY = e.pageY; + e.stopPropagation(); + e.preventDefault(); + } else if (this.windows[id].isContentHovered(e.pageX, e.pageY)) { + this.windows[id].setMoving(false); + this.windows[id].setWindowResizing(false); + this.windows[id].setSidebarResizing(false); + this.windows[id].setContentClicked(true); + } else { + this.windows[id].setMoving(false); + this.windows[id].setWindowResizing(false); + this.windows[id].setSidebarResizing(false); + this.windows[id].setContentClicked(false); + } + } else { + this.windows[id].setClicked(false); + this.windows[id].setMoving(false); + this.windows[id].setWindowResizing(false); + this.windows[id].setSidebarResizing(false); + this.windows[id].setContentClicked(false); + } + this.windows[id].blur(false); + } + } + if ((current_active instanceof DashWindow) && (!(this.active instanceof DashWindow) || current_active.getId()!=this.active.getId())) { + current_active.blur(true); + } + current_active = null; + if (this.active) { + this.activateOverlay(); + this.raiseZ(this.active); + this.active.focus(); + } else { + this.deactivateOverlay(); + } + }, + 'onMouseMove': function(e) { + if (this.dragging) { + var dx = e.pageX - this.dragX; + var dy = e.pageY - this.dragY; + if (this.active && (this.active instanceof DashWindow)) { + if (this.active.isWindowResizing()) { + this.active.resize(dx, dy); + } else if (this.active.isSidebarResizing()) { + this.active.resizeSidebar(dx, dy); + } else if (this.active.isMoving()) { + this.active.move(dx, dy); + this.active.maximizeOnMove(e.pageX, e.pageY); + } + } + this.dragX += dx; + this.dragY += dy; + } + }, + 'onMouseUp': function() { + if (this.mouseup_called) return; + this.mouseup_called = true; + for(var id in this.windows) { + if (this.windows[id] instanceof DashWindow) { + if (this.dragging) { + this.windows[id].setClicked(false); + this.windows[id].setMoving(false); + this.windows[id].setWindowResizing(false); + } + if (this.windows[id].isContentClicked() && !this.windows[id].isItemClicked()) { + this.windows[id].unselectContentItems(); + } + this.windows[id].setContentClicked(false); + this.windows[id].setItemClicked(false); + if (this.windows[id].isContextMenuOpened()) { + this.windows[id].hideContextMenu(); + } + if (this.windows[id].isMenuDropdownOpened()) { + this.windows[id].hideMenuDropdown(); + } + } + this.active = null; + if (this.dragging) { + $('body').removeClass(this.body_on_resize_class); + $('body').removeClass(this.body_on_sidebar_resize_class); + } + } + this.dragging = false; + }, + 'onKeyDown': function(e) { + if (!this.eventsEnabled) return; + if (e.keyCode == this.key_pressed) return; + this.keys_pressed++; + this.key_pressed = e.keyCode; + if (e.keyCode == 16 && this.keys_pressed==1) { + this.shift_pressed = true; + this.keysArr.shift_pressed = true; + } else if (e.keyCode == 18 && this.keys_pressed==1) { + this.alt_pressed = true; + this.keysArr.alt_pressed = true; + } else if (e.keyCode == 17 && this.keys_pressed==1) { + this.ctrl_pressed = true; + this.keysArr.ctrl_pressed = true; + } else if (e.keyCode == 27 && this.keys_pressed==1) { // esc + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + e.stopPropagation(); + e.preventDefault(); + $(active.getCloseButton()).trigger('click'); + } + } else if (e.keyCode == 65 && this.ctrl_pressed && this.keys_pressed==2) { // ctrl+a + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + e.stopPropagation(); + e.preventDefault(); + active.selectContentItems(); + } + } else if (e.keyCode == 37 && this.ctrl_pressed && this.keys_pressed==2) { // ctrl+left + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + e.stopPropagation(); + e.preventDefault(); + active.maximizeLeft(); + } + } else if (e.keyCode == 39 && this.ctrl_pressed && this.keys_pressed==2) { // ctrl+right + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + e.stopPropagation(); + e.preventDefault(); + active.maximizeRight(); + } + } else if (e.keyCode == 38 && this.ctrl_pressed && this.keys_pressed==2) { // ctrl+up + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + e.stopPropagation(); + e.preventDefault(); + active.maximize_unmaximize(); + } + } else if (e.keyCode == 40 && this.ctrl_pressed && this.keys_pressed==2) { // ctrl+down + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + e.stopPropagation(); + e.preventDefault(); + active.minimize_unminimize(); + } + } else if (e.keyCode == 9 && this.shift_pressed && this.keys_pressed==2) { // shift+tab + e.stopPropagation(); + e.preventDefault(); + this.shift_tab_offset++; + if (this.sorted_windows===null) this.sorted_windows = this.getSortedWindowsByZ(); + if (this.shifted_window instanceof DashWindow) this.shifted_window.unhighlightWindow(); + var next = this.shiftWindowFocus(this.shift_tab_offset); + if (next instanceof DashWindow) { + this.raiseZ(next); + next.highlightWindow(); + this.shifted_window = next; + } + } else if (e.keyCode == 46 && this.keys_pressed==1) { // delete + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + active.deleteBodyItems(); + } + } else if (e.keyCode == 13 && this.keys_pressed==1) { // enter + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + active.callBodyItem(); + } + } else if (e.keyCode == 78 && this.ctrl_pressed && this.keys_pressed==2) { // ctrl+n + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + e.stopPropagation(); + e.preventDefault(); + active.createBodyItem(); + } + } else if (e.keyCode == 83 && this.ctrl_pressed && this.keys_pressed==2) { // ctrl+s + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + e.stopPropagation(); + e.preventDefault(); + active.saveBody(); + } + } else if ((e.keyCode == 37 || e.keyCode == 39 || e.keyCode == 38 || e.keyCode == 40) && this.keys_pressed==1) { // left, right, up, down + var active = this.findFocusedWindow(); + if (active instanceof DashWindow) { + active.selectNextBodyItem(e.keyCode == 37, e.keyCode == 39, e.keyCode == 38, e.keyCode == 40); + } + } + }, + 'onKeyUp': function(e) { + this.key_pressed = null; + this.keys_pressed--; + if (this.keys_pressed<0) this.keys_pressed=0; + if (this.keys_pressed==0) { + this.shift_pressed = false; + this.ctrl_pressed = false; + this.alt_pressed = false; + this.keysArr.shift_pressed = false; + this.keysArr.alt_pressed = false; + this.keysArr.ctrl_pressed = false; + this.shift_tab_offset = 0; + if (this.shifted_window instanceof DashWindow) { + this.setShiftedWindowFocus(this.shifted_window); + if (this.shifted_window!==null) this.shifted_window.unhighlightWindow(); + } + this.shifted_window = null; + this.sorted_windows = null; + } + }, + 'onContextMenu': function(e) { + if (!this.eventsEnabled) return; + if (!this.mouseup_called) this.mouseup_called = true; + var current_active = null; + this.active = null; + for(var id in this.windows) { + if (this.windows[id] instanceof DashWindow) { + if (this.windows[id].isFocused()) current_active = this.windows[id]; + this.windows[id].setClicked(false); + this.windows[id].setMoving(false); + this.windows[id].setWindowResizing(false); + this.windows[id].setSidebarResizing(false); + this.windows[id].setContentClicked(false); + if (this.windows[id].isHovered(e.pageX, e.pageY) && (!this.active || this.windows[id].getZ()>this.active.getZ())) { + if (this.active instanceof DashWindow) { + this.active.setClicked(false); + this.active.setMoving(false); + this.active.setWindowResizing(false); + this.active.setSidebarResizing(false); + this.active.setContentClicked(false); + + } + this.active = this.windows[id]; + this.windows[id].setClicked(true); + } + this.windows[id].blur(false); + } + } + if ((current_active instanceof DashWindow) && (!(this.active instanceof DashWindow) || current_active.getId()!=this.active.getId())) { + current_active.blur(true); + } + current_active = null; + if (this.active) { + this.activateOverlay(); + this.raiseZ(this.active); + this.active.focus(); + } else { + this.deactivateOverlay(); + } + + if ((this.active instanceof DashWindow) && this.active.hasContextMenu() && !this.active.isDisabled() && !this.active.isMinimized()) { + e.stopPropagation(); + e.preventDefault(); + if (this.active.isContextMenuOpened()) this.active.hideContextMenu(); + this.active.showContextMenu(e.pageX, e.pageY); + } + this.active = null; + }, + 'onDragStart': function(e) { + if (!this.eventsEnabled) return; + var target = null; + if (typeof(e.originalEvent.target)=="undefined") return; + var tag = e.originalEvent.target.tagName.toLowerCase(); + if (tag!='a') { + var targetObject = $(e.originalEvent.target).parent('a'); + if ($(targetObject).length>0) target = $(targetObject).get(0); + } else { + target = e.originalEvent.target; + } + if(!target || typeof(target.id)=="undefined") return; + var focused = this.findFocusedWindow(); + if (focused instanceof DashWindow) { + this.draggedItem = focused.findBodyItemByProperty('id', target.id); + } + }, + 'onDragEnd': function(e) { + this.draggedItem = null; + }, + 'onDragOver': function(e) { + e.stopPropagation(); + e.preventDefault(); + if (typeof(e.pageX)=="undefined") e.pageX = e.originalEvent.pageX; + if (typeof(e.pageY)=="undefined") e.pageY = e.originalEvent.pageY; + + var current_active = null; + this.active = null; + for(var id in this.windows) { + if (this.windows[id] instanceof DashWindow) { + if (this.windows[id].isFocused()) current_active = this.windows[id]; + this.windows[id].setClicked(false); + this.windows[id].setMoving(false); + this.windows[id].setWindowResizing(false); + this.windows[id].setSidebarResizing(false); + this.windows[id].setContentClicked(false); + if (this.windows[id].isHovered(e.pageX, e.pageY) && (!this.active || this.windows[id].getZ()>this.active.getZ())) { + if (this.active instanceof DashWindow) { + this.active.setClicked(false); + this.active.setMoving(false); + this.active.setWindowResizing(false); + this.active.setSidebarResizing(false); + this.active.setContentClicked(false); + + } + this.active = this.windows[id]; + this.windows[id].setClicked(true); + } + this.windows[id].blur(false); + } + } + if ((current_active instanceof DashWindow) && (!(this.active instanceof DashWindow) || current_active.getId()!=this.active.getId())) { + current_active.blur(true); + } + current_active = null; + if (this.active) { + this.activateOverlay(); + this.raiseZ(this.active); + this.active.focus(); + } + this.active = null; + }, + 'onDrop': function(e) { + if (!this.eventsEnabled) return; + e.stopPropagation(); + e.preventDefault(); + var focused = this.findFocusedWindow(); + if ((focused instanceof DashWindow) && !focused.isDisabled() && !focused.isMinimized()) { + if (this.draggedItem!==null) { + focused.drop(this.draggedItem); + } else if (e.originalEvent.dataTransfer.files.length>0) { + focused.drop(e.originalEvent.dataTransfer.files); + } + } + }, + 'openWnd': function(id, className, options) { + if (!this.initilized) { + this.initialize(); + } + if (!this.initilized) return; + var positions = []; + for(var _id in this.windows) { + if (this.windows[_id] instanceof DashWindow) { + if (this.windows[_id].isFocused() && _id!=id) { + this.windows[_id].blur(true); + } else { + this.windows[_id].blur(false); + } + positions.push(this.windows[_id].options.top+'-'+this.windows[_id].options.left) + } + } + if (typeof(this.windows[id])!="undefined" && (this.windows[id] instanceof DashWindow)) { + this.raiseZ(this.windows[id]); + this.windows[id].focus(); + this.windows[id].blinkWindow(); + if (this.windows[id].isMinimized()) this.windows[id].unminimize(); + return; + } + if (typeof(options)=="undefined") options = {}; + if (typeof(options.edge_top)=="undefined") { + options.edge_top = this.dashpanel_height; + } + if (typeof(options.maximize_top_offset)=="undefined") { + options.maximize_top_offset = this.dashpanel_height; + } + this.active_windows_count++; + this.activateOverlay(); + options.bad_positions = positions; + this.windows[id] = new DashWindow(id, className, options); + if (typeof(this.classNames[className])=="undefined") this.classNames[className] = []; + if ($.inArray(id,this.classNames[className])<0) this.classNames[className].push(id); + this.raiseZ(this.windows[id]); + this.windows[id].focus(); + $(this.windows[id].getCloseButton()).click(this.bind(this.windows[id],function(e){ + e.stopPropagation(); + e.preventDefault(); + if (this.isMinimized()) return; + this.destroy(); + Desk.active_windows_count--; + Desk.windows[this.getId()] = null; + if (Desk.active_windows_count<=0) { + Desk.deactivateOverlay(); + } + })); + $(this.windows[id].getMinimizeButton()).click(this.bind(this.windows[id],function(e){ + e.stopPropagation(); + e.preventDefault(); + if (this.isMinimized()) return; + this.minimize(); + if (this.isMinimized()) { + this.blur(); + } + var all_minimized = true; + for(var id in Desk.windows) { + if (!(Desk.windows[id] instanceof DashWindow)) continue; + if (!Desk.windows[id].isMinimized()) { + all_minimized = false; + break; + } + } + if (all_minimized) Desk.deactivateOverlay(); + })); + $(this.windows[id].getMaximizeButton()).click(this.bind(this.windows[id],function(e){ + e.stopPropagation(); + e.preventDefault(); + if (this.isMinimized()) return; + this.maximize_unmaximize(); + })); + $(this.windows[id].getHeader()).dblclick(this.bind(this.windows[id],function(e){ + e.stopPropagation(); + e.preventDefault(); + if (this.isMinimized()) return; + this.maximize_unmaximize(); + })); + if (this.touchesEnabled) { + this.windows[id].setTouchesEnabled(true); + } + if (navigator.userAgent.match(/android/i)) { + this.windows[id].hideSidebar(); + } + this.windows[id].setMinimizedArray(this.minimized); + this.windows[id].setKeysArr(this.keysArr); + return this.windows[id]; + }, + 'raiseZ': function(window) { + if (window instanceof DashWindow) { + window.setZ(this.z); + this.z++; + } + if (this.dashpanel) { + $(this.dashpanel).css('zIndex', this.z); + } + }, + 'findFocusedWindow': function() { + for(var id in this.windows) { + if (!(this.windows[id] instanceof DashWindow)) continue; + if (this.windows[id].isFocused()) { + return this.windows[id]; + } + } + return null; + }, + 'findWindowById': function(search) { + for(var id in this.windows) { + if (!(this.windows[id] instanceof DashWindow)) continue; + if (this.windows[id].getId()==search) { + return this.windows[id]; + } + } + return null; + }, + 'getWindowIdsByClass': function(search) { + if (typeof(this.classNames[search])!="undefined") return this.classNames[search]; + return null; + }, + 'findMaxZWindow' : function(ignore_id) { + var active = null; + for(var id in this.windows) { + if (typeof(ignore_id)!="undefined" && id==ignore_id) continue; + if (this.windows[id] instanceof DashWindow) { + if (!active || this.windows[id].getZ()>active.getZ()) { + active = this.windows[id]; + } + } + } + return active; + }, + 'getSortedWindowsByZ': function() { + var z = []; + for(var id in this.windows) { + if (!(this.windows[id] instanceof DashWindow)) continue; + z.push(this.windows[id]); + this.sorted_windows_z[this.windows[id].getId()] = this.windows[id].getZ(); + } + if (z.length>0){ + z.sort(function(a, b){ + return a.getZ() - b.getZ(); + }); + z.reverse(); + } + return z; + }, + 'shiftWindowFocus': function(start) { + if (this.sorted_windows.length>0){ + if (start>=this.sorted_windows.length) start = start % this.sorted_windows.length; + return this.sorted_windows[start]; + } + return null; + }, + 'setShiftedWindowFocus': function(shifted_window) { + if (!(shifted_window instanceof DashWindow)) return; + for(var id in this.windows) { + if (!(this.windows[id] instanceof DashWindow)) continue; + if (this.windows[id].getId() == shifted_window.getId()) { + this.windows[id].focus(); + if (this.windows[id].isMinimized()) this.windows[id].unminimize(); + } else { + if (this.windows[id].isFocused()) { + this.windows[id].blur(true); + } else { + this.windows[id].blur(false); + } + if (typeof(this.sorted_windows_z[this.windows[id].getId()])!=="undefined") { + this.windows[id].setZ(this.sorted_windows_z[this.windows[id].getId()]); + } + } + } + this.activateOverlay(); + }, + 'activateOverlay': function() { + if (!this.overlay_is_active) { + this.overlay_is_active = true; + $('body').append('
    '); + } + }, + 'deactivateOverlay': function() { + if (this.overlay_is_active) { + this.overlay_is_active = false; + $('.'+this.dashpanel_overlay_class).remove(); + } + }, + 'focusWindow' : function(wnd) { + for(var id in this.windows) { + if (this.windows[id] instanceof DashWindow) { + if (this.windows[id].isFocused() && wnd != this.windows[id]) { + this.windows[id].blur(true); + } else { + this.windows[id].blur(false); + } + } + } + this.activateOverlay(); + this.raiseZ(wnd); + wnd.focus(); + }, + 'isFrame': function() { + return (window!=window.top); + } +}; \ No newline at end of file diff --git a/assets/js/highlight/LICENSE b/assets/js/highlight/LICENSE new file mode 100644 index 0000000..422deb7 --- /dev/null +++ b/assets/js/highlight/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2006, Ivan Sagalaev +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of highlight.js nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/assets/js/highlight/highlight.pack.js b/assets/js/highlight/highlight.pack.js new file mode 100644 index 0000000..284cfe0 --- /dev/null +++ b/assets/js/highlight/highlight.pack.js @@ -0,0 +1,2 @@ +/*! highlight.js v9.3.0 | BSD3 License | git.io/hljslicense */ +!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/gm,"&").replace(//gm,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){return/^(no-?highlight|plain|text)$/i.test(e)}function i(e){var n,t,r,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=/\blang(?:uage)?-([\w-]+)\b/i.exec(i))return w(t[1])?t[1]:"no-highlight";for(i=i.split(/\s+/),n=0,r=i.length;r>n;n++)if(w(i[n])||a(i[n]))return i[n]}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3==i.nodeType?a+=i.nodeValue.length:1==i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset"}function u(e){f+=""}function c(e){("start"==e.event?o:u)(e.node)}for(var s=0,f="",l=[];e.length||r.length;){var g=i();if(f+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){l.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g==e&&g.length&&g[0].offset==s);l.reverse().forEach(o)}else"start"==g[0].event?l.push(g[0].node):l.pop(),c(g.splice(0,1)[0])}return f+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):Object.keys(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var f=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=f.length?t(f.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){for(var t=0;t";return i+=e+'">',i+n+o}function h(){if(!k.k)return n(M);var e="",t=0;k.lR.lastIndex=0;for(var r=k.lR.exec(M);r;){e+=n(M.substr(t,r.index-t));var a=g(k,r);a?(B+=a[1],e+=p(a[0],n(r[0]))):e+=n(r[0]),t=k.lR.lastIndex,r=k.lR.exec(M)}return e+n(M.substr(t))}function d(){var e="string"==typeof k.sL;if(e&&!R[k.sL])return n(M);var t=e?f(k.sL,M,!0,y[k.sL]):l(M,k.sL.length?k.sL:void 0);return k.r>0&&(B+=t.r),e&&(y[k.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=void 0!==k.sL?d():h(),M=""}function v(e,n){L+=e.cN?p(e.cN,"",!0):"",k=Object.create(e,{parent:{value:k}})}function m(e,n){if(M+=e,void 0===n)return b(),0;var t=o(n,k);if(t)return t.skip?M+=n:(t.eB&&(M+=n),b(),t.rB||t.eB||(M=n)),v(t,n),t.rB?0:n.length;var r=u(k,n);if(r){var a=k;a.skip?M+=n:(a.rE||a.eE||(M+=n),b(),a.eE&&(M=n));do k.cN&&(L+="
    "),k.skip||(B+=k.r),k=k.parent;while(k!=r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,k))throw new Error('Illegal lexeme "'+n+'" for mode "'+(k.cN||"")+'"');return M+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var x,k=i||N,y={},L="";for(x=k;x!=N;x=x.parent)x.cN&&(L=p(x.cN,"",!0)+L);var M="",B=0;try{for(var C,j,I=0;;){if(k.t.lastIndex=I,C=k.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}for(m(t.substr(I)),x=k;x.parent;x=x.parent)x.cN&&(L+="");return{r:B,value:L,language:e,top:k}}catch(O){if(-1!=O.message.indexOf("Illegal"))return{r:0,value:n(t)};throw O}}function l(e,t){t=t||E.languages||Object.keys(R);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function g(e){return E.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,n){return n.replace(/\t/g,E.tabReplace)})),E.useBR&&(e=e.replace(/\n/g,"
    ")),e}function p(e,n,t){var r=n?x[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function h(e){var n=i(e);if(!a(n)){var t;E.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):t=e;var r=t.textContent,o=n?f(n,r,!0):l(r),s=u(t);if(s.length){var h=document.createElementNS("http://www.w3.org/1999/xhtml","div");h.innerHTML=o.value,o.value=c(s,u(h),r)}o.value=g(o.value),e.innerHTML=o.value,e.className=p(e.className,n,o.language),e.result={language:o.language,re:o.r},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.r})}}function d(e){E=o(E,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,h)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=R[n]=t(e);r.aliases&&r.aliases.forEach(function(e){x[e]=n})}function N(){return Object.keys(R)}function w(e){return e=(e||"").toLowerCase(),R[e]||R[x[e]]}var E={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},R={},x={};return e.highlight=f,e.highlightAuto=l,e.fixMarkup=g,e.highlightBlock=h,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[t],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[t],starts:{e:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("sql",function(e){var t=e.C("--","$");return{cI:!0,i:/[<>{}*#]/,c:[{bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke",e:/;/,eW:!0,l:/[\w\.]+/,k:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[t.inherit(t.QSM,{b:'((u8?|U)|L)?"'}),{b:'(u8?|U)?R"',e:'"',c:[t.BE]},{b:"'\\\\?.",e:"'",i:"."}]},i={cN:"number",v:[{b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},{b:t.CNR}],r:0},s={cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef"},c:[{b:/\\\n/,r:0},{bK:"include",e:"$",k:{"meta-keyword":"include"},c:[t.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:"<",e:">",i:"\\n"}]},r,t.CLCM,t.CBCM]},a=t.IR+"\\s*\\(",c={keyword:"int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},n=[e,t.CLCM,t.CBCM,i,r];return{aliases:["c","cc","h","c++","h++","hpp"],k:c,i:"",k:c,c:["self",e]},{b:t.IR+"::",k:c},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:c,c:n.concat([{b:/\(/,e:/\)/,c:n.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+t.IR+"[\\*&\\s]+)+"+a,rB:!0,e:/[{;=]/,eE:!0,k:c,i:/[^\w\s\*&]/,c:[{b:a,rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:c,r:0,c:[t.CLCM,t.CBCM,r,i]},t.CLCM,t.CBCM,s]}])}});hljs.registerLanguage("cs",function(e){var r={keyword:"abstract as base bool break byte case catch char checked const continue decimal dynamic default delegate do double else enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long when object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual volatile void while async protected public private internal ascending descending from get group into join let orderby partial select set value var where yield",literal:"null false true"},t=e.IR+"(<"+e.IR+">)?(\\[\\])?";return{aliases:["csharp"],k:r,i:/::/,c:[e.C("///","$",{rB:!0,c:[{cN:"doctag",v:[{b:"///",r:0},{b:""},{b:""}]}]}),e.CLCM,e.CBCM,{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},e.ASM,e.QSM,e.CNM,{bK:"class interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"namespace",e:/[{;=]/,i:/[^\s:]/,c:[e.inherit(e.TM,{b:"[a-zA-Z](\\.?\\w)*"}),e.CLCM,e.CBCM]},{bK:"new return throw await",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:r,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/=====/,e:/=====$/},{b:/^\-\-\-/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+\+\+/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}});hljs.registerLanguage("objectivec",function(e){var t={cN:"built_in",b:"(AV|CA|CF|CG|CI|MK|MP|NS|UI|XC)\\w+"},i={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},n=/[a-zA-Z@][a-zA-Z0-9_]*/,o="@interface @class @protocol @implementation";return{aliases:["mm","objc","obj-c"],k:i,l:n,i:""}]}]},{cN:"class",b:"("+o.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:o,l:n,c:[e.UTM]},{b:"\\."+e.UIR,r:0}]}});hljs.registerLanguage("python",function(e){var r={cN:"meta",b:/^(>>>|\.\.\.) /},b={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[r],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[r],r:10},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},e.ASM,e.QSM]},a={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},l={cN:"params",b:/\(/,e:/\)/,c:["self",r,a,b]};return{aliases:["py","gyp"],k:{keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},i:/(<\/|->|\?)/,c:[r,a,b,e.HCM,{v:[{cN:"function",bK:"def",r:10},{cN:"class",bK:"class"}],e:/:/,i:/[${=;\n,]/,c:[e.UTM,l,{b:/->/,eW:!0,k:"None"}]},{cN:"meta",b:/^[\t ]*@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/-?[a-z\.]+/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}});hljs.registerLanguage("ini",function(e){var b={cN:"string",c:[e.BE],v:[{b:"'''",e:"'''",r:10},{b:'"""',e:'"""',r:10},{b:'"',e:'"'},{b:"'",e:"'"}]};return{aliases:["toml"],cI:!0,i:/\S/,c:[e.C(";","$"),e.HCM,{cN:"section",b:/^\s*\[+/,e:/\]+/},{b:/^[a-z0-9\[\]_-]+\s*=\s*/,e:"$",rB:!0,c:[{cN:"attr",b:/[a-z0-9\[\]_-]+/},{b:/=/,eW:!0,r:0,c:[{cN:"literal",b:/\bon|off|true|false|yes|no\b/},{cN:"variable",v:[{b:/\$[\w\d"][\w\d_]*/},{b:/\$\{(.*?)}/}]},b,{cN:"number",b:/([\+\-]+)?[\d]+_[\d_]+/},e.NM]}]}]}});hljs.registerLanguage("coffeescript",function(e){var c={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",built_in:"npm require console print module global window document"},n="[A-Za-z$_][0-9A-Za-z$_]*",r={cN:"subst",b:/#\{/,e:/}/,k:c},s=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,r]},{b:/"/,e:/"/,c:[e.BE,r]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[r,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{b:"@"+n},{b:"`",e:"`",eB:!0,eE:!0,sL:"javascript"}];r.c=s;var i=e.inherit(e.TM,{b:n}),t="(\\(.*\\))?\\s*\\B[-=]>",o={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:c,c:["self"].concat(s)}]};return{aliases:["coffee","cson","iced"],k:c,i:/\/\*/,c:s.concat([e.C("###","###"),e.HCM,{cN:"function",b:"^\\s*"+n+"\\s*=\\s*"+t,e:"[-=]>",rB:!0,c:[i,o]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:t,e:"[-=]>",rB:!0,c:[o]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[i]},i]},{b:n+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("apache",function(e){var r={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"section",b:""},{cN:"attribute",b:/\w+/,r:0,k:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"meta",b:"\\s\\[",e:"\\]$"},{cN:"variable",b:"[\\$%]\\{",e:"\\}",c:["self",r]},r,e.QSM]}}],i:/\S/}});hljs.registerLanguage("ruby",function(e){var r="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",b={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},c={cN:"doctag",b:"@[A-Za-z]+"},a={b:"#<",e:">"},s=[e.C("#","$",{c:[c]}),e.C("^\\=begin","^\\=end",{c:[c],r:10}),e.C("^__END__","\\n$")],n={cN:"subst",b:"#\\{",e:"}",k:b},t={cN:"string",c:[e.BE,n],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/}]},i={cN:"params",b:"\\(",e:"\\)",endsParent:!0,k:b},d=[t,a,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<\\s*",c:[{b:"("+e.IR+"::)?"+e.IR}]}].concat(s)},{cN:"function",bK:"def",e:"$|;",c:[e.inherit(e.TM,{b:r}),i].concat(s)},{b:e.IR+"::"},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":(?!\\s)",c:[t,{b:r}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{cN:"params",b:/\|/,e:/\|/,k:b},{b:"("+e.RSR+")\\s*",c:[a,{cN:"regexp",c:[e.BE,n],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}].concat(s),r:0}].concat(s);n.c=d,i.c=d;var l="[>?]>",o="[\\w#]+\\(\\w+\\):\\d+:\\d+>",u="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",w=[{b:/^\s*=>/,starts:{e:"$",c:d}},{cN:"meta",b:"^("+l+"|"+o+"|"+u+")",starts:{e:"$",c:d}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:b,i:/\/\*/,c:s.concat(w).concat(d)}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("perl",function(e){var t="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",r={cN:"subst",b:"[$@]\\{",e:"\\}",k:t},s={b:"->{",e:"}"},n={v:[{b:/\$\d/},{b:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{b:/[\$%@][^\s\w{]/,r:0}]},i=[e.BE,r,n],o=[n,e.HCM,e.C("^\\=\\w","\\=cut",{eW:!0}),s,{cN:"string",c:i,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[e.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[e.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+e.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[e.HCM,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[e.BE],r:0}]},{cN:"function",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",eE:!0,r:5,c:[e.TM]},{b:"-\\w\\b",r:0},{b:"^__DATA__$",e:"^__END__$",sL:"mojolicious",c:[{b:"^@@.*",e:"$",cN:"comment"}]}];return r.c=o,s.c=o,{aliases:["pl","pm"],l:/[\w\.]+/,k:t,c:o}});hljs.registerLanguage("javascript",function(e){return{aliases:["js","jsx"],k:{keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,{cN:"string",b:"`",e:"`",c:[e.BE,{cN:"subst",b:"\\$\\{",e:"\\}"}]},e.CLCM,e.CBCM,{cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:["self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:[e.CLCM,e.CBCM]}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:"^\\[.+\\]:",rB:!0,c:[{cN:"symbol",b:"\\[",e:"\\]:",eB:!0,eE:!0,starts:{cN:"link",e:"$"}}]}]}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s+{",rB:!0,e:"{",c:[{cN:"section",b:e.UIR}],r:0},{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"attribute",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("makefile",function(e){var a={cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]};return{aliases:["mk","mak"],c:[e.HCM,{b:/^\w+\s*\W*=/,rB:!0,r:0,starts:{e:/\s*\W*=/,eE:!0,starts:{e:/$/,r:0,c:[a]}}},{cN:"section",b:/^[\w]+:\s*$/},{cN:"meta",b:/^\.PHONY:/,e:/$/,k:{"meta-keyword":".PHONY"},l:/[\.\w]+/},{b:/^\t+/,e:/$/,r:0,c:[e.QSM,a]}]}});hljs.registerLanguage("java",function(e){var t=e.UIR+"(<"+e.UIR+"(\\s*,\\s*"+e.UIR+")*>)?",a="false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports",r="\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",s={cN:"number",b:r,r:0};return{aliases:["jsp"],k:a,i:/<\/|#/,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw return else",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:a,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:a,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},s,{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("php",function(e){var c={b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},a={cN:"meta",b:/<\?(php)?|\?>/},i={cN:"string",c:[e.BE,a],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},t={v:[e.BNM,e.CNM]};return{aliases:["php3","php4","php5","php6"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.HCM,e.C("//","$",{c:[a]}),e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:/<<<['"]?\w+['"]?$/,e:/^\w+;?$/,c:[e.BE,{cN:"subst",v:[{b:/\$\w+/},{b:/\{\$/,e:/\}/}]}]},a,c,{b:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",c,e.CBCM,i,t]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},i,t]}}); \ No newline at end of file diff --git a/assets/js/highlight/styles/agate.css b/assets/js/highlight/styles/agate.css new file mode 100644 index 0000000..8d64547 --- /dev/null +++ b/assets/js/highlight/styles/agate.css @@ -0,0 +1,108 @@ +/*! + * Agate by Taufik Nurrohman + * ---------------------------------------------------- + * + * #ade5fc + * #a2fca2 + * #c6b4f0 + * #d36363 + * #fcc28c + * #fc9b9b + * #ffa + * #fff + * #333 + * #62c8f3 + * #888 + * + */ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #333; + color: white; +} + +.hljs-name, +.hljs-strong { + font-weight: bold; +} + +.hljs-code, +.hljs-emphasis { + font-style: italic; +} + +.hljs-tag { + color: #62c8f3; +} + +.hljs-variable, +.hljs-template-variable, +.hljs-selector-id, +.hljs-selector-class { + color: #ade5fc; +} + +.hljs-string, +.hljs-bullet { + color: #a2fca2; +} + +.hljs-type, +.hljs-title, +.hljs-section, +.hljs-attribute, +.hljs-quote, +.hljs-built_in, +.hljs-builtin-name { + color: #ffa; +} + +.hljs-number, +.hljs-symbol, +.hljs-bullet { + color: #d36363; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal { + color: #fcc28c; +} + +.hljs-comment, +.hljs-deletion, +.hljs-code { + color: #888; +} + +.hljs-regexp, +.hljs-link { + color: #c6b4f0; +} + +.hljs-meta { + color: #fc9b9b; +} + +.hljs-deletion { + background-color: #fc9b9b; + color: #333; +} + +.hljs-addition { + background-color: #a2fca2; + color: #333; +} + +.hljs a { + color: inherit; +} + +.hljs a:focus, +.hljs a:hover { + color: inherit; + text-decoration: underline; +} diff --git a/assets/js/highlight/styles/androidstudio.css b/assets/js/highlight/styles/androidstudio.css new file mode 100644 index 0000000..bc8e473 --- /dev/null +++ b/assets/js/highlight/styles/androidstudio.css @@ -0,0 +1,66 @@ +/* +Date: 24 Fev 2015 +Author: Pedro Oliveira +*/ + +.hljs { + color: #a9b7c6; + background: #282b2e; + display: block; + overflow-x: auto; + padding: 0.5em; +} + +.hljs-number, +.hljs-literal, +.hljs-symbol, +.hljs-bullet { + color: #6897BB; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-deletion { + color: #cc7832; +} + +.hljs-variable, +.hljs-template-variable, +.hljs-link { + color: #629755; +} + +.hljs-comment, +.hljs-quote { + color: #808080; +} + +.hljs-meta { + color: #bbb529; +} + +.hljs-string, +.hljs-attribute, +.hljs-addition { + color: #6A8759; +} + +.hljs-section, +.hljs-title, +.hljs-type { + color: #ffc66d; +} + +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #e8bf6a; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/arduino-light.css b/assets/js/highlight/styles/arduino-light.css new file mode 100644 index 0000000..4b8b7fd --- /dev/null +++ b/assets/js/highlight/styles/arduino-light.css @@ -0,0 +1,88 @@ +/* + +Arduino® Light Theme - Stefania Mellai + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #FFFFFF; +} + +.hljs, +.hljs-subst { + color: #434f54; +} + +.hljs-keyword, +.hljs-attribute, +.hljs-selector-tag, +.hljs-doctag, +.hljs-name { + color: #00979D; +} + +.hljs-built_in, +.hljs-literal, +.hljs-bullet, +.hljs-code, +.hljs-addition { + color: #D35400; +} + +.hljs-regexp, +.hljs-symbol, +.hljs-variable, +.hljs-template-variable, +.hljs-link, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #00979D; +} + +.hljs-type, +.hljs-string, +.hljs-selector-id, +.hljs-selector-class, +.hljs-quote, +.hljs-template-tag, +.hljs-deletion { + color: #005C5F; +} + +.hljs-title, +.hljs-section { + color: #880000; + font-weight: bold; +} + +.hljs-comment { + color: rgba(149,165,166,.8); +} + +.hljs-meta-keyword { + color: #728E00; +} + +.hljs-meta { + color: #728E00; + color: #434f54; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-function { + color: #728E00; +} + +.hljs-number { + color: #8A7B52; +} diff --git a/assets/js/highlight/styles/arta.css b/assets/js/highlight/styles/arta.css new file mode 100644 index 0000000..75ef3a9 --- /dev/null +++ b/assets/js/highlight/styles/arta.css @@ -0,0 +1,73 @@ +/* +Date: 17.V.2011 +Author: pumbur +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #222; +} + +.hljs, +.hljs-subst { + color: #aaa; +} + +.hljs-section { + color: #fff; +} + +.hljs-comment, +.hljs-quote, +.hljs-meta { + color: #444; +} + +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-regexp { + color: #ffcc33; +} + +.hljs-number, +.hljs-addition { + color: #00cc66; +} + +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-template-variable, +.hljs-attribute, +.hljs-link { + color: #32aaee; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #6644aa; +} + +.hljs-title, +.hljs-variable, +.hljs-deletion, +.hljs-template-tag { + color: #bb1166; +} + +.hljs-section, +.hljs-doctag, +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/ascetic.css b/assets/js/highlight/styles/ascetic.css new file mode 100644 index 0000000..48397e8 --- /dev/null +++ b/assets/js/highlight/styles/ascetic.css @@ -0,0 +1,45 @@ +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: white; + color: black; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-symbol, +.hljs-bullet, +.hljs-section, +.hljs-addition, +.hljs-attribute, +.hljs-link { + color: #888; +} + +.hljs-comment, +.hljs-quote, +.hljs-meta, +.hljs-deletion { + color: #ccc; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-section, +.hljs-name, +.hljs-type, +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/atelier-cave-dark.css b/assets/js/highlight/styles/atelier-cave-dark.css new file mode 100644 index 0000000..65428f3 --- /dev/null +++ b/assets/js/highlight/styles/atelier-cave-dark.css @@ -0,0 +1,83 @@ +/* Base16 Atelier Cave Dark - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Cave Comment */ +.hljs-comment, +.hljs-quote { + color: #7e7887; +} + +/* Atelier-Cave Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-regexp, +.hljs-link, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #be4678; +} + +/* Atelier-Cave Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #aa573c; +} + +/* Atelier-Cave Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #2a9292; +} + +/* Atelier-Cave Blue */ +.hljs-title, +.hljs-section { + color: #576ddb; +} + +/* Atelier-Cave Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #955ae7; +} + +.hljs-deletion, +.hljs-addition { + color: #19171c; + display: inline-block; + width: 100%; +} + +.hljs-deletion { + background-color: #be4678; +} + +.hljs-addition { + background-color: #2a9292; +} + +.hljs { + display: block; + overflow-x: auto; + background: #19171c; + color: #8b8792; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-cave-light.css b/assets/js/highlight/styles/atelier-cave-light.css new file mode 100644 index 0000000..b419f9f --- /dev/null +++ b/assets/js/highlight/styles/atelier-cave-light.css @@ -0,0 +1,85 @@ +/* Base16 Atelier Cave Light - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Cave Comment */ +.hljs-comment, +.hljs-quote { + color: #655f6d; +} + +/* Atelier-Cave Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #be4678; +} + +/* Atelier-Cave Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #aa573c; +} + +/* Atelier-Cave Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #2a9292; +} + +/* Atelier-Cave Blue */ +.hljs-title, +.hljs-section { + color: #576ddb; +} + +/* Atelier-Cave Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #955ae7; +} + +.hljs-deletion, +.hljs-addition { + color: #19171c; + display: inline-block; + width: 100%; +} + +.hljs-deletion { + background-color: #be4678; +} + +.hljs-addition { + background-color: #2a9292; +} + +.hljs { + display: block; + overflow-x: auto; + background: #efecf4; + color: #585260; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-dune-dark.css b/assets/js/highlight/styles/atelier-dune-dark.css new file mode 100644 index 0000000..1684f52 --- /dev/null +++ b/assets/js/highlight/styles/atelier-dune-dark.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Dune Dark - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Dune Comment */ +.hljs-comment, +.hljs-quote { + color: #999580; +} + +/* Atelier-Dune Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #d73737; +} + +/* Atelier-Dune Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #b65611; +} + +/* Atelier-Dune Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #60ac39; +} + +/* Atelier-Dune Blue */ +.hljs-title, +.hljs-section { + color: #6684e1; +} + +/* Atelier-Dune Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #b854d4; +} + +.hljs { + display: block; + overflow-x: auto; + background: #20201d; + color: #a6a28c; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-dune-light.css b/assets/js/highlight/styles/atelier-dune-light.css new file mode 100644 index 0000000..547719d --- /dev/null +++ b/assets/js/highlight/styles/atelier-dune-light.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Dune Light - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Dune Comment */ +.hljs-comment, +.hljs-quote { + color: #7d7a68; +} + +/* Atelier-Dune Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #d73737; +} + +/* Atelier-Dune Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #b65611; +} + +/* Atelier-Dune Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #60ac39; +} + +/* Atelier-Dune Blue */ +.hljs-title, +.hljs-section { + color: #6684e1; +} + +/* Atelier-Dune Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #b854d4; +} + +.hljs { + display: block; + overflow-x: auto; + background: #fefbec; + color: #6e6b5e; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-estuary-dark.css b/assets/js/highlight/styles/atelier-estuary-dark.css new file mode 100644 index 0000000..a5e5071 --- /dev/null +++ b/assets/js/highlight/styles/atelier-estuary-dark.css @@ -0,0 +1,84 @@ +/* Base16 Atelier Estuary Dark - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/estuary) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Estuary Comment */ +.hljs-comment, +.hljs-quote { + color: #878573; +} + +/* Atelier-Estuary Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #ba6236; +} + +/* Atelier-Estuary Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #ae7313; +} + +/* Atelier-Estuary Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #7d9726; +} + +/* Atelier-Estuary Blue */ +.hljs-title, +.hljs-section { + color: #36a166; +} + +/* Atelier-Estuary Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #5f9182; +} + +.hljs-deletion, +.hljs-addition { + color: #22221b; + display: inline-block; + width: 100%; +} + +.hljs-deletion { + background-color: #ba6236; +} + +.hljs-addition { + background-color: #7d9726; +} + +.hljs { + display: block; + overflow-x: auto; + background: #22221b; + color: #929181; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-estuary-light.css b/assets/js/highlight/styles/atelier-estuary-light.css new file mode 100644 index 0000000..1daee5d --- /dev/null +++ b/assets/js/highlight/styles/atelier-estuary-light.css @@ -0,0 +1,84 @@ +/* Base16 Atelier Estuary Light - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/estuary) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Estuary Comment */ +.hljs-comment, +.hljs-quote { + color: #6c6b5a; +} + +/* Atelier-Estuary Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #ba6236; +} + +/* Atelier-Estuary Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #ae7313; +} + +/* Atelier-Estuary Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #7d9726; +} + +/* Atelier-Estuary Blue */ +.hljs-title, +.hljs-section { + color: #36a166; +} + +/* Atelier-Estuary Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #5f9182; +} + +.hljs-deletion, +.hljs-addition { + color: #22221b; + display: inline-block; + width: 100%; +} + +.hljs-deletion { + background-color: #ba6236; +} + +.hljs-addition { + background-color: #7d9726; +} + +.hljs { + display: block; + overflow-x: auto; + background: #f4f3ec; + color: #5f5e4e; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-forest-dark.css b/assets/js/highlight/styles/atelier-forest-dark.css new file mode 100644 index 0000000..0ef4fae --- /dev/null +++ b/assets/js/highlight/styles/atelier-forest-dark.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Forest Dark - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/forest) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Forest Comment */ +.hljs-comment, +.hljs-quote { + color: #9c9491; +} + +/* Atelier-Forest Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #f22c40; +} + +/* Atelier-Forest Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #df5320; +} + +/* Atelier-Forest Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #7b9726; +} + +/* Atelier-Forest Blue */ +.hljs-title, +.hljs-section { + color: #407ee7; +} + +/* Atelier-Forest Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #6666ea; +} + +.hljs { + display: block; + overflow-x: auto; + background: #1b1918; + color: #a8a19f; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-forest-light.css b/assets/js/highlight/styles/atelier-forest-light.css new file mode 100644 index 0000000..bbedde1 --- /dev/null +++ b/assets/js/highlight/styles/atelier-forest-light.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Forest Light - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/forest) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Forest Comment */ +.hljs-comment, +.hljs-quote { + color: #766e6b; +} + +/* Atelier-Forest Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #f22c40; +} + +/* Atelier-Forest Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #df5320; +} + +/* Atelier-Forest Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #7b9726; +} + +/* Atelier-Forest Blue */ +.hljs-title, +.hljs-section { + color: #407ee7; +} + +/* Atelier-Forest Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #6666ea; +} + +.hljs { + display: block; + overflow-x: auto; + background: #f1efee; + color: #68615e; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-heath-dark.css b/assets/js/highlight/styles/atelier-heath-dark.css new file mode 100644 index 0000000..fe01ff7 --- /dev/null +++ b/assets/js/highlight/styles/atelier-heath-dark.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Heath Dark - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/heath) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Heath Comment */ +.hljs-comment, +.hljs-quote { + color: #9e8f9e; +} + +/* Atelier-Heath Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #ca402b; +} + +/* Atelier-Heath Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #a65926; +} + +/* Atelier-Heath Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #918b3b; +} + +/* Atelier-Heath Blue */ +.hljs-title, +.hljs-section { + color: #516aec; +} + +/* Atelier-Heath Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #7b59c0; +} + +.hljs { + display: block; + overflow-x: auto; + background: #1b181b; + color: #ab9bab; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-heath-light.css b/assets/js/highlight/styles/atelier-heath-light.css new file mode 100644 index 0000000..ee43786 --- /dev/null +++ b/assets/js/highlight/styles/atelier-heath-light.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Heath Light - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/heath) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Heath Comment */ +.hljs-comment, +.hljs-quote { + color: #776977; +} + +/* Atelier-Heath Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #ca402b; +} + +/* Atelier-Heath Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #a65926; +} + +/* Atelier-Heath Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #918b3b; +} + +/* Atelier-Heath Blue */ +.hljs-title, +.hljs-section { + color: #516aec; +} + +/* Atelier-Heath Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #7b59c0; +} + +.hljs { + display: block; + overflow-x: auto; + background: #f7f3f7; + color: #695d69; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-lakeside-dark.css b/assets/js/highlight/styles/atelier-lakeside-dark.css new file mode 100644 index 0000000..a937d3b --- /dev/null +++ b/assets/js/highlight/styles/atelier-lakeside-dark.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Lakeside Dark - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/lakeside) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Lakeside Comment */ +.hljs-comment, +.hljs-quote { + color: #7195a8; +} + +/* Atelier-Lakeside Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #d22d72; +} + +/* Atelier-Lakeside Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #935c25; +} + +/* Atelier-Lakeside Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #568c3b; +} + +/* Atelier-Lakeside Blue */ +.hljs-title, +.hljs-section { + color: #257fad; +} + +/* Atelier-Lakeside Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #6b6bb8; +} + +.hljs { + display: block; + overflow-x: auto; + background: #161b1d; + color: #7ea2b4; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-lakeside-light.css b/assets/js/highlight/styles/atelier-lakeside-light.css new file mode 100644 index 0000000..6c7e8f9 --- /dev/null +++ b/assets/js/highlight/styles/atelier-lakeside-light.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Lakeside Light - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/lakeside) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Lakeside Comment */ +.hljs-comment, +.hljs-quote { + color: #5a7b8c; +} + +/* Atelier-Lakeside Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #d22d72; +} + +/* Atelier-Lakeside Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #935c25; +} + +/* Atelier-Lakeside Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #568c3b; +} + +/* Atelier-Lakeside Blue */ +.hljs-title, +.hljs-section { + color: #257fad; +} + +/* Atelier-Lakeside Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #6b6bb8; +} + +.hljs { + display: block; + overflow-x: auto; + background: #ebf8ff; + color: #516d7b; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-plateau-dark.css b/assets/js/highlight/styles/atelier-plateau-dark.css new file mode 100644 index 0000000..3bb0526 --- /dev/null +++ b/assets/js/highlight/styles/atelier-plateau-dark.css @@ -0,0 +1,84 @@ +/* Base16 Atelier Plateau Dark - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/plateau) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Plateau Comment */ +.hljs-comment, +.hljs-quote { + color: #7e7777; +} + +/* Atelier-Plateau Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #ca4949; +} + +/* Atelier-Plateau Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #b45a3c; +} + +/* Atelier-Plateau Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #4b8b8b; +} + +/* Atelier-Plateau Blue */ +.hljs-title, +.hljs-section { + color: #7272ca; +} + +/* Atelier-Plateau Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #8464c4; +} + +.hljs-deletion, +.hljs-addition { + color: #1b1818; + display: inline-block; + width: 100%; +} + +.hljs-deletion { + background-color: #ca4949; +} + +.hljs-addition { + background-color: #4b8b8b; +} + +.hljs { + display: block; + overflow-x: auto; + background: #1b1818; + color: #8a8585; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-plateau-light.css b/assets/js/highlight/styles/atelier-plateau-light.css new file mode 100644 index 0000000..5f0222b --- /dev/null +++ b/assets/js/highlight/styles/atelier-plateau-light.css @@ -0,0 +1,84 @@ +/* Base16 Atelier Plateau Light - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/plateau) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Plateau Comment */ +.hljs-comment, +.hljs-quote { + color: #655d5d; +} + +/* Atelier-Plateau Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #ca4949; +} + +/* Atelier-Plateau Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #b45a3c; +} + +/* Atelier-Plateau Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #4b8b8b; +} + +/* Atelier-Plateau Blue */ +.hljs-title, +.hljs-section { + color: #7272ca; +} + +/* Atelier-Plateau Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #8464c4; +} + +.hljs-deletion, +.hljs-addition { + color: #1b1818; + display: inline-block; + width: 100%; +} + +.hljs-deletion { + background-color: #ca4949; +} + +.hljs-addition { + background-color: #4b8b8b; +} + +.hljs { + display: block; + overflow-x: auto; + background: #f4ecec; + color: #585050; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-savanna-dark.css b/assets/js/highlight/styles/atelier-savanna-dark.css new file mode 100644 index 0000000..38f8314 --- /dev/null +++ b/assets/js/highlight/styles/atelier-savanna-dark.css @@ -0,0 +1,84 @@ +/* Base16 Atelier Savanna Dark - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/savanna) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Savanna Comment */ +.hljs-comment, +.hljs-quote { + color: #78877d; +} + +/* Atelier-Savanna Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #b16139; +} + +/* Atelier-Savanna Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #9f713c; +} + +/* Atelier-Savanna Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #489963; +} + +/* Atelier-Savanna Blue */ +.hljs-title, +.hljs-section { + color: #478c90; +} + +/* Atelier-Savanna Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #55859b; +} + +.hljs-deletion, +.hljs-addition { + color: #171c19; + display: inline-block; + width: 100%; +} + +.hljs-deletion { + background-color: #b16139; +} + +.hljs-addition { + background-color: #489963; +} + +.hljs { + display: block; + overflow-x: auto; + background: #171c19; + color: #87928a; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-savanna-light.css b/assets/js/highlight/styles/atelier-savanna-light.css new file mode 100644 index 0000000..1ccd7c6 --- /dev/null +++ b/assets/js/highlight/styles/atelier-savanna-light.css @@ -0,0 +1,84 @@ +/* Base16 Atelier Savanna Light - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/savanna) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Savanna Comment */ +.hljs-comment, +.hljs-quote { + color: #5f6d64; +} + +/* Atelier-Savanna Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #b16139; +} + +/* Atelier-Savanna Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #9f713c; +} + +/* Atelier-Savanna Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #489963; +} + +/* Atelier-Savanna Blue */ +.hljs-title, +.hljs-section { + color: #478c90; +} + +/* Atelier-Savanna Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #55859b; +} + +.hljs-deletion, +.hljs-addition { + color: #171c19; + display: inline-block; + width: 100%; +} + +.hljs-deletion { + background-color: #b16139; +} + +.hljs-addition { + background-color: #489963; +} + +.hljs { + display: block; + overflow-x: auto; + background: #ecf4ee; + color: #526057; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-seaside-dark.css b/assets/js/highlight/styles/atelier-seaside-dark.css new file mode 100644 index 0000000..df29949 --- /dev/null +++ b/assets/js/highlight/styles/atelier-seaside-dark.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Seaside Dark - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/seaside) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Seaside Comment */ +.hljs-comment, +.hljs-quote { + color: #809980; +} + +/* Atelier-Seaside Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #e6193c; +} + +/* Atelier-Seaside Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #87711d; +} + +/* Atelier-Seaside Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #29a329; +} + +/* Atelier-Seaside Blue */ +.hljs-title, +.hljs-section { + color: #3d62f5; +} + +/* Atelier-Seaside Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #ad2bee; +} + +.hljs { + display: block; + overflow-x: auto; + background: #131513; + color: #8ca68c; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-seaside-light.css b/assets/js/highlight/styles/atelier-seaside-light.css new file mode 100644 index 0000000..9d960f2 --- /dev/null +++ b/assets/js/highlight/styles/atelier-seaside-light.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Seaside Light - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/seaside) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Seaside Comment */ +.hljs-comment, +.hljs-quote { + color: #687d68; +} + +/* Atelier-Seaside Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #e6193c; +} + +/* Atelier-Seaside Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #87711d; +} + +/* Atelier-Seaside Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #29a329; +} + +/* Atelier-Seaside Blue */ +.hljs-title, +.hljs-section { + color: #3d62f5; +} + +/* Atelier-Seaside Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #ad2bee; +} + +.hljs { + display: block; + overflow-x: auto; + background: #f4fbf4; + color: #5e6e5e; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-sulphurpool-dark.css b/assets/js/highlight/styles/atelier-sulphurpool-dark.css new file mode 100644 index 0000000..c2ab793 --- /dev/null +++ b/assets/js/highlight/styles/atelier-sulphurpool-dark.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Sulphurpool Dark - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Sulphurpool Comment */ +.hljs-comment, +.hljs-quote { + color: #898ea4; +} + +/* Atelier-Sulphurpool Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #c94922; +} + +/* Atelier-Sulphurpool Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #c76b29; +} + +/* Atelier-Sulphurpool Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #ac9739; +} + +/* Atelier-Sulphurpool Blue */ +.hljs-title, +.hljs-section { + color: #3d8fd1; +} + +/* Atelier-Sulphurpool Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #6679cc; +} + +.hljs { + display: block; + overflow-x: auto; + background: #202746; + color: #979db4; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/atelier-sulphurpool-light.css b/assets/js/highlight/styles/atelier-sulphurpool-light.css new file mode 100644 index 0000000..96c47d0 --- /dev/null +++ b/assets/js/highlight/styles/atelier-sulphurpool-light.css @@ -0,0 +1,69 @@ +/* Base16 Atelier Sulphurpool Light - Theme */ +/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool) */ +/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ + +/* Atelier-Sulphurpool Comment */ +.hljs-comment, +.hljs-quote { + color: #6b7394; +} + +/* Atelier-Sulphurpool Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #c94922; +} + +/* Atelier-Sulphurpool Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #c76b29; +} + +/* Atelier-Sulphurpool Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #ac9739; +} + +/* Atelier-Sulphurpool Blue */ +.hljs-title, +.hljs-section { + color: #3d8fd1; +} + +/* Atelier-Sulphurpool Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #6679cc; +} + +.hljs { + display: block; + overflow-x: auto; + background: #f5f7ff; + color: #5e6687; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/brown-paper.css b/assets/js/highlight/styles/brown-paper.css new file mode 100644 index 0000000..f0197b9 --- /dev/null +++ b/assets/js/highlight/styles/brown-paper.css @@ -0,0 +1,64 @@ +/* + +Brown Paper style from goldblog.com.ua (c) Zaripov Yura + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background:#b7a68e url(./brown-papersq.png); +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal { + color:#005599; + font-weight:bold; +} + +.hljs, +.hljs-subst { + color: #363c69; +} + +.hljs-string, +.hljs-title, +.hljs-section, +.hljs-type, +.hljs-attribute, +.hljs-symbol, +.hljs-bullet, +.hljs-built_in, +.hljs-addition, +.hljs-variable, +.hljs-template-tag, +.hljs-template-variable, +.hljs-link, +.hljs-name { + color: #2c009f; +} + +.hljs-comment, +.hljs-quote, +.hljs-meta, +.hljs-deletion { + color: #802022; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-doctag, +.hljs-title, +.hljs-section, +.hljs-type, +.hljs-name, +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/brown-papersq.png b/assets/js/highlight/styles/brown-papersq.png new file mode 100644 index 0000000..3813903 Binary files /dev/null and b/assets/js/highlight/styles/brown-papersq.png differ diff --git a/assets/js/highlight/styles/codepen-embed.css b/assets/js/highlight/styles/codepen-embed.css new file mode 100644 index 0000000..195c4a0 --- /dev/null +++ b/assets/js/highlight/styles/codepen-embed.css @@ -0,0 +1,60 @@ +/* + codepen.io Embed Theme + Author: Justin Perry + Original theme - https://github.com/chriskempson/tomorrow-theme +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #222; + color: #fff; +} + +.hljs-comment, +.hljs-quote { + color: #777; +} + +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-regexp, +.hljs-meta, +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-params, +.hljs-symbol, +.hljs-bullet, +.hljs-link, +.hljs-deletion { + color: #ab875d; +} + +.hljs-section, +.hljs-title, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-type, +.hljs-attribute { + color: #9b869b; +} + +.hljs-string, +.hljs-keyword, +.hljs-selector-tag, +.hljs-addition { + color: #8f9c6c; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/color-brewer.css b/assets/js/highlight/styles/color-brewer.css new file mode 100644 index 0000000..7934d98 --- /dev/null +++ b/assets/js/highlight/styles/color-brewer.css @@ -0,0 +1,71 @@ +/* + +Colorbrewer theme +Original: https://github.com/mbostock/colorbrewer-theme (c) Mike Bostock +Ported by Fabrício Tavares de Oliveira + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #fff; +} + +.hljs, +.hljs-subst { + color: #000; +} + +.hljs-string, +.hljs-meta, +.hljs-symbol, +.hljs-template-tag, +.hljs-template-variable, +.hljs-addition { + color: #756bb1; +} + +.hljs-comment, +.hljs-quote { + color: #636363; +} + +.hljs-number, +.hljs-regexp, +.hljs-literal, +.hljs-bullet, +.hljs-link { + color: #31a354; +} + +.hljs-deletion, +.hljs-variable { + color: #88f; +} + + + +.hljs-keyword, +.hljs-selector-tag, +.hljs-title, +.hljs-section, +.hljs-built_in, +.hljs-doctag, +.hljs-type, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-strong { + color: #3182bd; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-attribute { + color: #e6550d; +} diff --git a/assets/js/highlight/styles/dark.css b/assets/js/highlight/styles/dark.css new file mode 100644 index 0000000..b4724f5 --- /dev/null +++ b/assets/js/highlight/styles/dark.css @@ -0,0 +1,63 @@ +/* + +Dark style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #444; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-section, +.hljs-link { + color: white; +} + +.hljs, +.hljs-subst { + color: #ddd; +} + +.hljs-string, +.hljs-title, +.hljs-name, +.hljs-type, +.hljs-attribute, +.hljs-symbol, +.hljs-bullet, +.hljs-built_in, +.hljs-addition, +.hljs-variable, +.hljs-template-tag, +.hljs-template-variable { + color: #d88; +} + +.hljs-comment, +.hljs-quote, +.hljs-deletion, +.hljs-meta { + color: #777; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-title, +.hljs-section, +.hljs-doctag, +.hljs-type, +.hljs-name, +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/darkula.css b/assets/js/highlight/styles/darkula.css new file mode 100644 index 0000000..c01f9a7 --- /dev/null +++ b/assets/js/highlight/styles/darkula.css @@ -0,0 +1,74 @@ +/* + +Darkula color scheme from the JetBrains family of IDEs + +*/ + + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #2b2b2b; +} + +.hljs { + color: #bababa; +} + +.hljs-strong, +.hljs-emphasis { + color: #a8a8a2; +} + +.hljs-bullet, +.hljs-quote, +.hljs-link, +.hljs-number, +.hljs-regexp, +.hljs-literal { + color: #6896ba; +} + +.hljs-code, +.hljs-selector-class { + color: #a6e22e; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-section, +.hljs-attribute, +.hljs-name, +.hljs-variable { + color: #cb7832; +} + +.hljs-params { + color: #b9b9b9; +} + +.hljs-string, +.hljs-subst, +.hljs-type, +.hljs-built_in, +.hljs-builtin-name, +.hljs-symbol, +.hljs-selector-id, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-template-tag, +.hljs-template-variable, +.hljs-addition { + color: #e0c46c; +} + +.hljs-comment, +.hljs-deletion, +.hljs-meta { + color: #7f7f7f; +} diff --git a/assets/js/highlight/styles/default.css b/assets/js/highlight/styles/default.css new file mode 100644 index 0000000..f1bfade --- /dev/null +++ b/assets/js/highlight/styles/default.css @@ -0,0 +1,99 @@ +/* + +Original highlight.js style (c) Ivan Sagalaev + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #F0F0F0; +} + + +/* Base color: saturation 0; */ + +.hljs, +.hljs-subst { + color: #444; +} + +.hljs-comment { + color: #888888; +} + +.hljs-keyword, +.hljs-attribute, +.hljs-selector-tag, +.hljs-meta-keyword, +.hljs-doctag, +.hljs-name { + font-weight: bold; +} + + +/* User color: hue: 0 */ + +.hljs-type, +.hljs-string, +.hljs-number, +.hljs-selector-id, +.hljs-selector-class, +.hljs-quote, +.hljs-template-tag, +.hljs-deletion { + color: #880000; +} + +.hljs-title, +.hljs-section { + color: #880000; + font-weight: bold; +} + +.hljs-regexp, +.hljs-symbol, +.hljs-variable, +.hljs-template-variable, +.hljs-link, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #BC6060; +} + + +/* Language color: hue: 90; */ + +.hljs-literal { + color: #78A960; +} + +.hljs-built_in, +.hljs-bullet, +.hljs-code, +.hljs-addition { + color: #397300; +} + + +/* Meta color: hue: 200 */ + +.hljs-meta { + color: #1f7199; +} + +.hljs-meta-string { + color: #4d99bf; +} + + +/* Misc effects */ + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/docco.css b/assets/js/highlight/styles/docco.css new file mode 100644 index 0000000..db366be --- /dev/null +++ b/assets/js/highlight/styles/docco.css @@ -0,0 +1,97 @@ +/* +Docco style used in http://jashkenas.github.com/docco/ converted by Simon Madine (@thingsinjars) +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #000; + background: #f8f8ff; +} + +.hljs-comment, +.hljs-quote { + color: #408080; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-subst { + color: #954121; +} + +.hljs-number { + color: #40a070; +} + +.hljs-string, +.hljs-doctag { + color: #219161; +} + +.hljs-selector-id, +.hljs-selector-class, +.hljs-section, +.hljs-type { + color: #19469d; +} + +.hljs-params { + color: #00f; +} + +.hljs-title { + color: #458; + font-weight: bold; +} + +.hljs-tag, +.hljs-name, +.hljs-attribute { + color: #000080; + font-weight: normal; +} + +.hljs-variable, +.hljs-template-variable { + color: #008080; +} + +.hljs-regexp, +.hljs-link { + color: #b68; +} + +.hljs-symbol, +.hljs-bullet { + color: #990073; +} + +.hljs-built_in, +.hljs-builtin-name { + color: #0086b3; +} + +.hljs-meta { + color: #999; + font-weight: bold; +} + +.hljs-deletion { + background: #fdd; +} + +.hljs-addition { + background: #dfd; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/dracula.css b/assets/js/highlight/styles/dracula.css new file mode 100644 index 0000000..d591db6 --- /dev/null +++ b/assets/js/highlight/styles/dracula.css @@ -0,0 +1,76 @@ +/* + +Dracula Theme v1.2.0 + +https://github.com/zenorocha/dracula-theme + +Copyright 2015, All rights reserved + +Code licensed under the MIT license +http://zenorocha.mit-license.org + +@author Éverton Ribeiro +@author Zeno Rocha + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #282a36; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-section, +.hljs-link { + color: #8be9fd; +} + +.hljs-function .hljs-keyword { + color: #ff79c6; +} + +.hljs, +.hljs-subst { + color: #f8f8f2; +} + +.hljs-string, +.hljs-title, +.hljs-name, +.hljs-type, +.hljs-attribute, +.hljs-symbol, +.hljs-bullet, +.hljs-addition, +.hljs-variable, +.hljs-template-tag, +.hljs-template-variable { + color: #f1fa8c; +} + +.hljs-comment, +.hljs-quote, +.hljs-deletion, +.hljs-meta { + color: #6272a4; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-title, +.hljs-section, +.hljs-doctag, +.hljs-type, +.hljs-name, +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/far.css b/assets/js/highlight/styles/far.css new file mode 100644 index 0000000..2b3f87b --- /dev/null +++ b/assets/js/highlight/styles/far.css @@ -0,0 +1,71 @@ +/* + +FAR Style (c) MajestiC + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #000080; +} + +.hljs, +.hljs-subst { + color: #0ff; +} + +.hljs-string, +.hljs-attribute, +.hljs-symbol, +.hljs-bullet, +.hljs-built_in, +.hljs-builtin-name, +.hljs-template-tag, +.hljs-template-variable, +.hljs-addition { + color: #ff0; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-section, +.hljs-type, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-variable { + color: #fff; +} + +.hljs-comment, +.hljs-quote, +.hljs-doctag, +.hljs-deletion { + color: #888; +} + +.hljs-number, +.hljs-regexp, +.hljs-literal, +.hljs-link { + color: #0f0; +} + +.hljs-meta { + color: #008080; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-title, +.hljs-section, +.hljs-name, +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/foundation.css b/assets/js/highlight/styles/foundation.css new file mode 100644 index 0000000..f1fe64b --- /dev/null +++ b/assets/js/highlight/styles/foundation.css @@ -0,0 +1,88 @@ +/* +Description: Foundation 4 docs style for highlight.js +Author: Dan Allen +Website: http://foundation.zurb.com/docs/ +Version: 1.0 +Date: 2013-04-02 +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #eee; color: black; +} + +.hljs-link, +.hljs-emphasis, +.hljs-attribute, +.hljs-addition { + color: #070; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong, +.hljs-string, +.hljs-deletion { + color: #d14; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-quote, +.hljs-comment { + color: #998; + font-style: italic; +} + +.hljs-section, +.hljs-title { + color: #900; +} + +.hljs-class .hljs-title, +.hljs-type { + color: #458; +} + +.hljs-variable, +.hljs-template-variable { + color: #336699; +} + +.hljs-bullet { + color: #997700; +} + +.hljs-meta { + color: #3344bb; +} + +.hljs-code, +.hljs-number, +.hljs-literal, +.hljs-keyword, +.hljs-selector-tag { + color: #099; +} + +.hljs-regexp { + background-color: #fff0ff; + color: #880088; +} + +.hljs-symbol { + color: #990073; +} + +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #007700; +} diff --git a/assets/js/highlight/styles/github-gist.css b/assets/js/highlight/styles/github-gist.css new file mode 100644 index 0000000..155f0b9 --- /dev/null +++ b/assets/js/highlight/styles/github-gist.css @@ -0,0 +1,71 @@ +/** + * GitHub Gist Theme + * Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro + */ + +.hljs { + display: block; + background: white; + padding: 0.5em; + color: #333333; + overflow-x: auto; +} + +.hljs-comment, +.hljs-meta { + color: #969896; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-strong, +.hljs-emphasis, +.hljs-quote { + color: #df5000; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-type { + color: #a71d5d; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute { + color: #0086b3; +} + +.hljs-section, +.hljs-name { + color: #63a35c; +} + +.hljs-tag { + color: #333333; +} + +.hljs-title, +.hljs-attr, +.hljs-selector-id, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #795da3; +} + +.hljs-addition { + color: #55a532; + background-color: #eaffea; +} + +.hljs-deletion { + color: #bd2c00; + background-color: #ffecec; +} + +.hljs-link { + text-decoration: underline; +} diff --git a/assets/js/highlight/styles/github.css b/assets/js/highlight/styles/github.css new file mode 100644 index 0000000..791932b --- /dev/null +++ b/assets/js/highlight/styles/github.css @@ -0,0 +1,99 @@ +/* + +github.com style (c) Vasily Polovnyov + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #333; + background: #f8f8f8; +} + +.hljs-comment, +.hljs-quote { + color: #998; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-subst { + color: #333; + font-weight: bold; +} + +.hljs-number, +.hljs-literal, +.hljs-variable, +.hljs-template-variable, +.hljs-tag .hljs-attr { + color: #008080; +} + +.hljs-string, +.hljs-doctag { + color: #d14; +} + +.hljs-title, +.hljs-section, +.hljs-selector-id { + color: #900; + font-weight: bold; +} + +.hljs-subst { + font-weight: normal; +} + +.hljs-type, +.hljs-class .hljs-title { + color: #458; + font-weight: bold; +} + +.hljs-tag, +.hljs-name, +.hljs-attribute { + color: #000080; + font-weight: normal; +} + +.hljs-regexp, +.hljs-link { + color: #009926; +} + +.hljs-symbol, +.hljs-bullet { + color: #990073; +} + +.hljs-built_in, +.hljs-builtin-name { + color: #0086b3; +} + +.hljs-meta { + color: #999; + font-weight: bold; +} + +.hljs-deletion { + background: #fdd; +} + +.hljs-addition { + background: #dfd; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/googlecode.css b/assets/js/highlight/styles/googlecode.css new file mode 100644 index 0000000..884ad63 --- /dev/null +++ b/assets/js/highlight/styles/googlecode.css @@ -0,0 +1,89 @@ +/* + +Google Code style (c) Aahan Krish + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: white; + color: black; +} + +.hljs-comment, +.hljs-quote { + color: #800; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-section, +.hljs-title, +.hljs-name { + color: #008; +} + +.hljs-variable, +.hljs-template-variable { + color: #660; +} + +.hljs-string, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-regexp { + color: #080; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.hljs-meta, +.hljs-number, +.hljs-link { + color: #066; +} + +.hljs-title, +.hljs-doctag, +.hljs-type, +.hljs-attr, +.hljs-built_in, +.hljs-builtin-name, +.hljs-params { + color: #606; +} + +.hljs-attribute, +.hljs-subst { + color: #000; +} + +.hljs-formula { + background-color: #eee; + font-style: italic; +} + +.hljs-selector-id, +.hljs-selector-class { + color: #9B703F +} + +.hljs-addition { + background-color: #baeeba; +} + +.hljs-deletion { + background-color: #ffc8bd; +} + +.hljs-doctag, +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/grayscale.css b/assets/js/highlight/styles/grayscale.css new file mode 100644 index 0000000..5376f34 --- /dev/null +++ b/assets/js/highlight/styles/grayscale.css @@ -0,0 +1,101 @@ +/* + +grayscale style (c) MY Sun + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #333; + background: #fff; +} + +.hljs-comment, +.hljs-quote { + color: #777; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-subst { + color: #333; + font-weight: bold; +} + +.hljs-number, +.hljs-literal { + color: #777; +} + +.hljs-string, +.hljs-doctag, +.hljs-formula { + color: #333; + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAJ0lEQVQIW2O8e/fufwYGBgZBQUEQxcCIIfDu3Tuwivfv30NUoAsAALHpFMMLqZlPAAAAAElFTkSuQmCC) repeat; +} + +.hljs-title, +.hljs-section, +.hljs-selector-id { + color: #000; + font-weight: bold; +} + +.hljs-subst { + font-weight: normal; +} + +.hljs-class .hljs-title, +.hljs-type, +.hljs-name { + color: #333; + font-weight: bold; +} + +.hljs-tag { + color: #333; +} + +.hljs-regexp { + color: #333; + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAYAAADA+m62AAAAPUlEQVQYV2NkQAN37979r6yszIgujiIAU4RNMVwhuiQ6H6wQl3XI4oy4FMHcCJPHcDS6J2A2EqUQpJhohQDexSef15DBCwAAAABJRU5ErkJggg==) repeat; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link { + color: #000; + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAKElEQVQIW2NkQAO7d+/+z4gsBhJwdXVlhAvCBECKwIIwAbhKZBUwBQA6hBpm5efZsgAAAABJRU5ErkJggg==) repeat; +} + +.hljs-built_in, +.hljs-builtin-name { + color: #000; + text-decoration: underline; +} + +.hljs-meta { + color: #999; + font-weight: bold; +} + +.hljs-deletion { + color: #fff; + background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAADCAYAAABS3WWCAAAAE0lEQVQIW2MMDQ39zzhz5kwIAQAyxweWgUHd1AAAAABJRU5ErkJggg==) repeat; +} + +.hljs-addition { + color: #000; + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAALUlEQVQYV2N89+7dfwYk8P79ewZBQUFkIQZGOiu6e/cuiptQHAPl0NtNxAQBAM97Oejj3Dg7AAAAAElFTkSuQmCC) repeat; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/gruvbox-dark.css b/assets/js/highlight/styles/gruvbox-dark.css new file mode 100644 index 0000000..f563811 --- /dev/null +++ b/assets/js/highlight/styles/gruvbox-dark.css @@ -0,0 +1,108 @@ +/* + +Gruvbox style (dark) (c) Pavel Pertsev (original style at https://github.com/morhetz/gruvbox) + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #282828; +} + +.hljs, +.hljs-subst { + color: #ebdbb2; +} + +/* Gruvbox Red */ +.hljs-deletion, +.hljs-formula, +.hljs-keyword, +.hljs-link, +.hljs-selector-tag { + color: #fb4934; +} + +/* Gruvbox Blue */ +.hljs-built_in, +.hljs-emphasis, +.hljs-name, +.hljs-quote, +.hljs-strong, +.hljs-title, +.hljs-variable { + color: #83a598; +} + +/* Gruvbox Yellow */ +.hljs-attr, +.hljs-params, +.hljs-template-tag, +.hljs-type { + color: #fabd2f; +} + +/* Gruvbox Purple */ +.hljs-builtin-name, +.hljs-doctag, +.hljs-literal, +.hljs-number { + color: #8f3f71; +} + +/* Gruvbox Orange */ +.hljs-code, +.hljs-meta, +.hljs-regexp, +.hljs-selector-id, +.hljs-template-variable { + color: #fe8019; +} + +/* Gruvbox Green */ +.hljs-addition, +.hljs-meta-string, +.hljs-section, +.hljs-selector-attr, +.hljs-selector-class, +.hljs-string, +.hljs-symbol { + color: #b8bb26; +} + +/* Gruvbox Aqua */ +.hljs-attribute, +.hljs-bullet, +.hljs-class, +.hljs-function, +.hljs-function .hljs-keyword, +.hljs-meta-keyword, +.hljs-selector-pseudo, +.hljs-tag { + color: #8ec07c; +} + +/* Gruvbox Gray */ +.hljs-comment { + color: #928374; +} + +/* Gruvbox Purple */ +.hljs-link_label, +.hljs-literal, +.hljs-number { + color: #d3869b; +} + +.hljs-comment, +.hljs-emphasis { + font-style: italic; +} + +.hljs-section, +.hljs-strong, +.hljs-tag { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/gruvbox-light.css b/assets/js/highlight/styles/gruvbox-light.css new file mode 100644 index 0000000..ff45468 --- /dev/null +++ b/assets/js/highlight/styles/gruvbox-light.css @@ -0,0 +1,108 @@ +/* + +Gruvbox style (light) (c) Pavel Pertsev (original style at https://github.com/morhetz/gruvbox) + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #fbf1c7; +} + +.hljs, +.hljs-subst { + color: #3c3836; +} + +/* Gruvbox Red */ +.hljs-deletion, +.hljs-formula, +.hljs-keyword, +.hljs-link, +.hljs-selector-tag { + color: #9d0006; +} + +/* Gruvbox Blue */ +.hljs-built_in, +.hljs-emphasis, +.hljs-name, +.hljs-quote, +.hljs-strong, +.hljs-title, +.hljs-variable { + color: #076678; +} + +/* Gruvbox Yellow */ +.hljs-attr, +.hljs-params, +.hljs-template-tag, +.hljs-type { + color: #b57614; +} + +/* Gruvbox Purple */ +.hljs-builtin-name, +.hljs-doctag, +.hljs-literal, +.hljs-number { + color: #8f3f71; +} + +/* Gruvbox Orange */ +.hljs-code, +.hljs-meta, +.hljs-regexp, +.hljs-selector-id, +.hljs-template-variable { + color: #af3a03; +} + +/* Gruvbox Green */ +.hljs-addition, +.hljs-meta-string, +.hljs-section, +.hljs-selector-attr, +.hljs-selector-class, +.hljs-string, +.hljs-symbol { + color: #79740e; +} + +/* Gruvbox Aqua */ +.hljs-attribute, +.hljs-bullet, +.hljs-class, +.hljs-function, +.hljs-function .hljs-keyword, +.hljs-meta-keyword, +.hljs-selector-pseudo, +.hljs-tag { + color: #427b58; +} + +/* Gruvbox Gray */ +.hljs-comment { + color: #928374; +} + +/* Gruvbox Purple */ +.hljs-link_label, +.hljs-literal, +.hljs-number { + color: #8f3f71; +} + +.hljs-comment, +.hljs-emphasis { + font-style: italic; +} + +.hljs-section, +.hljs-strong, +.hljs-tag { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/hopscotch.css b/assets/js/highlight/styles/hopscotch.css new file mode 100644 index 0000000..32e60d2 --- /dev/null +++ b/assets/js/highlight/styles/hopscotch.css @@ -0,0 +1,83 @@ +/* + * Hopscotch + * by Jan T. Sott + * https://github.com/idleberg/Hopscotch + * + * This work is licensed under the Creative Commons CC0 1.0 Universal License + */ + +/* Comment */ +.hljs-comment, +.hljs-quote { + color: #989498; +} + +/* Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-link, +.hljs-deletion { + color: #dd464c; +} + +/* Orange */ +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #fd8b19; +} + +/* Yellow */ +.hljs-class .hljs-title { + color: #fdcc59; +} + +/* Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #8fc13e; +} + +/* Aqua */ +.hljs-meta { + color: #149b93; +} + +/* Blue */ +.hljs-function, +.hljs-section, +.hljs-title { + color: #1290bf; +} + +/* Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #c85e7c; +} + +.hljs { + display: block; + background: #322931; + color: #b9b5b8; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/hybrid.css b/assets/js/highlight/styles/hybrid.css new file mode 100644 index 0000000..29735a1 --- /dev/null +++ b/assets/js/highlight/styles/hybrid.css @@ -0,0 +1,102 @@ +/* + +vim-hybrid theme by w0ng (https://github.com/w0ng/vim-hybrid) + +*/ + +/*background color*/ +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #1d1f21; +} + +/*selection color*/ +.hljs::selection, +.hljs span::selection { + background: #373b41; +} + +.hljs::-moz-selection, +.hljs span::-moz-selection { + background: #373b41; +} + +/*foreground color*/ +.hljs { + color: #c5c8c6; +} + +/*color: fg_yellow*/ +.hljs-title, +.hljs-name { + color: #f0c674; +} + +/*color: fg_comment*/ +.hljs-comment, +.hljs-meta, +.hljs-meta .hljs-keyword { + color: #707880; +} + +/*color: fg_red*/ +.hljs-number, +.hljs-symbol, +.hljs-literal, +.hljs-deletion, +.hljs-link { + color: #cc6666 +} + +/*color: fg_green*/ +.hljs-string, +.hljs-doctag, +.hljs-addition, +.hljs-regexp, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #b5bd68; +} + +/*color: fg_purple*/ +.hljs-attribute, +.hljs-code, +.hljs-selector-id { + color: #b294bb; +} + +/*color: fg_blue*/ +.hljs-keyword, +.hljs-selector-tag, +.hljs-bullet, +.hljs-tag { + color: #81a2be; +} + +/*color: fg_aqua*/ +.hljs-subst, +.hljs-variable, +.hljs-template-tag, +.hljs-template-variable { + color: #8abeb7; +} + +/*color: fg_orange*/ +.hljs-type, +.hljs-built_in, +.hljs-builtin-name, +.hljs-quote, +.hljs-section, +.hljs-selector-class { + color: #de935f; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/idea.css b/assets/js/highlight/styles/idea.css new file mode 100644 index 0000000..3bf1892 --- /dev/null +++ b/assets/js/highlight/styles/idea.css @@ -0,0 +1,97 @@ +/* + +Intellij Idea-like styling (c) Vasily Polovnyov + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #000; + background: #fff; +} + +.hljs-subst, +.hljs-title { + font-weight: normal; + color: #000; +} + +.hljs-comment, +.hljs-quote { + color: #808080; + font-style: italic; +} + +.hljs-meta { + color: #808000; +} + +.hljs-tag { + background: #efefef; +} + +.hljs-section, +.hljs-name, +.hljs-literal, +.hljs-keyword, +.hljs-selector-tag, +.hljs-type, +.hljs-selector-id, +.hljs-selector-class { + font-weight: bold; + color: #000080; +} + +.hljs-attribute, +.hljs-number, +.hljs-regexp, +.hljs-link { + font-weight: bold; + color: #0000ff; +} + +.hljs-number, +.hljs-regexp, +.hljs-link { + font-weight: normal; +} + +.hljs-string { + color: #008000; + font-weight: bold; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-formula { + color: #000; + background: #d0eded; + font-style: italic; +} + +.hljs-doctag { + text-decoration: underline; +} + +.hljs-variable, +.hljs-template-variable { + color: #660e7a; +} + +.hljs-addition { + background: #baeeba; +} + +.hljs-deletion { + background: #ffc8bd; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/ir-black.css b/assets/js/highlight/styles/ir-black.css new file mode 100644 index 0000000..bd4c755 --- /dev/null +++ b/assets/js/highlight/styles/ir-black.css @@ -0,0 +1,73 @@ +/* + IR_Black style (c) Vasily Mikhailitchenko +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #000; + color: #f8f8f8; +} + +.hljs-comment, +.hljs-quote, +.hljs-meta { + color: #7c7c7c; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-tag, +.hljs-name { + color: #96cbfe; +} + +.hljs-attribute, +.hljs-selector-id { + color: #ffffb6; +} + +.hljs-string, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-addition { + color: #a8ff60; +} + +.hljs-subst { + color: #daefa3; +} + +.hljs-regexp, +.hljs-link { + color: #e9c062; +} + +.hljs-title, +.hljs-section, +.hljs-type, +.hljs-doctag { + color: #ffffb6; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-variable, +.hljs-template-variable, +.hljs-literal { + color: #c6c5fe; +} + +.hljs-number, +.hljs-deletion { + color:#ff73fd; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/kimbie.dark.css b/assets/js/highlight/styles/kimbie.dark.css new file mode 100644 index 0000000..d139cb5 --- /dev/null +++ b/assets/js/highlight/styles/kimbie.dark.css @@ -0,0 +1,74 @@ +/* + Name: Kimbie (dark) + Author: Jan T. Sott + License: Creative Commons Attribution-ShareAlike 4.0 Unported License + URL: https://github.com/idleberg/Kimbie-highlight.js +*/ + +/* Kimbie Comment */ +.hljs-comment, +.hljs-quote { + color: #d6baad; +} + +/* Kimbie Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-meta { + color: #dc3958; +} + +/* Kimbie Orange */ +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params, +.hljs-deletion, +.hljs-link { + color: #f79a32; +} + +/* Kimbie Yellow */ +.hljs-title, +.hljs-section, +.hljs-attribute { + color: #f06431; +} + +/* Kimbie Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #889b4a; +} + +/* Kimbie Purple */ +.hljs-keyword, +.hljs-selector-tag, +.hljs-function { + color: #98676a; +} + +.hljs { + display: block; + overflow-x: auto; + background: #221a0f; + color: #d3af86; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/kimbie.light.css b/assets/js/highlight/styles/kimbie.light.css new file mode 100644 index 0000000..04ff6ed --- /dev/null +++ b/assets/js/highlight/styles/kimbie.light.css @@ -0,0 +1,74 @@ +/* + Name: Kimbie (light) + Author: Jan T. Sott + License: Creative Commons Attribution-ShareAlike 4.0 Unported License + URL: https://github.com/idleberg/Kimbie-highlight.js +*/ + +/* Kimbie Comment */ +.hljs-comment, +.hljs-quote { + color: #a57a4c; +} + +/* Kimbie Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-meta { + color: #dc3958; +} + +/* Kimbie Orange */ +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params, +.hljs-deletion, +.hljs-link { + color: #f79a32; +} + +/* Kimbie Yellow */ +.hljs-title, +.hljs-section, +.hljs-attribute { + color: #f06431; +} + +/* Kimbie Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #889b4a; +} + +/* Kimbie Purple */ +.hljs-keyword, +.hljs-selector-tag, +.hljs-function { + color: #98676a; +} + +.hljs { + display: block; + overflow-x: auto; + background: #fbebd4; + color: #84613d; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/magula.css b/assets/js/highlight/styles/magula.css new file mode 100644 index 0000000..44dee5e --- /dev/null +++ b/assets/js/highlight/styles/magula.css @@ -0,0 +1,70 @@ +/* +Description: Magula style for highligh.js +Author: Ruslan Keba +Website: http://rukeba.com/ +Version: 1.0 +Date: 2009-01-03 +Music: Aphex Twin / Xtal +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background-color: #f4f4f4; +} + +.hljs, +.hljs-subst { + color: black; +} + +.hljs-string, +.hljs-title, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute, +.hljs-addition, +.hljs-variable, +.hljs-template-tag, +.hljs-template-variable { + color: #050; +} + +.hljs-comment, +.hljs-quote { + color: #777; +} + +.hljs-number, +.hljs-regexp, +.hljs-literal, +.hljs-type, +.hljs-link { + color: #800; +} + +.hljs-deletion, +.hljs-meta { + color: #00e; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-doctag, +.hljs-title, +.hljs-section, +.hljs-built_in, +.hljs-tag, +.hljs-name { + font-weight: bold; + color: navy; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/mono-blue.css b/assets/js/highlight/styles/mono-blue.css new file mode 100644 index 0000000..884c97c --- /dev/null +++ b/assets/js/highlight/styles/mono-blue.css @@ -0,0 +1,59 @@ +/* + Five-color theme from a single blue hue. +*/ +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #eaeef3; +} + +.hljs { + color: #00193a; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-title, +.hljs-section, +.hljs-doctag, +.hljs-name, +.hljs-strong { + font-weight: bold; +} + +.hljs-comment { + color: #738191; +} + +.hljs-string, +.hljs-title, +.hljs-section, +.hljs-built_in, +.hljs-literal, +.hljs-type, +.hljs-addition, +.hljs-tag, +.hljs-quote, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #0048ab; +} + +.hljs-meta, +.hljs-subst, +.hljs-symbol, +.hljs-regexp, +.hljs-attribute, +.hljs-deletion, +.hljs-variable, +.hljs-template-variable, +.hljs-link, +.hljs-bullet { + color: #4c81c9; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/monokai-sublime.css b/assets/js/highlight/styles/monokai-sublime.css new file mode 100644 index 0000000..2864170 --- /dev/null +++ b/assets/js/highlight/styles/monokai-sublime.css @@ -0,0 +1,83 @@ +/* + +Monokai Sublime style. Derived from Monokai by noformnocontent http://nn.mit-license.org/ + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #23241f; +} + +.hljs, +.hljs-tag, +.hljs-subst { + color: #f8f8f2; +} + +.hljs-strong, +.hljs-emphasis { + color: #a8a8a2; +} + +.hljs-bullet, +.hljs-quote, +.hljs-number, +.hljs-regexp, +.hljs-literal, +.hljs-link { + color: #ae81ff; +} + +.hljs-code, +.hljs-title, +.hljs-section, +.hljs-selector-class { + color: #a6e22e; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-name, +.hljs-attr { + color: #f92672; +} + +.hljs-symbol, +.hljs-attribute { + color: #66d9ef; +} + +.hljs-params, +.hljs-class .hljs-title { + color: #f8f8f2; +} + +.hljs-string, +.hljs-type, +.hljs-built_in, +.hljs-builtin-name, +.hljs-selector-id, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-addition, +.hljs-variable, +.hljs-template-variable { + color: #e6db74; +} + +.hljs-comment, +.hljs-deletion, +.hljs-meta { + color: #75715e; +} diff --git a/assets/js/highlight/styles/monokai.css b/assets/js/highlight/styles/monokai.css new file mode 100644 index 0000000..775d53f --- /dev/null +++ b/assets/js/highlight/styles/monokai.css @@ -0,0 +1,70 @@ +/* +Monokai style - ported by Luigi Maselli - http://grigio.org +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #272822; color: #ddd; +} + +.hljs-tag, +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-strong, +.hljs-name { + color: #f92672; +} + +.hljs-code { + color: #66d9ef; +} + +.hljs-class .hljs-title { + color: white; +} + +.hljs-attribute, +.hljs-symbol, +.hljs-regexp, +.hljs-link { + color: #bf79db; +} + +.hljs-string, +.hljs-bullet, +.hljs-subst, +.hljs-title, +.hljs-section, +.hljs-emphasis, +.hljs-type, +.hljs-built_in, +.hljs-builtin-name, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-addition, +.hljs-variable, +.hljs-template-tag, +.hljs-template-variable { + color: #a6e22e; +} + +.hljs-comment, +.hljs-quote, +.hljs-deletion, +.hljs-meta { + color: #75715e; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-doctag, +.hljs-title, +.hljs-section, +.hljs-type, +.hljs-selector-id { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/obsidian.css b/assets/js/highlight/styles/obsidian.css new file mode 100644 index 0000000..356630f --- /dev/null +++ b/assets/js/highlight/styles/obsidian.css @@ -0,0 +1,88 @@ +/** + * Obsidian style + * ported by Alexander Marenin (http://github.com/ioncreature) + */ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #282b2e; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-selector-id { + color: #93c763; +} + +.hljs-number { + color: #ffcd22; +} + +.hljs { + color: #e0e2e4; +} + +.hljs-attribute { + color: #668bb0; +} + +.hljs-code, +.hljs-class .hljs-title, +.hljs-section { + color: white; +} + +.hljs-regexp, +.hljs-link { + color: #d39745; +} + +.hljs-meta { + color: #557182; +} + +.hljs-tag, +.hljs-name, +.hljs-bullet, +.hljs-subst, +.hljs-emphasis, +.hljs-type, +.hljs-built_in, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-addition, +.hljs-variable, +.hljs-template-tag, +.hljs-template-variable { + color: #8cbbad; +} + +.hljs-string, +.hljs-symbol { + color: #ec7600; +} + +.hljs-comment, +.hljs-quote, +.hljs-deletion { + color: #818e96; +} + +.hljs-selector-class { + color: #A082BD +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-doctag, +.hljs-title, +.hljs-section, +.hljs-type, +.hljs-name, +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/paraiso-dark.css b/assets/js/highlight/styles/paraiso-dark.css new file mode 100644 index 0000000..e729240 --- /dev/null +++ b/assets/js/highlight/styles/paraiso-dark.css @@ -0,0 +1,72 @@ +/* + Paraíso (dark) + Created by Jan T. Sott (http://github.com/idleberg) + Inspired by the art of Rubens LP (http://www.rubenslp.com.br) +*/ + +/* Paraíso Comment */ +.hljs-comment, +.hljs-quote { + color: #8d8687; +} + +/* Paraíso Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-link, +.hljs-meta { + color: #ef6155; +} + +/* Paraíso Orange */ +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params, +.hljs-deletion { + color: #f99b15; +} + +/* Paraíso Yellow */ +.hljs-title, +.hljs-section, +.hljs-attribute { + color: #fec418; +} + +/* Paraíso Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #48b685; +} + +/* Paraíso Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #815ba4; +} + +.hljs { + display: block; + overflow-x: auto; + background: #2f1e2e; + color: #a39e9b; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/paraiso-light.css b/assets/js/highlight/styles/paraiso-light.css new file mode 100644 index 0000000..944857c --- /dev/null +++ b/assets/js/highlight/styles/paraiso-light.css @@ -0,0 +1,72 @@ +/* + Paraíso (light) + Created by Jan T. Sott (http://github.com/idleberg) + Inspired by the art of Rubens LP (http://www.rubenslp.com.br) +*/ + +/* Paraíso Comment */ +.hljs-comment, +.hljs-quote { + color: #776e71; +} + +/* Paraíso Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-link, +.hljs-meta { + color: #ef6155; +} + +/* Paraíso Orange */ +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params, +.hljs-deletion { + color: #f99b15; +} + +/* Paraíso Yellow */ +.hljs-title, +.hljs-section, +.hljs-attribute { + color: #fec418; +} + +/* Paraíso Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #48b685; +} + +/* Paraíso Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #815ba4; +} + +.hljs { + display: block; + overflow-x: auto; + background: #e7e9db; + color: #4f424c; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/pojoaque.css b/assets/js/highlight/styles/pojoaque.css new file mode 100644 index 0000000..2e07847 --- /dev/null +++ b/assets/js/highlight/styles/pojoaque.css @@ -0,0 +1,83 @@ +/* + +Pojoaque Style by Jason Tate +http://web-cms-designs.com/ftopict-10-pojoaque-style-for-highlight-js-code-highlighter.html +Based on Solarized Style from http://ethanschoonover.com/solarized + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #dccf8f; + background: url(./pojoaque.jpg) repeat scroll left top #181914; +} + +.hljs-comment, +.hljs-quote { + color: #586e75; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-addition { + color: #b64926; +} + +.hljs-number, +.hljs-string, +.hljs-doctag, +.hljs-regexp { + color: #468966; +} + +.hljs-title, +.hljs-section, +.hljs-built_in, +.hljs-name { + color: #ffb03b; +} + +.hljs-variable, +.hljs-template-variable, +.hljs-class .hljs-title, +.hljs-type, +.hljs-tag { + color: #b58900; +} + +.hljs-attribute { + color: #b89859; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link, +.hljs-subst, +.hljs-meta { + color: #cb4b16; +} + +.hljs-deletion { + color: #dc322f; +} + +.hljs-selector-id, +.hljs-selector-class { + color: #d3a60c; +} + +.hljs-formula { + background: #073642; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/pojoaque.jpg b/assets/js/highlight/styles/pojoaque.jpg new file mode 100644 index 0000000..9c07d4a Binary files /dev/null and b/assets/js/highlight/styles/pojoaque.jpg differ diff --git a/assets/js/highlight/styles/qtcreator_dark.css b/assets/js/highlight/styles/qtcreator_dark.css new file mode 100644 index 0000000..7aa56a3 --- /dev/null +++ b/assets/js/highlight/styles/qtcreator_dark.css @@ -0,0 +1,83 @@ +/* + +Qt Creator dark color scheme + +*/ + + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #000000; +} + +.hljs, +.hljs-subst, +.hljs-tag, +.hljs-title { + color: #aaaaaa; +} + +.hljs-strong, +.hljs-emphasis { + color: #a8a8a2; +} + +.hljs-bullet, +.hljs-quote, +.hljs-number, +.hljs-regexp, +.hljs-literal { + color: #ff55ff; +} + +.hljs-code +.hljs-selector-class { + color: #aaaaff; +} + +.hljs-emphasis, +.hljs-stronge, +.hljs-type { + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-function, +.hljs-section, +.hljs-symbol, +.hljs-name { + color: #ffff55; +} + +.hljs-attribute { + color: #ff5555; +} + +.hljs-variable, +.hljs-params, +.hljs-class .hljs-title { + color: #8888ff; +} + +.hljs-string, +.hljs-selector-id, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-type, +.hljs-built_in, +.hljs-builtin-name, +.hljs-template-tag, +.hljs-template-variable, +.hljs-addition, +.hljs-link { + color: #ff55ff; +} + +.hljs-comment, +.hljs-meta, +.hljs-deletion { + color: #55ffff; +} diff --git a/assets/js/highlight/styles/qtcreator_light.css b/assets/js/highlight/styles/qtcreator_light.css new file mode 100644 index 0000000..1efa2c6 --- /dev/null +++ b/assets/js/highlight/styles/qtcreator_light.css @@ -0,0 +1,83 @@ +/* + +Qt Creator light color scheme + +*/ + + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #ffffff; +} + +.hljs, +.hljs-subst, +.hljs-tag, +.hljs-title { + color: #000000; +} + +.hljs-strong, +.hljs-emphasis { + color: #000000; +} + +.hljs-bullet, +.hljs-quote, +.hljs-number, +.hljs-regexp, +.hljs-literal { + color: #000080; +} + +.hljs-code +.hljs-selector-class { + color: #800080; +} + +.hljs-emphasis, +.hljs-stronge, +.hljs-type { + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-function, +.hljs-section, +.hljs-symbol, +.hljs-name { + color: #808000; +} + +.hljs-attribute { + color: #800000; +} + +.hljs-variable, +.hljs-params, +.hljs-class .hljs-title { + color: #0055AF; +} + +.hljs-string, +.hljs-selector-id, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-type, +.hljs-built_in, +.hljs-builtin-name, +.hljs-template-tag, +.hljs-template-variable, +.hljs-addition, +.hljs-link { + color: #008000; +} + +.hljs-comment, +.hljs-meta, +.hljs-deletion { + color: #008000; +} diff --git a/assets/js/highlight/styles/railscasts.css b/assets/js/highlight/styles/railscasts.css new file mode 100644 index 0000000..008cdc5 --- /dev/null +++ b/assets/js/highlight/styles/railscasts.css @@ -0,0 +1,106 @@ +/* + +Railscasts-like style (c) Visoft, Inc. (Damien White) + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #232323; + color: #e6e1dc; +} + +.hljs-comment, +.hljs-quote { + color: #bc9458; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag { + color: #c26230; +} + +.hljs-string, +.hljs-number, +.hljs-regexp, +.hljs-variable, +.hljs-template-variable { + color: #a5c261; +} + +.hljs-subst { + color: #519f50; +} + +.hljs-tag, +.hljs-name { + color: #e8bf6a; +} + +.hljs-type { + color: #da4939; +} + + +.hljs-symbol, +.hljs-bullet, +.hljs-built_in, +.hljs-builtin-name, +.hljs-attr, +.hljs-link { + color: #6d9cbe; +} + +.hljs-params { + color: #d0d0ff; +} + +.hljs-attribute { + color: #cda869; +} + +.hljs-meta { + color: #9b859d; +} + +.hljs-title, +.hljs-section { + color: #ffc66d; +} + +.hljs-addition { + background-color: #144212; + color: #e6e1dc; + display: inline-block; + width: 100%; +} + +.hljs-deletion { + background-color: #600; + color: #e6e1dc; + display: inline-block; + width: 100%; +} + +.hljs-selector-class { + color: #9b703f; +} + +.hljs-selector-id { + color: #8b98ab; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-link { + text-decoration: underline; +} diff --git a/assets/js/highlight/styles/rainbow.css b/assets/js/highlight/styles/rainbow.css new file mode 100644 index 0000000..905eb8e --- /dev/null +++ b/assets/js/highlight/styles/rainbow.css @@ -0,0 +1,85 @@ +/* + +Style with support for rainbow parens + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #474949; + color: #d1d9e1; +} + + +.hljs-comment, +.hljs-quote { + color: #969896; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-type, +.hljs-addition { + color: #cc99cc; +} + +.hljs-number, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #f99157; +} + +.hljs-string, +.hljs-doctag, +.hljs-regexp { + color: #8abeb7; +} + +.hljs-title, +.hljs-name, +.hljs-section, +.hljs-built_in { + color: #b5bd68; +} + +.hljs-variable, +.hljs-template-variable, +.hljs-selector-id, +.hljs-class .hljs-title { + color: #ffcc66; +} + +.hljs-section, +.hljs-name, +.hljs-strong { + font-weight: bold; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-subst, +.hljs-meta, +.hljs-link { + color: #f99157; +} + +.hljs-deletion { + color: #dc322f; +} + +.hljs-formula { + background: #eee8d5; +} + +.hljs-attr, +.hljs-attribute { + color: #81a2be; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/school-book.css b/assets/js/highlight/styles/school-book.css new file mode 100644 index 0000000..964b51d --- /dev/null +++ b/assets/js/highlight/styles/school-book.css @@ -0,0 +1,72 @@ +/* + +School Book style from goldblog.com.ua (c) Zaripov Yura + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 15px 0.5em 0.5em 30px; + font-size: 11px; + line-height:16px; +} + +pre{ + background:#f6f6ae url(./school-book.png); + border-top: solid 2px #d2e8b9; + border-bottom: solid 1px #d2e8b9; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal { + color:#005599; + font-weight:bold; +} + +.hljs, +.hljs-subst { + color: #3e5915; +} + +.hljs-string, +.hljs-title, +.hljs-section, +.hljs-type, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute, +.hljs-built_in, +.hljs-builtin-name, +.hljs-addition, +.hljs-variable, +.hljs-template-tag, +.hljs-template-variable, +.hljs-link { + color: #2c009f; +} + +.hljs-comment, +.hljs-quote, +.hljs-deletion, +.hljs-meta { + color: #e60415; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal, +.hljs-doctag, +.hljs-title, +.hljs-section, +.hljs-type, +.hljs-name, +.hljs-selector-id, +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/school-book.png b/assets/js/highlight/styles/school-book.png new file mode 100644 index 0000000..956e979 Binary files /dev/null and b/assets/js/highlight/styles/school-book.png differ diff --git a/assets/js/highlight/styles/solarized-dark.css b/assets/js/highlight/styles/solarized-dark.css new file mode 100644 index 0000000..b4c0da1 --- /dev/null +++ b/assets/js/highlight/styles/solarized-dark.css @@ -0,0 +1,84 @@ +/* + +Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #002b36; + color: #839496; +} + +.hljs-comment, +.hljs-quote { + color: #586e75; +} + +/* Solarized Green */ +.hljs-keyword, +.hljs-selector-tag, +.hljs-addition { + color: #859900; +} + +/* Solarized Cyan */ +.hljs-number, +.hljs-string, +.hljs-meta .hljs-meta-string, +.hljs-literal, +.hljs-doctag, +.hljs-regexp { + color: #2aa198; +} + +/* Solarized Blue */ +.hljs-title, +.hljs-section, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #268bd2; +} + +/* Solarized Yellow */ +.hljs-attribute, +.hljs-attr, +.hljs-variable, +.hljs-template-variable, +.hljs-class .hljs-title, +.hljs-type { + color: #b58900; +} + +/* Solarized Orange */ +.hljs-symbol, +.hljs-bullet, +.hljs-subst, +.hljs-meta, +.hljs-meta .hljs-keyword, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-link { + color: #cb4b16; +} + +/* Solarized Red */ +.hljs-built_in, +.hljs-deletion { + color: #dc322f; +} + +.hljs-formula { + background: #073642; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/solarized-light.css b/assets/js/highlight/styles/solarized-light.css new file mode 100644 index 0000000..fdcfcc7 --- /dev/null +++ b/assets/js/highlight/styles/solarized-light.css @@ -0,0 +1,84 @@ +/* + +Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #fdf6e3; + color: #657b83; +} + +.hljs-comment, +.hljs-quote { + color: #93a1a1; +} + +/* Solarized Green */ +.hljs-keyword, +.hljs-selector-tag, +.hljs-addition { + color: #859900; +} + +/* Solarized Cyan */ +.hljs-number, +.hljs-string, +.hljs-meta .hljs-meta-string, +.hljs-literal, +.hljs-doctag, +.hljs-regexp { + color: #2aa198; +} + +/* Solarized Blue */ +.hljs-title, +.hljs-section, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #268bd2; +} + +/* Solarized Yellow */ +.hljs-attribute, +.hljs-attr, +.hljs-variable, +.hljs-template-variable, +.hljs-class .hljs-title, +.hljs-type { + color: #b58900; +} + +/* Solarized Orange */ +.hljs-symbol, +.hljs-bullet, +.hljs-subst, +.hljs-meta, +.hljs-meta .hljs-keyword, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-link { + color: #cb4b16; +} + +/* Solarized Red */ +.hljs-built_in, +.hljs-deletion { + color: #dc322f; +} + +.hljs-formula { + background: #eee8d5; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/sunburst.css b/assets/js/highlight/styles/sunburst.css new file mode 100644 index 0000000..f56dd5e --- /dev/null +++ b/assets/js/highlight/styles/sunburst.css @@ -0,0 +1,102 @@ +/* + +Sunburst-like style (c) Vasily Polovnyov + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #000; + color: #f8f8f8; +} + +.hljs-comment, +.hljs-quote { + color: #aeaeae; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-type { + color: #e28964; +} + +.hljs-string { + color: #65b042; +} + +.hljs-subst { + color: #daefa3; +} + +.hljs-regexp, +.hljs-link { + color: #e9c062; +} + +.hljs-title, +.hljs-section, +.hljs-tag, +.hljs-name { + color: #89bdff; +} + +.hljs-class .hljs-title, +.hljs-doctag { + text-decoration: underline; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-number { + color: #3387cc; +} + +.hljs-params, +.hljs-variable, +.hljs-template-variable { + color: #3e87e3; +} + +.hljs-attribute { + color: #cda869; +} + +.hljs-meta { + color: #8996a8; +} + +.hljs-formula { + background-color: #0e2231; + color: #f8f8f8; + font-style: italic; +} + +.hljs-addition { + background-color: #253b22; + color: #f8f8f8; +} + +.hljs-deletion { + background-color: #420e09; + color: #f8f8f8; +} + +.hljs-selector-class { + color: #9b703f; +} + +.hljs-selector-id { + color: #8b98ab; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/tomorrow-night-blue.css b/assets/js/highlight/styles/tomorrow-night-blue.css new file mode 100644 index 0000000..78e59cc --- /dev/null +++ b/assets/js/highlight/styles/tomorrow-night-blue.css @@ -0,0 +1,75 @@ +/* Tomorrow Night Blue Theme */ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ + +/* Tomorrow Comment */ +.hljs-comment, +.hljs-quote { + color: #7285b7; +} + +/* Tomorrow Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-deletion { + color: #ff9da4; +} + +/* Tomorrow Orange */ +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params, +.hljs-meta, +.hljs-link { + color: #ffc58f; +} + +/* Tomorrow Yellow */ +.hljs-attribute { + color: #ffeead; +} + +/* Tomorrow Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #d1f1a9; +} + +/* Tomorrow Blue */ +.hljs-title, +.hljs-section { + color: #bbdaff; +} + +/* Tomorrow Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #ebbbff; +} + +.hljs { + display: block; + overflow-x: auto; + background: #002451; + color: white; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/tomorrow-night-bright.css b/assets/js/highlight/styles/tomorrow-night-bright.css new file mode 100644 index 0000000..e05af8a --- /dev/null +++ b/assets/js/highlight/styles/tomorrow-night-bright.css @@ -0,0 +1,74 @@ +/* Tomorrow Night Bright Theme */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ + +/* Tomorrow Comment */ +.hljs-comment, +.hljs-quote { + color: #969896; +} + +/* Tomorrow Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-deletion { + color: #d54e53; +} + +/* Tomorrow Orange */ +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params, +.hljs-meta, +.hljs-link { + color: #e78c45; +} + +/* Tomorrow Yellow */ +.hljs-attribute { + color: #e7c547; +} + +/* Tomorrow Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #b9ca4a; +} + +/* Tomorrow Blue */ +.hljs-title, +.hljs-section { + color: #7aa6da; +} + +/* Tomorrow Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #c397d8; +} + +.hljs { + display: block; + overflow-x: auto; + background: black; + color: #eaeaea; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/tomorrow-night-eighties.css b/assets/js/highlight/styles/tomorrow-night-eighties.css new file mode 100644 index 0000000..08fd51c --- /dev/null +++ b/assets/js/highlight/styles/tomorrow-night-eighties.css @@ -0,0 +1,74 @@ +/* Tomorrow Night Eighties Theme */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ + +/* Tomorrow Comment */ +.hljs-comment, +.hljs-quote { + color: #999999; +} + +/* Tomorrow Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-deletion { + color: #f2777a; +} + +/* Tomorrow Orange */ +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params, +.hljs-meta, +.hljs-link { + color: #f99157; +} + +/* Tomorrow Yellow */ +.hljs-attribute { + color: #ffcc66; +} + +/* Tomorrow Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #99cc99; +} + +/* Tomorrow Blue */ +.hljs-title, +.hljs-section { + color: #6699cc; +} + +/* Tomorrow Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #cc99cc; +} + +.hljs { + display: block; + overflow-x: auto; + background: #2d2d2d; + color: #cccccc; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/tomorrow-night.css b/assets/js/highlight/styles/tomorrow-night.css new file mode 100644 index 0000000..ddd270a --- /dev/null +++ b/assets/js/highlight/styles/tomorrow-night.css @@ -0,0 +1,75 @@ +/* Tomorrow Night Theme */ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ + +/* Tomorrow Comment */ +.hljs-comment, +.hljs-quote { + color: #969896; +} + +/* Tomorrow Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-deletion { + color: #cc6666; +} + +/* Tomorrow Orange */ +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params, +.hljs-meta, +.hljs-link { + color: #de935f; +} + +/* Tomorrow Yellow */ +.hljs-attribute { + color: #f0c674; +} + +/* Tomorrow Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #b5bd68; +} + +/* Tomorrow Blue */ +.hljs-title, +.hljs-section { + color: #81a2be; +} + +/* Tomorrow Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #b294bb; +} + +.hljs { + display: block; + overflow-x: auto; + background: #1d1f21; + color: #c5c8c6; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/tomorrow.css b/assets/js/highlight/styles/tomorrow.css new file mode 100644 index 0000000..026a62f --- /dev/null +++ b/assets/js/highlight/styles/tomorrow.css @@ -0,0 +1,72 @@ +/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ + +/* Tomorrow Comment */ +.hljs-comment, +.hljs-quote { + color: #8e908c; +} + +/* Tomorrow Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-deletion { + color: #c82829; +} + +/* Tomorrow Orange */ +.hljs-number, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params, +.hljs-meta, +.hljs-link { + color: #f5871f; +} + +/* Tomorrow Yellow */ +.hljs-attribute { + color: #eab700; +} + +/* Tomorrow Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #718c00; +} + +/* Tomorrow Blue */ +.hljs-title, +.hljs-section { + color: #4271ae; +} + +/* Tomorrow Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #8959a8; +} + +.hljs { + display: block; + overflow-x: auto; + background: white; + color: #4d4d4c; + padding: 0.5em; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/vs.css b/assets/js/highlight/styles/vs.css new file mode 100644 index 0000000..c5d07d3 --- /dev/null +++ b/assets/js/highlight/styles/vs.css @@ -0,0 +1,68 @@ +/* + +Visual Studio-like style based on original C# coloring by Jason Diamond + +*/ +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: white; + color: black; +} + +.hljs-comment, +.hljs-quote, +.hljs-variable { + color: #008000; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-built_in, +.hljs-name, +.hljs-tag { + color: #00f; +} + +.hljs-string, +.hljs-title, +.hljs-section, +.hljs-attribute, +.hljs-literal, +.hljs-template-tag, +.hljs-template-variable, +.hljs-type, +.hljs-addition { + color: #a31515; +} + +.hljs-deletion, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-meta { + color: #2b91af; +} + +.hljs-doctag { + color: #808080; +} + +.hljs-attr { + color: #f00; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link { + color: #00b0e8; +} + + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/highlight/styles/xcode.css b/assets/js/highlight/styles/xcode.css new file mode 100644 index 0000000..43dddad --- /dev/null +++ b/assets/js/highlight/styles/xcode.css @@ -0,0 +1,93 @@ +/* + +XCode style (c) Angel Garcia + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #fff; + color: black; +} + +.hljs-comment, +.hljs-quote { + color: #006a00; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-literal { + color: #aa0d91; +} + +.hljs-name { + color: #008; +} + +.hljs-variable, +.hljs-template-variable { + color: #660; +} + +.hljs-string { + color: #c41a16; +} + +.hljs-regexp, +.hljs-link { + color: #080; +} + +.hljs-title, +.hljs-tag, +.hljs-symbol, +.hljs-bullet, +.hljs-number, +.hljs-meta { + color: #1c00cf; +} + +.hljs-section, +.hljs-class .hljs-title, +.hljs-type, +.hljs-attr, +.hljs-built_in, +.hljs-builtin-name, +.hljs-params { + color: #5c2699; +} + +.hljs-attribute, +.hljs-subst { + color: #000; +} + +.hljs-formula { + background-color: #eee; + font-style: italic; +} + +.hljs-addition { + background-color: #baeeba; +} + +.hljs-deletion { + background-color: #ffc8bd; +} + +.hljs-selector-id, +.hljs-selector-class { + color: #9b703f; +} + +.hljs-doctag, +.hljs-strong { + font-weight: bold; +} + +.hljs-emphasis { + font-style: italic; +} diff --git a/assets/js/highlight/styles/xt256.css b/assets/js/highlight/styles/xt256.css new file mode 100644 index 0000000..351d066 --- /dev/null +++ b/assets/js/highlight/styles/xt256.css @@ -0,0 +1,92 @@ + +/* + xt256.css + + Contact: initbar [at] protonmail [dot] ch + : github.com/initbar +*/ + +.hljs { + display: block; + overflow-x: auto; + color: #eaeaea; + background: #000; + padding: 0.5e; +} + +.hljs-subst { + color: #eaeaea; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-builtin-name, +.hljs-type { + color: #eaeaea; +} + +.hljs-params { + color: #da0000; +} + +.hljs-literal, +.hljs-number, +.hljs-name { + color: #ff0000; + font-weight: bolder; +} + +.hljs-comment { + color: #969896; +} + +.hljs-selector-id, +.hljs-quote { + color: #00ffff; +} + +.hljs-template-variable, +.hljs-variable, +.hljs-title { + color: #00ffff; + font-weight: bold; +} + +.hljs-selector-class, +.hljs-keyword, +.hljs-symbol { + color: #fff000; +} + +.hljs-string, +.hljs-bullet { + color: #00ff00; +} + +.hljs-tag, +.hljs-section { + color: #000fff; +} + +.hljs-selector-tag { + color: #000fff; + font-weight: bold; +} + +.hljs-attribute, +.hljs-built_in, +.hljs-regexp, +.hljs-link { + color: #ff00ff; +} + +.hljs-meta { + color: #fff; + font-weight: bolder; +} diff --git a/assets/js/highlight/styles/zenburn.css b/assets/js/highlight/styles/zenburn.css new file mode 100644 index 0000000..07be502 --- /dev/null +++ b/assets/js/highlight/styles/zenburn.css @@ -0,0 +1,80 @@ +/* + +Zenburn style from voldmar.ru (c) Vladimir Epifanov +based on dark.css by Ivan Sagalaev + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #3f3f3f; + color: #dcdcdc; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-tag { + color: #e3ceab; +} + +.hljs-template-tag { + color: #dcdcdc; +} + +.hljs-number { + color: #8cd0d3; +} + +.hljs-variable, +.hljs-template-variable, +.hljs-attribute { + color: #efdcbc; +} + +.hljs-literal { + color: #efefaf; +} + +.hljs-subst { + color: #8f8f8f; +} + +.hljs-title, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-section, +.hljs-type { + color: #efef8f; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link { + color: #dca3a3; +} + +.hljs-deletion, +.hljs-string, +.hljs-built_in, +.hljs-builtin-name { + color: #cc9393; +} + +.hljs-addition, +.hljs-comment, +.hljs-quote, +.hljs-meta { + color: #7f9f7f; +} + + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/assets/js/html5shiv.min.js b/assets/js/html5shiv.min.js new file mode 100644 index 0000000..bbbc46d --- /dev/null +++ b/assets/js/html5shiv.min.js @@ -0,0 +1,4 @@ +/** + * @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed + */ +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document); \ No newline at end of file diff --git a/assets/js/index.php b/assets/js/index.php new file mode 100644 index 0000000..e668113 --- /dev/null +++ b/assets/js/index.php @@ -0,0 +1,64 @@ +1; +$assets_root = '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . ASSETS_ROOT; +$path = $assets_root . DIRECTORY_SEPARATOR . ASSETS_CACHE_FILE; +$gz_path = $assets_root . DIRECTORY_SEPARATOR . ASSETS_GZIP_CACHE_FILE; + +if (!file_exists($path)) exit('File not found'); +if (!is_readable($path)) exit('File is not readable'); + +header_remove('X-Powered-By'); +header_remove('Pragma'); +header_remove('Set-Cookie'); +header("Content-Type: text/javascript; charset=utf-8"); +header('Cache-Control: public'); +header("Expires: ".date('r',time()+3600*24)); + +if (!empty($etag)) header('ETag: '.$etag); +if (empty($etag) || !isset($_SERVER['HTTP_IF_NONE_MATCH']) || $etag!=$_SERVER['HTTP_IF_NONE_MATCH']) { + header('HTTP/1.1 200 OK'); + + $accept_encoding = ''; + if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && preg_match( '/\b(x-gzip|gzip)\b/', strtolower($_SERVER['HTTP_ACCEPT_ENCODING']), $match)) { + $accept_encoding = $match[1]; + } + if (empty($accept_encoding) && defined('FORCE_GZIP_ASSETS') && FORCE_GZIP_ASSETS) $accept_encoding = 'gzip'; + if ($gzip && function_exists('gzencode') && !@ini_get('zlib.output_compression') && !empty($accept_encoding)) { + header("Vary: Accept-Encoding"); + header("Content-Encoding: " . $accept_encoding); + + if (file_exists($gz_path) && is_readable($gz_path) && filesize($gz_path)>0 && filemtime($gz_path)==filemtime($path)) { + $output = file_get_contents($gz_path); + } else { + $output = file_get_contents($path); + $output = gzencode($output, 9, FORCE_GZIP); + + if (is_writable($assets_root) && ($f=fopen($gz_path,'wb'))!==false) { + fwrite($f, $output); + fclose($f); + touch($gz_path, filemtime($path)); + } + } + } else { + $output = file_get_contents($path); + } + + echo $output; +} else { + header('HTTP/1.1 304 Not Modified'); +} \ No newline at end of file diff --git a/assets/js/jquery.min.js b/assets/js/jquery.min.js new file mode 100644 index 0000000..0f60b7b --- /dev/null +++ b/assets/js/jquery.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; + +return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
  • ").addClass("cw").text("#"));c.isBefore(f.clone().endOf("w"));)b.append(a("").addClass("dow").text(c.format("dd"))),c.add(1,"d");o.find(".datepicker-days thead").append(b)},M=function(a){return d.disabledDates[a.format("YYYY-MM-DD")]===!0},N=function(a){return d.enabledDates[a.format("YYYY-MM-DD")]===!0},O=function(a){return d.disabledHours[a.format("H")]===!0},P=function(a){return d.enabledHours[a.format("H")]===!0},Q=function(b,c){if(!b.isValid())return!1;if(d.disabledDates&&"d"===c&&M(b))return!1;if(d.enabledDates&&"d"===c&&!N(b))return!1;if(d.minDate&&b.isBefore(d.minDate,c))return!1;if(d.maxDate&&b.isAfter(d.maxDate,c))return!1;if(d.daysOfWeekDisabled&&"d"===c&&-1!==d.daysOfWeekDisabled.indexOf(b.day()))return!1;if(d.disabledHours&&("h"===c||"m"===c||"s"===c)&&O(b))return!1;if(d.enabledHours&&("h"===c||"m"===c||"s"===c)&&!P(b))return!1;if(d.disabledTimeIntervals&&("h"===c||"m"===c||"s"===c)){var e=!1;if(a.each(d.disabledTimeIntervals,function(){return b.isBetween(this[0],this[1])?(e=!0,!1):void 0}),e)return!1}return!0},R=function(){for(var b=[],c=f.clone().startOf("y").startOf("d");c.isSame(f,"y");)b.push(a("").attr("data-action","selectMonth").addClass("month").text(c.format("MMM"))),c.add(1,"M");o.find(".datepicker-months td").empty().append(b)},S=function(){var b=o.find(".datepicker-months"),c=b.find("th"),g=b.find("tbody").find("span");c.eq(0).find("span").attr("title",d.tooltips.prevYear),c.eq(1).attr("title",d.tooltips.selectYear),c.eq(2).find("span").attr("title",d.tooltips.nextYear),b.find(".disabled").removeClass("disabled"),Q(f.clone().subtract(1,"y"),"y")||c.eq(0).addClass("disabled"),c.eq(1).text(f.year()),Q(f.clone().add(1,"y"),"y")||c.eq(2).addClass("disabled"),g.removeClass("active"),e.isSame(f,"y")&&!m&&g.eq(e.month()).addClass("active"),g.each(function(b){Q(f.clone().month(b),"M")||a(this).addClass("disabled")})},T=function(){var a=o.find(".datepicker-years"),b=a.find("th"),c=f.clone().subtract(5,"y"),g=f.clone().add(6,"y"),h="";for(b.eq(0).find("span").attr("title",d.tooltips.prevDecade),b.eq(1).attr("title",d.tooltips.selectDecade),b.eq(2).find("span").attr("title",d.tooltips.nextDecade),a.find(".disabled").removeClass("disabled"),d.minDate&&d.minDate.isAfter(c,"y")&&b.eq(0).addClass("disabled"),b.eq(1).text(c.year()+"-"+g.year()),d.maxDate&&d.maxDate.isBefore(g,"y")&&b.eq(2).addClass("disabled");!c.isAfter(g,"y");)h+=''+c.year()+"",c.add(1,"y");a.find("td").html(h)},U=function(){var a=o.find(".datepicker-decades"),c=a.find("th"),g=b({y:f.year()-f.year()%100-1}),h=g.clone().add(100,"y"),i=g.clone(),j="";for(c.eq(0).find("span").attr("title",d.tooltips.prevCentury),c.eq(2).find("span").attr("title",d.tooltips.nextCentury),a.find(".disabled").removeClass("disabled"),(g.isSame(b({y:1900}))||d.minDate&&d.minDate.isAfter(g,"y"))&&c.eq(0).addClass("disabled"),c.eq(1).text(g.year()+"-"+h.year()),(g.isSame(b({y:2e3}))||d.maxDate&&d.maxDate.isBefore(h,"y"))&&c.eq(2).addClass("disabled");!g.isAfter(h,"y");)j+=''+(g.year()+1)+" - "+(g.year()+12)+"",g.add(12,"y");j+="",a.find("td").html(j),c.eq(1).text(i.year()+1+"-"+g.year())},V=function(){var b,c,g,h,i=o.find(".datepicker-days"),j=i.find("th"),k=[];if(A()){for(j.eq(0).find("span").attr("title",d.tooltips.prevMonth),j.eq(1).attr("title",d.tooltips.selectMonth),j.eq(2).find("span").attr("title",d.tooltips.nextMonth),i.find(".disabled").removeClass("disabled"),j.eq(1).text(f.format(d.dayViewHeaderFormat)),Q(f.clone().subtract(1,"M"),"M")||j.eq(0).addClass("disabled"),Q(f.clone().add(1,"M"),"M")||j.eq(2).addClass("disabled"),b=f.clone().startOf("M").startOf("w").startOf("d"),h=0;42>h;h++)0===b.weekday()&&(c=a("
    '+b.week()+"'+b.date()+"
    '+c.format(h?"HH":"hh")+"
    '+c.format("mm")+"
    '+c.format("ss")+"
    a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/
    ","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:k.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m(""}else"application/x-shockwave-flash"==e.source1mime?(f+='',e.poster&&(f+=''),f+=""):-1!=e.source1mime.indexOf("audio")?a.settings.audio_template_callback?f=a.settings.audio_template_callback(e):f+='":"script"==e.type?f+='':f=a.settings.video_template_callback?a.settings.video_template_callback(e):'"}return f}function i(a){var b={};return new tinymce.html.SaxParser({validate:!1,allow_conditional_comments:!0,special:"script,noscript",start:function(a,c){if(b.source1||"param"!=a||(b.source1=c.map.movie),("iframe"==a||"object"==a||"embed"==a||"video"==a||"audio"==a)&&(b.type||(b.type=a),b=tinymce.extend(c.map,b)),"script"==a){var e=d(c.map.src);if(!e)return;b={type:"script",source1:c.map.src,width:e.width,height:e.height}}"source"==a&&(b.source1?b.source2||(b.source2=c.map.src):b.source1=c.map.src),"img"!=a||b.poster||(b.poster=c.map.src)}}).parse(a),b.source1=b.source1||b.src||b.data,b.source2=b.source2||"",b.poster=b.poster||"",b}function j(b){return b.getAttribute("data-mce-object")?i(a.serializer.serialize(b,{selection:!0})):{}}function k(b){if(a.settings.media_filter_html===!1)return b;var c,d=new tinymce.html.Writer;return new tinymce.html.SaxParser({validate:!1,allow_conditional_comments:!1,special:"script,noscript",comment:function(a){d.comment(a)},cdata:function(a){d.cdata(a)},text:function(a,b){d.text(a,b)},start:function(b,e,f){if(c=!0,"script"!=b&&"noscript"!=b){for(var g=0;g=g&&(d(h,{src:b["source"+g],type:b["source"+g+"mime"]}),!b["source"+g]))return;break;case"img":if(!b.poster)return;e=!0}f.start(a,h,i)},end:function(a){if("video"==a&&c)for(var h=1;2>=h;h++)if(b["source"+h]){var i=[];i.map={},h>g&&(d(i,{src:b["source"+h],type:b["source"+h+"mime"]}),f.start("source",i,!0))}if(b.poster&&"object"==a&&c&&!e){var j=[];j.map={},d(j,{src:b.poster,width:b.width,height:b.height}),f.start("img",j,!0)}f.end(a)}},new tinymce.html.Schema({})).parse(a),f.getContent()}function m(b,c){var d,e,f,g,h;for(f=b.attributes,g=f.length;g--;)d=f[g].name,e=f[g].value,"width"!==d&&"height"!==d&&"style"!==d&&(("data"==d||"src"==d)&&(e=a.convertURL(e,d)),c.attr("data-mce-p-"+d,e));h=b.firstChild&&b.firstChild.value,h&&(c.attr("data-mce-html",escape(h)),c.firstChild=null)}function n(a){var b,c=a.name;return b=new tinymce.html.Node("img",1),b.shortEnded=!0,m(a,b),b.attr({width:a.attr("width")||"300",height:a.attr("height")||("audio"==c?"30":"150"),style:a.attr("style"),src:tinymce.Env.transparentSrc,"data-mce-object":c,"class":"mce-object mce-object-"+c}),b}function o(a){var b,c,d,e=a.name;return b=new tinymce.html.Node("span",1),b.attr({contentEditable:"false",style:a.attr("style"),"data-mce-object":e,"class":"mce-preview-object mce-object-"+e}),m(a,b),c=new tinymce.html.Node(e,1),c.attr({src:a.attr("src"),allowfullscreen:a.attr("allowfullscreen"),width:a.attr("width")||"300",height:a.attr("height")||("audio"==e?"30":"150"),frameborder:"0"}),d=new tinymce.html.Node("span",1),d.attr("class","mce-shim"),b.append(c),b.append(d),b}var p=[{regex:/youtu\.be\/([\w\-.]+)/,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/youtube\.com(.+)v=([^&]+)/,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$2",allowFullscreen:!0},{regex:/youtube.com\/embed\/([a-z0-9]+)/i,type:"iframe",w:560,h:314,url:"//www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/vimeo\.com\/([0-9]+)/,type:"iframe",w:425,h:350,url:"//player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc",allowfullscreen:!0},{regex:/vimeo\.com\/(.*)\/([0-9]+)/,type:"iframe",w:425,h:350,url:"//player.vimeo.com/video/$2?title=0&byline=0",allowfullscreen:!0},{regex:/maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,type:"iframe",w:425,h:350,url:'//maps.google.com/maps/ms?msid=$2&output=embed"',allowFullscreen:!1}],q=tinymce.Env.ie&&tinymce.Env.ie<=8?"onChange":"onInput";a.on("ResolveName",function(a){var b;1==a.target.nodeType&&(b=a.target.getAttribute("data-mce-object"))&&(a.name=b)}),a.on("preInit",function(){var b=a.schema.getSpecialElements();tinymce.each("video audio iframe object".split(" "),function(a){b[a]=new RegExp("]*>","gi")});var c=a.schema.getBoolAttrs();tinymce.each("webkitallowfullscreen mozallowfullscreen allowfullscreen".split(" "),function(a){c[a]={}}),a.parser.addNodeFilter("iframe,video,audio,object,embed,script",function(b){for(var c,e,f,g=b.length;g--;)c=b[g],c.parent&&(c.parent.attr("data-mce-object")||("script"!=c.name||(f=d(c.attr("src"))))&&(f&&(f.width&&c.attr("width",f.width.toString()),f.height&&c.attr("height",f.height.toString())),e="iframe"==c.name&&a.settings.media_live_embeds!==!1&&tinymce.Env.ceFalse?o(c):n(c),c.replace(e)))}),a.serializer.addAttributeFilter("data-mce-object",function(a,b){for(var c,d,e,f,g,h,i,j,l=a.length;l--;)if(c=a[l],c.parent){for(i=c.attr(b),d=new tinymce.html.Node(i,1),"audio"!=i&&"script"!=i&&(j=c.attr("class"),j&&-1!==j.indexOf("mce-preview-object")?d.attr({width:c.firstChild.attr("width"),height:c.firstChild.attr("height")}):d.attr({width:c.attr("width"),height:c.attr("height")})),d.attr({style:c.attr("style")}),f=c.attributes,e=f.length;e--;){var m=f[e].name;0===m.indexOf("data-mce-p-")&&d.attr(m.substr(11),f[e].value)}"script"==i&&d.attr("type","text/javascript"),g=c.attr("data-mce-html"),g&&(h=new tinymce.html.Node("#text",3),h.raw=!0,h.value=k(unescape(g)),d.append(h)),c.replace(d)}}),a.on("PastePreProcess",function(a){var b=g(a.content);b&&(a.content=b)})}),a.on("ObjectSelected",function(a){var b=a.target.getAttribute("data-mce-object");("audio"==b||"script"==b)&&a.preventDefault()}),a.on("objectResized",function(a){var b,c=a.target;c.getAttribute("data-mce-object")&&(b=c.getAttribute("data-mce-html"),b&&(b=unescape(b),c.setAttribute("data-mce-html",escape(l(b,{width:a.width,height:a.height})))))}),a.addButton("media",{tooltip:"Insert/edit video",onclick:e,stateSelector:["img[data-mce-object]","span[data-mce-object]"]}),a.addMenuItem("media",{icon:"media",text:"Insert/edit video",onclick:e,context:"insert",prependToContext:!0}),a.addCommand("mceMedia",e),this.showDialog=e}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/nonbreaking/plugin.min.js b/assets/js/tinymce/plugins/nonbreaking/plugin.min.js new file mode 100644 index 0000000..190dc33 --- /dev/null +++ b/assets/js/tinymce/plugins/nonbreaking/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("nonbreaking",function(a){var b=a.getParam("nonbreaking_force_tab");if(a.addCommand("mceNonBreaking",function(){a.insertContent(a.plugins.visualchars&&a.plugins.visualchars.state?' ':" "),a.dom.setAttrib(a.dom.select("span.mce-nbsp"),"data-mce-bogus","1")}),a.addButton("nonbreaking",{title:"Nonbreaking space",cmd:"mceNonBreaking"}),a.addMenuItem("nonbreaking",{text:"Nonbreaking space",cmd:"mceNonBreaking",context:"insert"}),b){var c=+b>1?+b:3;a.on("keydown",function(b){if(9==b.keyCode){if(b.shiftKey)return;b.preventDefault();for(var d=0;c>d;d++)a.execCommand("mceNonBreaking")}})}}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/noneditable/plugin.min.js b/assets/js/tinymce/plugins/noneditable/plugin.min.js new file mode 100644 index 0000000..49e9d5a --- /dev/null +++ b/assets/js/tinymce/plugins/noneditable/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("noneditable",function(a){function b(a){return function(b){return-1!==(" "+b.attr("class")+" ").indexOf(a)}}function c(b){function c(b){var c=arguments,d=c[c.length-2];return d>0&&'"'==g.charAt(d-1)?b:''+a.dom.encode("string"==typeof c[1]?c[1]:c[0])+""}var d=f.length,g=b.content,h=tinymce.trim(e);if("raw"!=b.format){for(;d--;)g=g.replace(f[d],c);b.content=g}}var d,e,f,g="contenteditable";d=" "+tinymce.trim(a.getParam("noneditable_editable_class","mceEditable"))+" ",e=" "+tinymce.trim(a.getParam("noneditable_noneditable_class","mceNonEditable"))+" ";var h=b(d),i=b(e);f=a.getParam("noneditable_regexp"),f&&!f.length&&(f=[f]),a.on("PreInit",function(){f&&a.on("BeforeSetContent",c),a.parser.addAttributeFilter("class",function(a){for(var b,c=a.length;c--;)b=a[c],h(b)?b.attr(g,"true"):i(b)&&b.attr(g,"false")}),a.serializer.addAttributeFilter(g,function(a){for(var b,c=a.length;c--;)b=a[c],(h(b)||i(b))&&(f&&b.attr("data-mce-content")?(b.name="#text",b.type=3,b.raw=!0,b.value=b.attr("data-mce-content")):b.attr(g,null))})})}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/pagebreak/plugin.min.js b/assets/js/tinymce/plugins/pagebreak/plugin.min.js new file mode 100644 index 0000000..2a69eba --- /dev/null +++ b/assets/js/tinymce/plugins/pagebreak/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("pagebreak",function(a){var b="mce-pagebreak",c=a.getParam("pagebreak_separator",""),d=new RegExp(c.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(a){return"\\"+a}),"gi"),e='';a.addCommand("mcePageBreak",function(){a.settings.pagebreak_split_block?a.insertContent("

    "+e+"

    "):a.insertContent(e)}),a.addButton("pagebreak",{title:"Page break",cmd:"mcePageBreak"}),a.addMenuItem("pagebreak",{text:"Page break",icon:"pagebreak",cmd:"mcePageBreak",context:"insert"}),a.on("ResolveName",function(c){"IMG"==c.target.nodeName&&a.dom.hasClass(c.target,b)&&(c.name="pagebreak")}),a.on("click",function(c){c=c.target,"IMG"===c.nodeName&&a.dom.hasClass(c,b)&&a.selection.select(c)}),a.on("BeforeSetContent",function(a){a.content=a.content.replace(d,e)}),a.on("PreInit",function(){a.serializer.addNodeFilter("img",function(b){for(var d,e,f=b.length;f--;)if(d=b[f],e=d.attr("class"),e&&-1!==e.indexOf("mce-pagebreak")){var g=d.parent;if(a.schema.getBlockElements()[g.name]&&a.settings.pagebreak_split_block){g.type=3,g.value=c,g.raw=!0,d.remove();continue}d.type=3,d.value=c,d.raw=!0}})})}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/paste/plugin.min.js b/assets/js/tinymce/plugins/paste/plugin.min.js new file mode 100644 index 0000000..0145b01 --- /dev/null +++ b/assets/js/tinymce/plugins/paste/plugin.min.js @@ -0,0 +1 @@ +!function(a,b){"use strict";function c(a,b){for(var c,d=[],f=0;f/g]),f(h.parse(e)),i}function f(a){function b(a,b,c){return b||c?"\xa0":" "}return a=d(a,[/^[\s\S]*]*>\s*|\s*<\/body[^>]*>[\s\S]*$/g,/|/g,[/( ?)\u00a0<\/span>( ?)/g,b],/
    /g,/
    $/i])}return{filter:d,innerText:e,trimHtml:f}}),d("tinymce/pasteplugin/Clipboard",["tinymce/Env","tinymce/dom/RangeUtils","tinymce/util/VK","tinymce/pasteplugin/Utils","tinymce/util/Delay"],function(a,b,c,d,e){return function(f){function g(a){var b,c=f.dom;if(b=f.fire("BeforePastePreProcess",{content:a}),b=f.fire("PastePreProcess",b),a=b.content,!b.isDefaultPrevented()){if(f.hasEventListeners("PastePostProcess")&&!b.isDefaultPrevented()){var d=c.add(f.getBody(),"div",{style:"display:none"},a);b=f.fire("PastePostProcess",{node:d}),c.remove(d),a=b.node.innerHTML}b.isDefaultPrevented()||f.insertContent(a,{merge:f.settings.paste_merge_formats!==!1,data:{paste:!0}})}}function h(a){a=f.dom.encode(a).replace(/\r\n/g,"\n");var b,c=f.dom.getParent(f.selection.getStart(),f.dom.isBlock),e=f.settings.forced_root_block;e&&(b=f.dom.createHTML(e,f.settings.forced_root_block_attrs),b=b.substr(0,b.length-3)+">"),c&&/^(PRE|DIV)$/.test(c.nodeName)||!e?a=d.filter(a,[[/\n/g,"
    "]]):(a=d.filter(a,[[/\n\n/g,"

    "+b],[/^(.*<\/p>)(

    )$/,b+"$1"],[/\n/g,"
    "]]),-1!=a.indexOf("

    ")&&(a=b+a)),g(a)}function i(){function b(a){var b,c,e,f=a.startContainer;if(b=a.getClientRects(),b.length)return b[0];if(a.collapsed&&1==f.nodeType){for(e=f.childNodes[w.startOffset];e&&3==e.nodeType&&!e.data.length;)e=e.nextSibling;if(e)return"BR"==e.tagName&&(c=d.doc.createTextNode("\ufeff"),e.parentNode.insertBefore(c,e),a=d.createRng(),a.setStartBefore(c),a.setEndAfter(c),b=a.getClientRects(),d.remove(c)),b.length?b[0]:void 0}}var c,d=f.dom,e=f.getBody(),g=f.dom.getViewPort(f.getWin()),h=g.y,i=20;if(w=f.selection.getRng(),f.inline&&(c=f.selection.getScrollContainer(),c&&c.scrollTop>0&&(h=c.scrollTop)),w.getClientRects){var j=b(w);if(j)i=h+(j.top-d.getPos(e).y);else{i=h;var k=w.startContainer;k&&(3==k.nodeType&&k.parentNode!=e&&(k=k.parentNode),1==k.nodeType&&(i=d.getPos(k,c||e).y))}}v=d.add(f.getBody(),"div",{id:"mcepastebin",contentEditable:!0,"data-mce-bogus":"all",style:"position: absolute; top: "+i+"px;width: 10px; height: 10px; overflow: hidden; opacity: 0"},B),(a.ie||a.gecko)&&d.setStyle(v,"left","rtl"==d.getStyle(e,"direction",!0)?65535:-65535),d.bind(v,"beforedeactivate focusin focusout",function(a){a.stopPropagation()}),v.focus(),f.selection.select(v,!0)}function j(){if(v){for(var a;a=f.dom.get("mcepastebin");)f.dom.remove(a),f.dom.unbind(a);w&&f.selection.setRng(w)}v=w=null}function k(){var a,b,c,d,e="";for(a=f.dom.select("div[id=mcepastebin]"),b=0;b>8);return decodeURIComponent(escape(c))}function m(a){var b,c,d;return c="",b=a.indexOf(c),-1!==b&&(a=a.substr(b+c.length)),d="",b=a.indexOf(d),-1!==b&&(a=a.substr(0,b)),a}function n(a){var b={};if(a){if(a.getData){var c=a.getData("Text");c&&c.length>0&&-1==c.indexOf(C)&&(b["text/plain"]=c)}if(a.types)for(var d=0;d')}var e,h,i,j=!1;if(c)for(e=0;e0}function t(a){return c.metaKeyPressed(a)&&86==a.keyCode||a.shiftKey&&45==a.keyCode}function u(){function b(a,b,c){var e;return s(a,"text/html")?e=a["text/html"]:(e=k(),e==B&&(c=!0)),e=d.trimHtml(e),v&&v.firstChild&&"mcepastebin"===v.firstChild.id&&(c=!0),j(),e.length||(c=!0),c&&(e=s(a,"text/plain")&&-1==e.indexOf("

    ")?a["text/plain"]:d.innerText(e)),e==B?void(b||f.windowManager.alert("Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.")):void(c?h(e):g(e))}f.on("keydown",function(b){function c(a){t(a)&&!a.isDefaultPrevented()&&j()}if(t(b)&&!b.isDefaultPrevented()){if(x=b.shiftKey&&86==b.keyCode,x&&a.webkit&&-1!=navigator.userAgent.indexOf("Version/"))return;if(b.stopImmediatePropagation(),z=(new Date).getTime(),a.ie&&x)return b.preventDefault(),void f.fire("paste",{ieFake:!0});j(),i(),f.once("keyup",c),f.once("paste",function(){f.off("keyup",c)})}}),f.on("paste",function(c){var d=(new Date).getTime(),g=o(c),h=(new Date).getTime()-d,l=(new Date).getTime()-z-h<1e3,m="text"==y.pasteFormat||x;return x=!1,c.isDefaultPrevented()||q(c)?void j():p(c)?void j():(l||c.preventDefault(),!a.ie||l&&!c.ieFake||(i(),f.dom.bind(v,"paste",function(a){a.stopPropagation()}),f.getDoc().execCommand("Paste",!1,null),g["text/html"]=k()),void(s(g,"text/html")?(c.preventDefault(),b(g,l,m)):e.setEditorTimeout(f,function(){b(g,l,m)},0)))}),f.on("dragstart dragend",function(a){A="dragstart"==a.type}),f.on("drop",function(a){var b=r(a);if(!a.isDefaultPrevented()&&!A&&!p(a,b)&&b&&f.settings.paste_filter_drop!==!1){var c=n(a.dataTransfer),e=c["mce-internal"]||c["text/html"]||c["text/plain"];e&&(a.preventDefault(),f.undoManager.transact(function(){c["mce-internal"]&&f.execCommand("Delete"),f.selection.setRng(b),e=d.trimHtml(e),c["text/html"]?g(e):h(e)}))}}),f.on("dragover dragend",function(a){f.settings.paste_data_images&&a.preventDefault()})}var v,w,x,y=this,z=0,A=!1,B="%MCEPASTEBIN%",C="data:text/mce-internal,";y.pasteHtml=g,y.pasteText=h,f.on("preInit",function(){u(),f.parser.addNodeFilter("img",function(b,c,d){function e(a){return a.data&&a.data.paste===!0}function g(b){b.attr("data-mce-object")||k===a.transparentSrc||b.remove()}function h(a){return 0===a.indexOf("webkit-fake-url")}function i(a){return 0===a.indexOf("data:")}if(!f.settings.paste_data_images&&e(d))for(var j=b.length;j--;){var k=b[j].attributes.map.src;k&&(h(k)?g(b[j]):!f.settings.allow_html_data_urls&&i(k)&&g(b[j]))}})})}}),d("tinymce/pasteplugin/WordFilter",["tinymce/util/Tools","tinymce/html/DomParser","tinymce/html/Schema","tinymce/html/Serializer","tinymce/html/Node","tinymce/pasteplugin/Utils"],function(a,b,c,d,e,f){function g(a){return/h?g&&(g=g.parent.parent):(j=g,g=null)),g&&g.name==b?g.append(a):(j=j||g,g=new e(b,1),f>1&&g.attr("start",""+f),a.wrap(g)),a.name="li",h>k&&j&&j.lastChild.append(g),k=h,d(a),c(a,/^\u00a0+/),c(a,/^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/),c(a,/^\u00a0+/)}for(var g,j,k=1,l=[],m=a.firstChild;"undefined"!=typeof m&&null!==m;)if(l.push(m),m=m.walk(),null!==m)for(;"undefined"!=typeof m&&m.parent!==a;)m=m.walk();for(var n=0;n]+id="?docs-internal-[^>]*>/gi,""),q=q.replace(/
    /gi,""),o=k.paste_retain_style_properties,o&&(p=a.makeMap(o.split(/[, ]/))),k.paste_enable_default_filters!==!1&&g(l.content)){l.wordContent=!0,q=f.filter(q,[//gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/([\s\u00a0]*)<\/span>/gi,function(a,b){return b.length>0?b.replace(/./," ").slice(Math.floor(b.length/2)).split("").join("\xa0"):""}]]);var r=k.paste_word_valid_elements;r||(r="-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody");var s=new c({valid_elements:r,valid_children:"-li[p]"});a.each(s.elements,function(a){a.attributes["class"]||(a.attributes["class"]={},a.attributesOrder.push("class")),a.attributes.style||(a.attributes.style={},a.attributesOrder.push("style"))});var t=new b({},s);t.addAttributeFilter("style",function(a){for(var b,c=a.length;c--;)b=a[c],b.attr("style",n(b,b.attr("style"))),"span"==b.name&&b.parent&&!b.attributes.length&&b.unwrap()}),t.addAttributeFilter("class",function(a){for(var b,c,d=a.length;d--;)b=a[d],c=b.attr("class"),/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(c)&&b.remove(),b.attr("class",null)}),t.addNodeFilter("del",function(a){for(var b=a.length;b--;)a[b].remove()}),t.addNodeFilter("a",function(a){for(var b,c,d,e=a.length;e--;)if(b=a[e],c=b.attr("href"),d=b.attr("name"),c&&-1!=c.indexOf("#_msocom_"))b.remove();else if(c&&0===c.indexOf("file://")&&(c=c.split("#")[1],c&&(c="#"+c)),c||d){if(d&&!/^_?(?:toc|edn|ftn)/i.test(d)){b.unwrap();continue}b.attr({href:c,name:d})}else b.unwrap()});var u=t.parse(q);k.paste_convert_word_fake_lists!==!1&&m(u),l.content=new d({validate:k.validate},s).serialize(u)}})}return j.isWordContent=g,j}),d("tinymce/pasteplugin/Quirks",["tinymce/Env","tinymce/util/Tools","tinymce/pasteplugin/WordFilter","tinymce/pasteplugin/Utils"],function(a,b,c,d){return function(e){function f(a){e.on("BeforePastePreProcess",function(b){b.content=a(b.content)})}function g(a){if(!c.isWordContent(a))return a;var f=[];b.each(e.schema.getBlockElements(),function(a,b){f.push(b)});var g=new RegExp("(?:
     [\\s\\r\\n]+|
    )*(<\\/?("+f.join("|")+")[^>]*>)(?:
     [\\s\\r\\n]+|
    )*","g");return a=d.filter(a,[[g,"$1"]]),a=d.filter(a,[[/

    /g,"

    "],[/
    /g," "],[/

    /g,"
    "]])}function h(a){if(c.isWordContent(a))return a;var b=e.settings.paste_webkit_styles;if(e.settings.paste_remove_styles_if_webkit===!1||"all"==b)return a;if(b&&(b=b.split(/[, ]/)),b){var d=e.dom,f=e.selection.getNode();a=a.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi,function(a,c,e,g){var h=d.parseStyle(e,"span"),i={};if("none"===b)return c+g;for(var j=0;j]+) style="([^"]*)"([^>]*>)/gi,"$1$3");return a=a.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi,function(a,b,c,d){return b+' style="'+c+'"'+d})}a.webkit&&f(h),a.ie&&f(g)}}),d("tinymce/pasteplugin/Plugin",["tinymce/PluginManager","tinymce/pasteplugin/Clipboard","tinymce/pasteplugin/WordFilter","tinymce/pasteplugin/Quirks"],function(a,b,c,d){var e;a.add("paste",function(a){function f(){if("text"==g.pasteFormat)this.active(!1),g.pasteFormat="html";else if(g.pasteFormat="text",this.active(!0),!e){var b=a.translate("Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.");a.notificationManager.open({text:b,type:"info"}),e=!0}}var g,h=this,i=a.settings;h.clipboard=g=new b(a),h.quirks=new d(a),h.wordFilter=new c(a),a.settings.paste_as_text&&(h.clipboard.pasteFormat="text"),i.paste_preprocess&&a.on("PastePreProcess",function(a){i.paste_preprocess.call(h,h,a)}),i.paste_postprocess&&a.on("PastePostProcess",function(a){i.paste_postprocess.call(h,h,a)}),a.addCommand("mceInsertClipboardContent",function(a,b){b.content&&h.clipboard.pasteHtml(b.content),b.text&&h.clipboard.pasteText(b.text)}),a.paste_block_drop&&a.on("dragend dragover draggesture dragdrop drop drag",function(a){a.preventDefault(),a.stopPropagation()}),a.settings.paste_data_images||a.on("drop",function(a){var b=a.dataTransfer;b&&b.files&&b.files.length>0&&a.preventDefault()}),a.addButton("pastetext",{icon:"pastetext",tooltip:"Paste as text",onclick:f,active:"text"==h.clipboard.pasteFormat}),a.addMenuItem("pastetext",{text:"Paste as text",selectable:!0,active:g.pasteFormat,onclick:f})})}),f(["tinymce/pasteplugin/Utils"])}(this); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/preview/plugin.min.js b/assets/js/tinymce/plugins/preview/plugin.min.js new file mode 100644 index 0000000..10e57e2 --- /dev/null +++ b/assets/js/tinymce/plugins/preview/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("preview",function(a){var b=a.settings,c=!tinymce.Env.ie;a.addCommand("mcePreview",function(){a.windowManager.open({title:"Preview",width:parseInt(a.getParam("plugin_preview_width","650"),10),height:parseInt(a.getParam("plugin_preview_height","500"),10),html:'",buttons:{text:"Close",onclick:function(){this.parent().parent().close()}},onPostRender:function(){var d,e="";e+='',tinymce.each(a.contentCSS,function(b){e+=''});var f=b.body_id||"tinymce";-1!=f.indexOf("=")&&(f=a.getParam("body_id","","hash"),f=f[a.id]||f);var g=b.body_class||"";-1!=g.indexOf("=")&&(g=a.getParam("body_class","","hash"),g=g[a.id]||"");var h=a.settings.directionality?' dir="'+a.settings.directionality+'"':"";if(d=""+e+'"+a.getContent()+"",c)this.getEl("body").firstChild.src="data:text/html;charset=utf-8,"+encodeURIComponent(d);else{var i=this.getEl("body").firstChild.contentWindow.document;i.open(),i.write(d),i.close()}}})}),a.addButton("preview",{title:"Preview",cmd:"mcePreview"}),a.addMenuItem("preview",{text:"Preview",cmd:"mcePreview",context:"view"})}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/print/plugin.min.js b/assets/js/tinymce/plugins/print/plugin.min.js new file mode 100644 index 0000000..e91ff54 --- /dev/null +++ b/assets/js/tinymce/plugins/print/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("print",function(a){a.addCommand("mcePrint",function(){a.getWin().print()}),a.addButton("print",{title:"Print",cmd:"mcePrint"}),a.addShortcut("Meta+P","","mcePrint"),a.addMenuItem("print",{text:"Print",cmd:"mcePrint",icon:"print",shortcut:"Meta+P",context:"file"})}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/save/plugin.min.js b/assets/js/tinymce/plugins/save/plugin.min.js new file mode 100644 index 0000000..b805dbd --- /dev/null +++ b/assets/js/tinymce/plugins/save/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("save",function(a){function b(){var b;return b=tinymce.DOM.getParent(a.id,"form"),!a.getParam("save_enablewhendirty",!0)||a.isDirty()?(tinymce.triggerSave(),a.getParam("save_onsavecallback")?(a.execCallback("save_onsavecallback",a),void a.nodeChanged()):void(b?(a.setDirty(!1),(!b.onsubmit||b.onsubmit())&&("function"==typeof b.submit?b.submit():c(a.translate("Error: Form submit field collision."))),a.nodeChanged()):c(a.translate("Error: No form element found.")))):void 0}function c(b){a.notificationManager.open({text:b,type:"error"})}function d(){var b=tinymce.trim(a.startContent);return a.getParam("save_oncancelcallback")?void a.execCallback("save_oncancelcallback",a):(a.setContent(b),a.undoManager.clear(),void a.nodeChanged())}function e(){var b=this;a.on("nodeChange dirty",function(){b.disabled(a.getParam("save_enablewhendirty",!0)&&!a.isDirty())})}a.addCommand("mceSave",b),a.addCommand("mceCancel",d),a.addButton("save",{icon:"save",text:"Save",cmd:"mceSave",disabled:!0,onPostRender:e}),a.addButton("cancel",{text:"Cancel",icon:!1,cmd:"mceCancel",disabled:!0,onPostRender:e}),a.addShortcut("Meta+S","","mceSave")}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/searchreplace/plugin.min.js b/assets/js/tinymce/plugins/searchreplace/plugin.min.js new file mode 100644 index 0000000..a139b71 --- /dev/null +++ b/assets/js/tinymce/plugins/searchreplace/plugin.min.js @@ -0,0 +1 @@ +!function(){function a(a){return a&&1==a.nodeType&&"false"===a.contentEditable}function b(b,c,d,e,f){function g(a,b){if(b=b||0,!a[0])throw"findAndReplaceDOMText cannot handle zero-length matches";var c=a.index;if(b>0){var d=a[b];if(!d)throw"Invalid capture group";c+=a[0].indexOf(d),a[0]=d}return[c,c+a[0].length,[a[0]]]}function h(b){var c;if(3===b.nodeType)return b.data;if(o[b.nodeName]&&!n[b.nodeName])return"";if(c="",a(b))return"\n";if((n[b.nodeName]||p[b.nodeName])&&(c+="\n"),b=b.firstChild)do c+=h(b);while(b=b.nextSibling);return c}function i(b,c,d){var e,f,g,h,i=[],j=0,k=b,l=c.shift(),m=0;a:for(;;){if((n[k.nodeName]||p[k.nodeName]||a(k))&&j++,3===k.nodeType&&(!f&&k.length+j>=l[1]?(f=k,h=l[1]-j):e&&i.push(k),!e&&k.length+j>l[0]&&(e=k,g=l[0]-j),j+=k.length),e&&f){if(k=d({startNode:e,startNodeIndex:g,endNode:f,endNodeIndex:h,innerNodes:i,match:l[2],matchIndex:m}),j-=f.length-h,e=null,f=null,i=[],l=c.shift(),m++,!l)break}else if(o[k.nodeName]&&!n[k.nodeName]||!k.firstChild){if(k.nextSibling){k=k.nextSibling;continue}}else if(!a(k)){k=k.firstChild;continue}for(;;){if(k.nextSibling){k=k.nextSibling;break}if(k.parentNode===b)break a;k=k.parentNode}}}function j(a){var b;if("function"!=typeof a){var c=a.nodeType?a:m.createElement(a);b=function(a,b){var d=c.cloneNode(!1);return d.setAttribute("data-mce-index",b),a&&d.appendChild(m.createTextNode(a)),d}}else b=a;return function(a){var c,d,e,f=a.startNode,g=a.endNode,h=a.matchIndex;if(f===g){var i=f;e=i.parentNode,a.startNodeIndex>0&&(c=m.createTextNode(i.data.substring(0,a.startNodeIndex)),e.insertBefore(c,i));var j=b(a.match[0],h);return e.insertBefore(j,i),a.endNodeIndexn;++n){var p=a.innerNodes[n],q=b(p.data,h);p.parentNode.replaceChild(q,p),l.push(q)}var r=b(g.data.substring(0,a.endNodeIndex),h);return e=f.parentNode,e.insertBefore(c,f),e.insertBefore(k,f),e.removeChild(f),e=g.parentNode,e.insertBefore(r,g),e.insertBefore(d,g),e.removeChild(g),r}}var k,l,m,n,o,p,q=[],r=0;if(m=c.ownerDocument,n=f.getBlockElements(),o=f.getWhiteSpaceElements(),p=f.getShortEndedElements(),l=h(c)){if(b.global)for(;k=b.exec(l);)q.push(g(k,e));else k=l.match(b),q.push(g(k,e));return q.length&&(r=q.length,i(c,q,j(d))),r}}function c(a){function c(){function b(){f.statusbar.find("#next").disabled(!g(l+1).length),f.statusbar.find("#prev").disabled(!g(l-1).length)}function c(){tinymce.ui.MessageBox.alert("Could not find the specified string.",function(){f.find("#find")[0].focus()})}var d,e={};d=tinymce.trim(a.selection.getContent({format:"text"}));var f=tinymce.ui.Factory.create({type:"window",layout:"flex",pack:"center",align:"center",onClose:function(){a.focus(),k.done()},onSubmit:function(a){var d,h,i,j;return a.preventDefault(),h=f.find("#case").checked(),j=f.find("#words").checked(),i=f.find("#find").value(),i.length?e.text==i&&e.caseState==h&&e.wholeWord==j?0===g(l+1).length?void c():(k.next(),void b()):(d=k.find(i,h,j),d||c(),f.statusbar.items().slice(1).disabled(0===d),b(),void(e={text:i,caseState:h,wholeWord:j})):(k.done(!1),void f.statusbar.items().slice(1).disabled(!0))},buttons:[{text:"Find",subtype:"primary",onclick:function(){f.submit()}},{text:"Replace",disabled:!0,onclick:function(){k.replace(f.find("#replace").value())||(f.statusbar.items().slice(1).disabled(!0),l=-1,e={})}},{text:"Replace all",disabled:!0,onclick:function(){k.replace(f.find("#replace").value(),!0,!0),f.statusbar.items().slice(1).disabled(!0),e={}}},{type:"spacer",flex:1},{text:"Prev",name:"prev",disabled:!0,onclick:function(){k.prev(),b()}},{text:"Next",name:"next",disabled:!0,onclick:function(){k.next(),b()}}],title:"Find and replace",items:{type:"form",padding:20,labelGap:30,spacing:10,items:[{type:"textbox",name:"find",size:40,label:"Find",value:d},{type:"textbox",name:"replace",size:40,label:"Replace with"},{type:"checkbox",name:"case",text:"Match case",label:" "},{type:"checkbox",name:"words",text:"Whole words",label:" "}]}}).renderTo().reflow()}function d(a){var b=a.getAttribute("data-mce-index");return"number"==typeof b?""+b:b}function e(c){var d,e;return e=a.dom.create("span",{"data-mce-bogus":1}),e.className="mce-match-marker",d=a.getBody(),k.done(!1),b(c,d,e,!1,a.schema)}function f(a){var b=a.parentNode;a.firstChild&&b.insertBefore(a.firstChild,a),a.parentNode.removeChild(a)}function g(b){var c,e=[];if(c=tinymce.toArray(a.getBody().getElementsByTagName("span")),c.length)for(var f=0;f0}var k=this,l=-1;k.init=function(a){a.addMenuItem("searchreplace",{text:"Find and replace",shortcut:"Meta+F",onclick:c,separator:"before",context:"edit"}),a.addButton("searchreplace",{tooltip:"Find and replace",shortcut:"Meta+F",onclick:c}),a.addCommand("SearchReplace",c),a.shortcuts.add("Meta+F","",c)},k.find=function(a,b,c){a=a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),a=c?"\\b"+a+"\\b":a;var d=e(new RegExp(a,b?"g":"gi"));return d&&(l=-1,l=h(!0)),d},k.next=function(){var a=h(!0);-1!==a&&(l=a)},k.prev=function(){var a=h(!1);-1!==a&&(l=a)},k.replace=function(b,c,e){var h,m,n,o,p,q,r=l;for(c=c!==!1,n=a.getBody(),m=tinymce.grep(tinymce.toArray(n.getElementsByTagName("span")),j),h=0;hl&&m[h].setAttribute("data-mce-index",p-1)}return a.undoManager.add(),l=r,c?(q=g(r+1).length>0,k.next()):(q=g(r-1).length>0,k.prev()),!e&&q},k.done=function(b){var c,e,g,h;for(e=tinymce.toArray(a.getBody().getElementsByTagName("span")),c=0;c=i.end?(f=l,h=i.end-k):e&&j.push(l),!e&&l.length+k>i.start&&(e=l,g=i.start-k),k+=l.length),e&&f){if(l=d({startNode:e,startNodeIndex:g,endNode:f,endNodeIndex:h,innerNodes:j,match:i.text,matchIndex:m}),k-=f.length-h,e=null,f=null,j=[],i=c.shift(),m++,!i)break}else if(y[l.nodeName]&&!x[l.nodeName]||!l.firstChild){if(l.nextSibling){l=l.nextSibling;continue}}else if(!a(l)){l=l.firstChild;continue}for(;;){if(l.nextSibling){l=l.nextSibling;break}if(l.parentNode===b)break a;l=l.parentNode}}}function g(a){function b(b,c){var d=A[c];d.stencil||(d.stencil=a(d));var e=d.stencil.cloneNode(!1);return e.setAttribute("data-mce-index",c),b&&e.appendChild(B.doc.createTextNode(b)),e}return function(a){var c,d,e,f=a.startNode,g=a.endNode,h=a.matchIndex,i=B.doc;if(f===g){var j=f;e=j.parentNode,a.startNodeIndex>0&&(c=i.createTextNode(j.data.substring(0,a.startNodeIndex)),e.insertBefore(c,j));var k=b(a.match,h);return e.insertBefore(k,j),a.endNodeIndexn;++n){var p=a.innerNodes[n],q=b(p.data,h);p.parentNode.replaceChild(q,p),m.push(q)}var r=b(g.data.substring(0,a.endNodeIndex),h);return e=f.parentNode,e.insertBefore(c,f),e.insertBefore(l,f),e.removeChild(f),e=g.parentNode,e.insertBefore(r,g),e.insertBefore(d,g),e.removeChild(g),r}}function h(a){var b=a.parentNode;b.insertBefore(a.firstChild,a),a.parentNode.removeChild(a)}function i(a){var c=b.getElementsByTagName("*"),d=[];a="number"==typeof a?""+a:null;for(var e=0;eb&&a(A[b],b)!==!1;b++);return this}function m(a){return A.length&&f(b,A,g(a)),this}function n(a,b){if(w&&a.global)for(;v=a.exec(w);)A.push(d(v,b));return this}function o(a){var b,c=i(a?j(a):null);for(b=c.length;b--;)h(c[b]);return this}function p(a){return A[a.getAttribute("data-mce-index")]}function q(a){return i(j(a))[0]}function r(a,b,c){return A.push({start:a,end:a+b,text:w.substr(a,b),data:c}),this}function s(a){var b=i(j(a)),d=c.dom.createRng();return d.setStartBefore(b[0]),d.setEndAfter(b[b.length-1]),d}function t(a,b){var d=s(a);return d.deleteContents(),b.length>0&&d.insertNode(c.dom.doc.createTextNode(b)),d}function u(){return A.splice(0,A.length),o(),this}var v,w,x,y,z,A=[],B=c.dom;return x=c.schema.getBlockElements(),y=c.schema.getWhiteSpaceElements(),z=c.schema.getShortEndedElements(),w=e(b),{text:w,matches:A,each:l,filter:k,reset:u,matchFromElement:p,elementFromMatch:q,find:n,add:r,wrap:m,unwrap:o,replace:t,rangeFromMatch:s,indexOf:j}}}),d("tinymce/spellcheckerplugin/Plugin",["tinymce/spellcheckerplugin/DomTextMatcher","tinymce/PluginManager","tinymce/util/Tools","tinymce/ui/Menu","tinymce/dom/DOMUtils","tinymce/util/XHR","tinymce/util/URI","tinymce/util/JSON"],function(a,b,c,d,e,f,g,h){b.add("spellchecker",function(b,i){function j(){return E.textMatcher||(E.textMatcher=new a(b.getBody(),b)),E.textMatcher}function k(a,b){var d=[];return c.each(b,function(a){d.push({selectable:!0,text:a.name,data:a.value})}),d}function l(a){for(var b in a)return!1;return!0}function m(a,f){var g=[],h=A[a];c.each(h,function(a){g.push({text:a,onclick:function(){b.insertContent(b.dom.encode(a)),b.dom.remove(f),r()}})}),g.push({text:"-"}),D&&g.push({text:"Add to Dictionary",onclick:function(){s(a,f)}}),g.push.apply(g,[{text:"Ignore",onclick:function(){t(a,f)}},{text:"Ignore all",onclick:function(){t(a,f,!0)}}]),C=new d({items:g,context:"contextmenu",onautohide:function(a){-1!=a.target.className.indexOf("spellchecker")&&a.preventDefault()},onhide:function(){C.remove(),C=null}}),C.renderTo(document.body);var i=e.DOM.getPos(b.getContentAreaContainer()),j=b.dom.getPos(f[0]),k=b.dom.getRoot();"BODY"==k.nodeName?(j.x-=k.ownerDocument.documentElement.scrollLeft||k.scrollLeft,j.y-=k.ownerDocument.documentElement.scrollTop||k.scrollTop):(j.x-=k.scrollLeft,j.y-=k.scrollTop),i.x+=j.x,i.y+=j.y,C.moveTo(i.x,i.y+f[0].offsetHeight)}function n(){return b.getParam("spellchecker_wordchar_pattern")||new RegExp('[^\\s!"#$%&()*+,-./:;<=>?@[\\]^_{|}`\xa7\xa9\xab\xae\xb1\xb6\xb7\xb8\xbb\xbc\xbd\xbe\xbf\xd7\xf7\xa4\u201d\u201c\u201e\xa0\u2002\u2003\u2009]+',"g")}function o(a,d,e,j){var k={method:a},l="";"spellcheck"==a&&(k.text=d,k.lang=F.spellchecker_language),"addToDictionary"==a&&(k.word=d),c.each(k,function(a,b){l&&(l+="&"),l+=b+"="+encodeURIComponent(a)}),f.send({url:new g(i).toAbsolute(F.spellchecker_rpc_url),type:"post",content_type:"application/x-www-form-urlencoded",data:l,success:function(a){if(a=h.parse(a))a.error?j(a.error):e(a);else{var c=b.translate("Server response wasn't proper JSON.");j(c)}},error:function(){var a=b.translate("The spelling service was not found: (")+F.spellchecker_rpc_url+b.translate(")");j(a)}})}function p(a,b,c,d){var e=F.spellchecker_callback||o;e.call(E,a,b,c,d)}function q(){function a(a){b.notificationManager.open({text:a,type:"error"}),b.setProgressState(!1),u()}u()||(b.setProgressState(!0),p("spellcheck",j().text,y,a),b.focus())}function r(){b.dom.select("span.mce-spellchecker-word").length||u()}function s(a,c){b.setProgressState(!0),p("addToDictionary",a,function(){b.setProgressState(!1),b.dom.remove(c,!0),r()},function(a){b.notificationManager.open({text:a,type:"error"}),b.setProgressState(!1)})}function t(a,d,e){b.selection.collapse(),e?c.each(b.dom.select("span.mce-spellchecker-word"),function(c){c.getAttribute("data-mce-word")==a&&b.dom.remove(c,!0)}):b.dom.remove(d,!0),r()}function u(){return j().reset(),E.textMatcher=null,B?(B=!1,b.fire("SpellcheckEnd"),!0):void 0}function v(a){var b=a.getAttribute("data-mce-index");return"number"==typeof b?""+b:b}function w(a){var d,e=[];if(d=c.toArray(b.getBody().getElementsByTagName("span")),d.length)for(var f=0;f0){var e=b.dom.createRng();e.setStartBefore(d[0]),e.setEndAfter(d[d.length-1]),b.selection.setRng(e),m(c.getAttribute("data-mce-word"),d)}}}),b.addMenuItem("spellchecker",{text:"Spellcheck",context:"tools",onclick:q,selectable:!0,onPostRender:function(){var a=this;a.active(B),b.on("SpellcheckStart SpellcheckEnd",function(){a.active(B)})}});var H={tooltip:"Spellcheck",onclick:q,onPostRender:function(){var a=this;b.on("SpellcheckStart SpellcheckEnd",function(){a.active(B)})}};z.length>1&&(H.type="splitbutton",H.menu=z,H.onshow=x,H.onselect=function(a){F.spellchecker_language=a.control.settings.data}),b.addButton("spellchecker",H),b.addCommand("mceSpellCheck",q),b.on("remove",function(){C&&(C.remove(),C=null)}),b.on("change",r),this.getTextMatcher=j,this.getWordCharPattern=n,this.markErrors=y,this.getLanguage=function(){return F.spellchecker_language},F.spellchecker_language=F.spellchecker_language||F.language||"en"})}),f(["tinymce/spellcheckerplugin/DomTextMatcher"])}(this); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/tabfocus/plugin.min.js b/assets/js/tinymce/plugins/tabfocus/plugin.min.js new file mode 100644 index 0000000..df420ac --- /dev/null +++ b/assets/js/tinymce/plugins/tabfocus/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("tabfocus",function(a){function b(a){9!==a.keyCode||a.ctrlKey||a.altKey||a.metaKey||a.preventDefault()}function c(b){function c(c){function f(a){return"BODY"===a.nodeName||"hidden"!=a.type&&"none"!=a.style.display&&"hidden"!=a.style.visibility&&f(a.parentNode)}function i(a){return/INPUT|TEXTAREA|BUTTON/.test(a.tagName)&&tinymce.get(b.id)&&-1!=a.tabIndex&&f(a)}if(h=d.select(":input:enabled,*[tabindex]:not(iframe)"),e(h,function(b,c){return b.id==a.id?(g=c,!1):void 0}),c>0){for(j=g+1;j=0;j--)if(i(h[j]))return h[j];return null}var g,h,i,j;if(!(9!==b.keyCode||b.ctrlKey||b.altKey||b.metaKey||b.isDefaultPrevented())&&(i=f(a.getParam("tab_focus",a.getParam("tabfocus_elements",":prev,:next"))),1==i.length&&(i[1]=i[0],i[0]=":prev"),h=b.shiftKey?":prev"==i[0]?c(-1):d.get(i[0]):":next"==i[1]?c(1):d.get(i[1]))){var k=tinymce.get(h.id||h.name);h.id&&k?k.focus():tinymce.util.Delay.setTimeout(function(){tinymce.Env.webkit||window.focus(),h.focus()},10),b.preventDefault()}}var d=tinymce.DOM,e=tinymce.each,f=tinymce.explode;a.on("init",function(){a.inline&&tinymce.DOM.setAttrib(a.getBody(),"tabIndex",null),a.on("keyup",b),tinymce.Env.gecko?a.on("keypress keydown",c):a.on("keydown",c)})}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/table/plugin.min.js b/assets/js/tinymce/plugins/table/plugin.min.js new file mode 100644 index 0000000..baff637 --- /dev/null +++ b/assets/js/tinymce/plugins/table/plugin.min.js @@ -0,0 +1,2 @@ +!function(a,b){"use strict";function c(a,b){for(var c,d=[],g=0;g10)&&(b.innerHTML='
    ')}return{getSpanVal:b,paddCell:c}}),d("tinymce/tableplugin/TableGrid",["tinymce/util/Tools","tinymce/Env","tinymce/tableplugin/Utils"],function(a,c,d){var e=a.each,f=d.getSpanVal;return function(g,h){function i(a){return a===g.getBody()}function j(){var a=0;J=[],K=0,e(["thead","tbody","tfoot"],function(b){var c=P.select("> "+b+" tr",h);e(c,function(c,d){d+=a,e(P.select("> td, > th",c),function(a,c){var e,g,h,i;if(J[d])for(;J[d][c];)c++;for(h=f(a,"rowspan"),i=f(a,"colspan"),g=d;d+h>g;g++)for(J[g]||(J[g]=[]),e=c;c+i>e;e++)J[g][e]={part:b,real:g==d&&e==c,elm:a,rowspan:h,colspan:i};K=Math.max(K,c+1)})}),a+=c.length})}function k(a,b){return a=a.cloneNode(b),a.removeAttribute("id"),a}function l(a,b){var c;return c=J[b],c?c[a]:void 0}function m(a,b,c){a&&(c=parseInt(c,10),1===c?a.removeAttribute(b,1):a.setAttribute(b,c,1))}function n(a){return a&&(P.hasClass(a.elm,"mce-item-selected")||a==N)}function o(){var a=[];return e(h.rows,function(b){e(b.cells,function(c){return P.hasClass(c,"mce-item-selected")||N&&c==N.elm?(a.push(b),!1):void 0})}),a}function p(){var a=P.createRng();i(h)||(a.setStartAfter(h),a.setEndAfter(h),O.setRng(a),P.remove(h))}function q(b){var f,h={};return g.settings.table_clone_elements!==!1&&(h=a.makeMap((g.settings.table_clone_elements||"strong em b i span font h1 h2 h3 h4 h5 h6 p div").toUpperCase(),/[ ,]/)),a.walk(b,function(a){var d;return 3==a.nodeType?(e(P.getParents(a.parentNode,null,b).reverse(),function(a){h[a.nodeName]&&(a=k(a,!1),f?d&&d.appendChild(a):f=d=a,d=a)}),d&&(d.innerHTML=c.ie?" ":'
    '),!1):void 0},"childNodes"),b=k(b,!1),m(b,"rowSpan",1),m(b,"colSpan",1),f?b.appendChild(f):d.paddCell(b),b}function r(){var a,b=P.createRng();return e(P.select("tr",h),function(a){0===a.cells.length&&P.remove(a)}),0===P.select("tr",h).length?(b.setStartBefore(h),b.setEndBefore(h),O.setRng(b),void P.remove(h)):(e(P.select("thead,tbody,tfoot",h),function(a){0===a.rows.length&&P.remove(a)}),j(),void(L&&(a=J[Math.min(J.length-1,L.y)],a&&(O.select(a[Math.min(a.length-1,L.x)].elm,!0),O.collapse(!0)))))}function s(a,b,c,d){var e,f,g,h,i;for(e=J[b][a].elm.parentNode,g=1;c>=g;g++)if(e=P.getNext(e,"tr")){for(f=a;f>=0;f--)if(i=J[b+g][f].elm,i.parentNode==e){for(h=1;d>=h;h++)P.insertAfter(q(i),i);break}if(-1==f)for(h=1;d>=h;h++)e.insertBefore(q(e.cells[0]),e.cells[0])}}function t(){e(J,function(a,b){e(a,function(a,c){var d,e,g;if(n(a)&&(a=a.elm,d=f(a,"colspan"),e=f(a,"rowspan"),d>1||e>1)){for(m(a,"rowSpan",1),m(a,"colSpan",1),g=0;d-1>g;g++)P.insertAfter(q(a),a);s(c,b,e-1,d)}})})}function u(b,c,d){var f,g,h,i,k,o,p,q,s,u,v;if(b?(f=E(b),g=f.x,h=f.y,i=g+(c-1),k=h+(d-1)):(L=M=null,e(J,function(a,b){e(a,function(a,c){n(a)&&(L||(L={x:c,y:b}),M={x:c,y:b})})}),L&&(g=L.x,h=L.y,i=M.x,k=M.y)),q=l(g,h),s=l(i,k),q&&s&&q.part==s.part){for(t(),j(),q=l(g,h).elm,m(q,"colSpan",i-g+1),m(q,"rowSpan",k-h+1),p=h;k>=p;p++)for(o=g;i>=o;o++)J[p]&&J[p][o]&&(b=J[p][o].elm,b!=q&&(u=a.grep(b.childNodes),e(u,function(a){q.appendChild(a)}),u.length&&(u=a.grep(q.childNodes),v=0,e(u,function(a){"BR"==a.nodeName&&P.getAttrib(a,"data-mce-bogus")&&v++0&&J[c-1][h]&&(o=J[c-1][h].elm,p=f(o,"rowSpan"),p>1)){m(o,"rowSpan",p+1);continue}}else if(p=f(d,"rowspan"),p>1){m(d,"rowSpan",p+1);continue}l=q(d),m(l,"colSpan",d.colSpan),j.appendChild(l),g=d}j.hasChildNodes()&&(a?i.parentNode.insertBefore(j,i):P.insertAfter(j,i))}}function w(a){var b,c;e(J,function(c){return e(c,function(c,d){return n(c)&&(b=d,a)?!1:void 0}),a?!b:void 0}),e(J,function(d,e){var g,h,i;d[b]&&(g=d[b].elm,g!=c&&(i=f(g,"colspan"),h=f(g,"rowspan"),1==i?a?(g.parentNode.insertBefore(q(g),g),s(b,e,h-1,i)):(P.insertAfter(q(g),g),s(b,e,h-1,i)):m(g,"colSpan",g.colSpan+1),c=g))})}function x(b){return a.grep(y(b),n)}function y(a){var b=[];return e(a,function(a){e(a,function(a){b.push(a)})}),b}function z(){var b=[];if(i(h)){if(1==J[0].length)return;if(x(J).length==y(J).length)return}e(J,function(c){e(c,function(c,d){n(c)&&-1===a.inArray(b,d)&&(e(J,function(a){var b,c=a[d].elm;b=f(c,"colSpan"),b>1?m(c,"colSpan",b-1):P.remove(c)}),b.push(d))})}),r()}function A(){function a(a){var b,c;e(a.cells,function(a){var c=f(a,"rowSpan");c>1&&(m(a,"rowSpan",c-1),b=E(a),s(b.x,b.y,1,1))}),b=E(a.cells[0]),e(J[b.y],function(a){var b;a=a.elm,a!=c&&(b=f(a,"rowSpan"),1>=b?P.remove(a):m(a,"rowSpan",b-1),c=a)})}var b;b=o(),i(h)&&b.length==h.rows.length||(e(b.reverse(),function(b){a(b)}),r())}function B(){var a=o();if(!i(h)||a.length!=h.rows.length)return P.remove(a),r(),a}function C(){var a=o();return e(a,function(b,c){a[c]=k(b,!0)}),a}function D(a,b){var c=o(),d=c[b?0:c.length-1],f=d.cells.length;a&&(e(J,function(a){var b;return f=0,e(a,function(a){a.real&&(f+=a.colspan),a.elm.parentNode==d&&(b=1)}),b?!1:void 0}),b||a.reverse(),e(a,function(a){var c,e,g=a.cells.length;for(c=0;g>c;c++)e=a.cells[c],m(e,"colSpan",1),m(e,"rowSpan",1);for(c=g;f>c;c++)a.appendChild(q(a.cells[g-1]));for(c=f;g>c;c++)P.remove(a.cells[c]);b?d.parentNode.insertBefore(a,d):P.insertAfter(a,d)}),P.removeClass(P.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"))}function E(a){var b;return e(J,function(c,d){return e(c,function(c,e){return c.elm==a?(b={x:e,y:d},!1):void 0}),!b}),b}function F(a){L=E(a)}function G(){var a,b;return a=b=0,e(J,function(c,d){e(c,function(c,e){var f,g;n(c)&&(c=J[d][e],e>a&&(a=e),d>b&&(b=d),c.real&&(f=c.colspan-1,g=c.rowspan-1,f&&e+f>a&&(a=e+f),g&&d+g>b&&(b=d+g)))})}),{x:a,y:b}}function H(a){var b,c,d,e,f,g,h,i,j,k;if(M=E(a),L&&M){for(b=Math.min(L.x,M.x),c=Math.min(L.y,M.y),d=Math.max(L.x,M.x),e=Math.max(L.y,M.y),f=d,g=e,k=c;g>=k;k++)a=J[k][b],a.real||b-(a.colspan-1)=j;j++)a=J[c][j],a.real||c-(a.rowspan-1)=k;k++)for(j=b;d>=j;j++)a=J[k][j],a.real&&(h=a.colspan-1,i=a.rowspan-1,h&&j+h>f&&(f=j+h),i&&k+i>g&&(g=k+i));for(P.removeClass(P.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),k=c;g>=k;k++)for(j=b;f>=j;j++)J[k][j]&&P.addClass(J[k][j].elm,"mce-item-selected")}}function I(a,b){var c,d,e;c=E(a),d=c.y*K+c.x;do{if(d+=b,e=l(d%K,Math.floor(d/K)),!e)break;if(e.elm!=a)return O.select(e.elm,!0),P.isEmpty(e.elm)&&O.collapse(!0),!0}while(e.elm==a);return!1}var J,K,L,M,N,O=g.selection,P=O.dom;h=h||P.getParent(O.getStart(!0),"table"),j(),N=P.getParent(O.getStart(!0),"th,td"),N&&(L=E(N),M=G(),N=l(L.x,L.y)),a.extend(this,{deleteTable:p,split:t,merge:u,insertRow:v,insertCol:w,deleteCols:z,deleteRows:A,cutRows:B,copyRows:C,pasteRows:D,getPos:E,setStartCell:F,setEndCell:H,moveRelIdx:I,refresh:j})}}),d("tinymce/tableplugin/Quirks",["tinymce/util/VK","tinymce/util/Delay","tinymce/Env","tinymce/util/Tools","tinymce/tableplugin/Utils"],function(a,b,c,d,e){var f=d.each,g=e.getSpanVal;return function(h){function i(){function c(c){function d(a,b){var d=a?"previousSibling":"nextSibling",f=h.dom.getParent(b,"tr"),g=f[d];if(g)return r(h,b,g,a),c.preventDefault(),!0;var i=h.dom.getParent(f,"table"),l=f.parentNode,m=l.nodeName.toLowerCase();if("tbody"===m||m===(a?"tfoot":"thead")){var n=e(a,i,l,"tbody");if(null!==n)return j(a,n,b)}return k(a,f,d,i)}function e(a,b,c,d){var e=h.dom.select(">"+d,b),f=e.indexOf(c);if(a&&0===f||!a&&f===e.length-1)return i(a,b);if(-1===f){var g="thead"===c.tagName.toLowerCase()?0:e.length-1;return e[g]}return e[f+(a?-1:1)]}function i(a,b){var c=a?"thead":"tfoot",d=h.dom.select(">"+c,b);return 0!==d.length?d[0]:null}function j(a,b,d){var e=l(b,a);return e&&r(h,d,e,a),c.preventDefault(),!0}function k(a,b,e,f){var g=f[e];if(g)return m(g),!0;var i=h.dom.getParent(f,"td,th");if(i)return d(a,i,c);var j=l(b,!a);return m(j),c.preventDefault(),!1}function l(a,b){var c=a&&a[b?"lastChild":"firstChild"];return c&&"BR"===c.nodeName?h.dom.getParent(c,"td,th"):c}function m(a){h.selection.setCursorLocation(a,0)}function n(){return u==a.UP||u==a.DOWN}function o(a){var b=a.selection.getNode(),c=a.dom.getParent(b,"tr");return null!==c}function p(a){for(var b=0,c=a;c.previousSibling;)c=c.previousSibling,b+=g(c,"colspan");return b}function q(a,b){var c=0,d=0;return f(a.children,function(a,e){return c+=g(a,"colspan"),d=e,c>b?!1:void 0}),d}function r(a,b,c,d){var e=p(h.dom.getParent(b,"td,th")),f=q(c,e),g=c.childNodes[f],i=l(g,d);m(i||g)}function s(a){var b=h.selection.getNode(),c=h.dom.getParent(b,"td,th"),d=h.dom.getParent(a,"td,th");return c&&c!==d&&t(c,d)}function t(a,b){return h.dom.getParent(a,"TABLE")===h.dom.getParent(b,"TABLE")}var u=c.keyCode;if(n()&&o(h)){var v=h.selection.getNode();b.setEditorTimeout(h,function(){s(v)&&d(!c.shiftKey&&u===a.UP,v,c)},0)}}h.on("KeyDown",function(a){c(a)})}function j(){function a(a,b){var c,d=b.ownerDocument,e=d.createRange();return e.setStartBefore(b),e.setEnd(a.endContainer,a.endOffset),c=d.createElement("body"),c.appendChild(e.cloneContents()),0===c.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length}h.on("KeyDown",function(b){var c,d,e=h.dom;(37==b.keyCode||38==b.keyCode)&&(c=h.selection.getRng(),d=e.getParent(c.startContainer,"table"),d&&h.getBody().firstChild==d&&a(c,d)&&(c=e.createRng(),c.setStartBefore(d),c.setEndBefore(d),h.selection.setRng(c),b.preventDefault()))})}function k(){h.on("KeyDown SetContent VisualAid",function(){var a;for(a=h.getBody().lastChild;a;a=a.previousSibling)if(3==a.nodeType){if(a.nodeValue.length>0)break}else if(1==a.nodeType&&("BR"==a.tagName||!a.getAttribute("data-mce-bogus")))break;a&&"TABLE"==a.nodeName&&(h.settings.forced_root_block?h.dom.add(h.getBody(),h.settings.forced_root_block,h.settings.forced_root_block_attrs,c.ie&&c.ie<11?" ":'
    '):h.dom.add(h.getBody(),"br",{"data-mce-bogus":"1"}))}),h.on("PreProcess",function(a){var b=a.node.lastChild;b&&("BR"==b.nodeName||1==b.childNodes.length&&("BR"==b.firstChild.nodeName||"\xa0"==b.firstChild.nodeValue))&&b.previousSibling&&"TABLE"==b.previousSibling.nodeName&&h.dom.remove(b)})}function l(){function a(a,b,c,d){var e,f,g,h=3,i=a.dom.getParent(b.startContainer,"TABLE");return i&&(e=i.parentNode),f=b.startContainer.nodeType==h&&0===b.startOffset&&0===b.endOffset&&d&&("TR"==c.nodeName||c==e),g=("TD"==c.nodeName||"TH"==c.nodeName)&&!d,f||g}function b(){var b=h.selection.getRng(),c=h.selection.getNode(),d=h.dom.getParent(b.startContainer,"TD,TH");if(a(h,b,c,d)){d||(d=c);for(var e=d.lastChild;e.lastChild;)e=e.lastChild;3==e.nodeType&&(b.setEnd(e,e.data.length),h.selection.setRng(b))}}h.on("KeyDown",function(){b()}),h.on("MouseDown",function(a){2!=a.button&&b()})}function m(){function b(a){h.selection.select(a,!0),h.selection.collapse(!0)}function c(a){h.$(a).empty(),e.paddCell(a)}h.on("keydown",function(e){if((e.keyCode==a.DELETE||e.keyCode==a.BACKSPACE)&&!e.isDefaultPrevented()){var f,g,i,j;if(f=h.dom.getParent(h.selection.getStart(),"table")){if(g=h.dom.select("td,th",f),i=d.grep(g,function(a){return h.dom.hasClass(a,"mce-item-selected")}),0===i.length)return j=h.dom.getParent(h.selection.getStart(),"td,th"),void(h.selection.isCollapsed()&&j&&h.dom.isEmpty(j)&&(e.preventDefault(),c(j),b(j)));e.preventDefault(),h.undoManager.transact(function(){g.length==i.length?h.execCommand("mceTableDelete"):(d.each(i,c),b(i[0]))})}}})}m(),c.webkit&&(i(),l()),c.gecko&&(j(),k()),c.ie>10&&(j(),k())}}),d("tinymce/tableplugin/CellSelection",["tinymce/tableplugin/TableGrid","tinymce/dom/TreeWalker","tinymce/util/Tools"],function(a,b,c){return function(d){function e(a){d.getBody().style.webkitUserSelect="",(a||l)&&(d.dom.removeClass(d.dom.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),l=!1)}function f(b){var c,e,f=b.target;if(!j&&h&&(g||f!=h)&&("TD"==f.nodeName||"TH"==f.nodeName)){e=k.getParent(f,"table"),e==i&&(g||(g=new a(d,e),g.setStartCell(h),d.getBody().style.webkitUserSelect="none"),g.setEndCell(f),l=!0),c=d.selection.getSel();try{c.removeAllRanges?c.removeAllRanges():c.empty()}catch(m){}b.preventDefault()}}var g,h,i,j,k=d.dom,l=!0;return d.on("MouseDown",function(a){2==a.button||j||(e(),h=k.getParent(a.target,"td,th"),i=k.getParent(h,"table"))}),d.on("mouseover",f),d.on("remove",function(){k.unbind(d.getDoc(),"mouseover",f)}),d.on("MouseUp",function(){function a(a,d){var f=new b(a,a);do{if(3==a.nodeType&&0!==c.trim(a.nodeValue).length)return void(d?e.setStart(a,0):e.setEnd(a,a.nodeValue.length));if("BR"==a.nodeName)return void(d?e.setStartBefore(a):e.setEndBefore(a))}while(a=d?f.next():f.prev())}var e,f,j,l,m,n=d.selection;if(h){if(g&&(d.getBody().style.webkitUserSelect=""),f=k.select("td.mce-item-selected,th.mce-item-selected"),f.length>0){e=k.createRng(),l=f[0],e.setStartBefore(l),e.setEndAfter(l),a(l,1),j=new b(l,k.getParent(f[0],"table"));do if("TD"==l.nodeName||"TH"==l.nodeName){if(!k.hasClass(l,"mce-item-selected"))break;m=l}while(l=j.next());a(m),n.setRng(e)}d.nodeChanged(),h=g=i=null}}),d.on("KeyUp Drop SetContent",function(a){e("setcontent"==a.type),h=g=i=null,j=!1}),d.on("ObjectResizeStart ObjectResized",function(a){j="objectresized"!=a.type}),{clear:e}}}),d("tinymce/tableplugin/Dialogs",["tinymce/util/Tools","tinymce/Env"],function(a,b){var c=a.each;return function(d){function e(){var a=d.settings.color_picker_callback;return a?function(){var b=this;a.call(d,function(a){b.value(a).fire("change")},b.value())}:void 0}function f(a){return{title:"Advanced",type:"form",defaults:{onchange:function(){l(a,this.parents().reverse()[0],"style"==this.name())}},items:[{label:"Style",name:"style",type:"textbox"},{type:"form",padding:0,formItemDefaults:{layout:"grid",alignH:["start","right"]},defaults:{size:7},items:[{label:"Border color",type:"colorbox",name:"borderColor",onaction:e()},{label:"Background color",type:"colorbox",name:"backgroundColor",onaction:e()}]}]}}function g(a){return a?a.replace(/px$/,""):""}function h(a){return/^[0-9]+$/.test(a)&&(a+="px"),a}function i(a){c("left center right".split(" "),function(b){d.formatter.remove("align"+b,{},a)})}function j(a){c("top middle bottom".split(" "),function(b){d.formatter.remove("valign"+b,{},a)})}function k(b,c,d){function e(b,d){return d=d||[],a.each(b,function(a){var b={text:a.text||a.title};a.menu?b.menu=e(a.menu):(b.value=a.value,c&&c(b)),d.push(b)}),d}return e(b,d||[])}function l(a,b,c){var d=b.toJSON(),e=a.parseStyle(d.style);c?(b.find("#borderColor").value(e["border-color"]||"")[0].fire("change"),b.find("#backgroundColor").value(e["background-color"]||"")[0].fire("change")):(e["border-color"]=d.borderColor,e["background-color"]=d.backgroundColor),b.find("#style").value(a.serializeStyle(a.parseStyle(a.serializeStyle(e))))}function m(a,b,c){var d=a.parseStyle(a.getAttrib(c,"style"));d["border-color"]&&(b.borderColor=d["border-color"]),d["background-color"]&&(b.backgroundColor=d["background-color"]),b.style=a.serializeStyle(d)}function n(a,b,d){var e=a.parseStyle(a.getAttrib(b,"style"));c(d,function(a){e[a.name]=a.value}),a.setAttrib(b,"style",a.serializeStyle(a.parseStyle(a.serializeStyle(e))))}var o=this;o.tableProps=function(){o.table(!0)},o.table=function(e){function j(){function c(a,b,d){if("TD"===a.tagName||"TH"===a.tagName)v.setStyle(a,b,d);else if(a.children)for(var e=0;e',p.insertBefore(e,p.firstChild)),i(p),w.align&&d.formatter.apply("align"+w.align,{},p),d.focus(),d.addVisual()})}function o(a,b){function c(a,c){for(var d=0;dd;d++)c.push(d);return c}function A(a,b,c){for(var d,e=a(),f=0;f0?r(d,e,g):[],m=h.length>0?r(k,l,h):[];v(j,a.offsetWidth,i),w(m,a.offsetHeight,i)}function E(a,b,c,d){if(0>b||b>=a.length-1)return"";var e=a[b];if(e)e={value:e,delta:0};else for(var f=a.slice(0,b).reverse(),g=0;g0?e:f}function H(b,c,d){for(var e=B(b),f=a.map(e,function(a){return k(a.colIndex,a.element).x}),g=[],h=0;h1?E(f,h):G(e[h].element,c,d);j=j?j:ua,g.push(j)}return g}function I(a){var b=F(a,"height"),c=parseInt(b,10);return P(b)&&(c=0),!isNaN(c)&&c>0?c:n(a,"height")}function J(b){for(var c=C(b),e=a.map(c,function(a){return d(a.rowIndex,a.element).y}),f=[],g=0;g1?E(e,g):I(c[g].element);i=i?i:va,f.push(i)}return f}function K(b,c,d,e,f){function g(b){return a.map(b,function(){return 0})}function h(){var a;if(f)a=[100-l[0]];else{var b=Math.max(e,l[0]+d);a=[b-l[0]]}return a}function i(a,b){var c,f=g(l.slice(0,a)),h=g(l.slice(b+1));if(d>=0){var i=Math.max(e,l[b]-d);c=f.concat([d,i-l[b]]).concat(h)}else{var j=Math.max(e,l[a]+d),k=l[a]-j;c=f.concat([j-l[a],k]).concat(h)}return c}function j(a,b){var c,f=g(l.slice(0,b));if(d>=0)c=f.concat([d]);else{var h=Math.max(e,l[b]+d);c=f.concat([h-l[b]])}return c}var k,l=b.slice(0);return k=0===b.length?[]:1===b.length?h():0===c?i(0,1):c>0&&ce;e++)d+=c[e];return d}function M(b,c){var d=b.getAllCells();return a.map(d,function(a){var b=L(a.colIndex,a.colIndex+a.colspan,c);return{element:a.element,width:b,colspan:a.colspan}})}function N(b,c){var d=b.getAllCells();return a.map(d,function(a){var b=L(a.rowIndex,a.rowIndex+a.rowspan,c);return{element:a.element,height:b,rowspan:a.rowspan}})}function O(b,c){var d=b.getAllRows();return a.map(d,function(a,b){return{element:a.element,height:c[b]}})}function P(a){return xa.test(a)}function Q(a){return ya.test(a)}function R(b,d,e){function f(b,d){a.each(b,function(a){c.dom.setStyle(a.element,"width",a.width+d),c.dom.setAttrib(a.element,"width",null)})}function g(){return ec;c++){for(e+="
    ",d=0;a>d;d++)e+="";e+=""}return e+="
    "+(h.ie?" ":"
    ")+"
    ",f.undoManager.transact(function(){f.insertContent(e),g=f.dom.get("__mce"),f.dom.setAttrib(g,"id",null),f.dom.setAttribs(g,f.settings.table_default_attributes||{}),f.dom.setStyles(g,f.settings.table_default_styles||{})}),g}function j(a,b){function c(){a.disabled(!f.dom.getParent(f.selection.getStart(),b)),f.selection.selectorChanged(b,function(b){a.disabled(!b)})}f.initialized?c():f.on("init",c)}function l(){j(this,"table")}function m(){j(this,"td,th")}function n(){var a="";a='';for(var b=0;10>b;b++){a+="";for(var c=0;10>c;c++)a+='';a+=""}return a+="
    ",a+=''}function o(a,b,c){var d,e,g,h,i,j=c.getEl().getElementsByTagName("table")[0],k=c.isRtl()||"tl-tr"==c.parent().rel;for(j.nextSibling.innerHTML=a+1+" x "+(b+1),k&&(a=9-a),e=0;10>e;e++)for(d=0;10>d;d++)h=j.rows[e].childNodes[d].firstChild,i=(k?d>=a:a>=d)&&b>=e,f.dom.toggleClass(h,"mce-active",i),i&&(g=h);return g.parentNode}function p(){f.addButton("tableprops",{title:"Table properties",onclick:u.tableProps,icon:"table"}),f.addButton("tabledelete",{title:"Delete table",onclick:g("mceTableDelete")}),f.addButton("tablecellprops",{title:"Cell properties",onclick:g("mceTableCellProps")}),f.addButton("tablemergecells",{title:"Merge cells",onclick:g("mceTableMergeCells")}),f.addButton("tablesplitcells",{title:"Split cell",onclick:g("mceTableSplitCells")}),f.addButton("tableinsertrowbefore",{title:"Insert row before",onclick:g("mceTableInsertRowBefore")}),f.addButton("tableinsertrowafter",{title:"Insert row after",onclick:g("mceTableInsertRowAfter")}),f.addButton("tabledeleterow",{title:"Delete row",onclick:g("mceTableDeleteRow")}),f.addButton("tablerowprops",{title:"Row properties",onclick:g("mceTableRowProps")}),f.addButton("tablecutrow",{title:"Cut row",onclick:g("mceTableCutRow")}),f.addButton("tablecopyrow",{title:"Copy row",onclick:g("mceTableCopyRow")}),f.addButton("tablepasterowbefore",{title:"Paste row before",onclick:g("mceTablePasteRowBefore")}),f.addButton("tablepasterowafter",{title:"Paste row after",onclick:g("mceTablePasteRowAfter")}),f.addButton("tableinsertcolbefore",{title:"Insert column before",onclick:g("mceTableInsertColBefore")}),f.addButton("tableinsertcolafter",{title:"Insert column after",onclick:g("mceTableInsertColAfter")}),f.addButton("tabledeletecol",{title:"Delete column",onclick:g("mceTableDeleteCol")})}function q(a){var b=f.dom.is(a,"table");return b}function r(){var a=f.settings.table_toolbar;""!==a&&a!==!1&&(a||(a="tableprops tabledelete | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol"),f.addContextToolbar(q,a))}var s,t=this,u=new d(f),v=e(f);f.settings.table_grid===!1?f.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",onclick:u.table}):f.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",ariaHideMenu:!0,onclick:function(a){a.aria&&(this.parent().hideAll(),a.stopImmediatePropagation(),u.table())},onshow:function(){o(0,0,this.menu.items()[0])},onhide:function(){var a=this.menu.items()[0].getEl().getElementsByTagName("a");f.dom.removeClass(a,"mce-active"),f.dom.addClass(a[0],"mce-active")},menu:[{type:"container",html:n(),onPostRender:function(){this.lastX=this.lastY=0},onmousemove:function(a){var b,c,d=a.target;"A"==d.tagName.toUpperCase()&&(b=parseInt(d.getAttribute("data-mce-x"),10),c=parseInt(d.getAttribute("data-mce-y"),10),(this.isRtl()||"tl-tr"==this.parent().rel)&&(b=9-b),(b!==this.lastX||c!==this.lastY)&&(o(b,c,a.control),this.lastX=b,this.lastY=c))},onclick:function(a){var b=this;"A"==a.target.tagName.toUpperCase()&&(a.preventDefault(),a.stopPropagation(),b.parent().cancel(),f.undoManager.transact(function(){i(b.lastX+1,b.lastY+1)}),f.addVisual())}}]}),f.addMenuItem("tableprops",{text:"Table properties",context:"table",onPostRender:l,onclick:u.tableProps}),f.addMenuItem("deletetable",{text:"Delete table",context:"table",onPostRender:l,cmd:"mceTableDelete"}),f.addMenuItem("cell",{separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:g("mceTableCellProps"),onPostRender:m},{text:"Merge cells",onclick:g("mceTableMergeCells"),onPostRender:m},{text:"Split cell",onclick:g("mceTableSplitCells"),onPostRender:m}]}),f.addMenuItem("row",{text:"Row",context:"table",menu:[{text:"Insert row before",onclick:g("mceTableInsertRowBefore"),onPostRender:m},{text:"Insert row after",onclick:g("mceTableInsertRowAfter"),onPostRender:m},{text:"Delete row",onclick:g("mceTableDeleteRow"),onPostRender:m},{text:"Row properties",onclick:g("mceTableRowProps"),onPostRender:m},{text:"-"},{text:"Cut row",onclick:g("mceTableCutRow"),onPostRender:m},{text:"Copy row",onclick:g("mceTableCopyRow"),onPostRender:m},{text:"Paste row before",onclick:g("mceTablePasteRowBefore"),onPostRender:m},{text:"Paste row after",onclick:g("mceTablePasteRowAfter"),onPostRender:m}]}),f.addMenuItem("column",{text:"Column",context:"table",menu:[{text:"Insert column before",onclick:g("mceTableInsertColBefore"),onPostRender:m},{text:"Insert column after",onclick:g("mceTableInsertColAfter"),onPostRender:m},{text:"Delete column",onclick:g("mceTableDeleteCol"),onPostRender:m}]});var w=[];k("inserttable tableprops deletetable | cell row column".split(" "),function(a){"|"==a?w.push({text:"-"}):w.push(f.menuItems[a])}),f.addButton("table",{type:"menubutton",title:"Table",menu:w}),h.isIE||f.on("click",function(a){a=a.target,"TABLE"===a.nodeName&&(f.selection.select(a),f.nodeChanged())}),t.quirks=new b(f),f.on("Init",function(){t.cellSelection=new c(f),t.resizeBars=v}),f.on("PreInit",function(){f.serializer.addAttributeFilter("data-mce-cell-padding,data-mce-border,data-mce-border-color",function(a,b){for(var c=a.length;c--;)a[c].attr(b,null)})}),k({mceTableSplitCells:function(a){a.split()},mceTableMergeCells:function(a){var b;b=f.dom.getParent(f.selection.getStart(),"th,td"),f.dom.select("td.mce-item-selected,th.mce-item-selected").length?a.merge():u.merge(a,b)},mceTableInsertRowBefore:function(a){a.insertRow(!0)},mceTableInsertRowAfter:function(a){a.insertRow()},mceTableInsertColBefore:function(a){a.insertCol(!0)},mceTableInsertColAfter:function(a){a.insertCol()},mceTableDeleteCol:function(a){a.deleteCols()},mceTableDeleteRow:function(a){a.deleteRows()},mceTableCutRow:function(a){s=a.cutRows()},mceTableCopyRow:function(a){s=a.copyRows()},mceTablePasteRowBefore:function(a){a.pasteRows(s,!0)},mceTablePasteRowAfter:function(a){a.pasteRows(s)},mceTableDelete:function(a){v.clearBars(),a.deleteTable()}},function(b,c){f.addCommand(c,function(){var c=new a(f);c&&(b(c),f.execCommand("mceRepaint"),t.cellSelection.clear())})}),k({mceInsertTable:u.table,mceTableProps:function(){u.table(!0)},mceTableRowProps:u.row,mceTableCellProps:u.cell},function(a,b){f.addCommand(b,function(b,c){a(c)})}),p(),r(),f.settings.table_tab_navigation!==!1&&f.on("keydown",function(b){var c,d,e;9==b.keyCode&&(c=f.dom.getParent(f.selection.getStart(),"th,td"),c&&(b.preventDefault(),d=new a(f),e=b.shiftKey?-1:1,f.undoManager.transact(function(){!d.moveRelIdx(c,e)&&e>0&&(d.insertRow(),d.refresh(),d.moveRelIdx(c,e))})))}),t.insertTable=i}var k=f.each;i.add("table",j)})}(this); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/template/plugin.min.js b/assets/js/tinymce/plugins/template/plugin.min.js new file mode 100644 index 0000000..c3d3c69 --- /dev/null +++ b/assets/js/tinymce/plugins/template/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("template",function(a){function b(b){return function(){var c=a.settings.templates;"string"==typeof c?tinymce.util.XHR.send({url:c,success:function(a){b(tinymce.util.JSON.parse(a))}}):b(c)}}function c(b){function c(b){function c(b){if(-1==b.indexOf("")){var c="";tinymce.each(a.contentCSS,function(b){c+=''}),b=""+c+""+b+""}b=f(b,"template_preview_replace_values");var e=d.find("iframe")[0].getEl().contentWindow.document;e.open(),e.write(b),e.close()}var g=b.control.value();g.url?tinymce.util.XHR.send({url:g.url,success:function(a){e=a,c(e)}}):(e=g.content,c(e)),d.find("#description")[0].text(b.control.value().description)}var d,e,h=[];if(!b||0===b.length){var i=a.translate("No templates defined.");return void a.notificationManager.open({text:i,type:"info"})}tinymce.each(b,function(a){h.push({selected:!h.length,text:a.title,value:{url:a.url,content:a.content,description:a.description}})}),d=a.windowManager.open({title:"Insert template",layout:"flex",direction:"column",align:"stretch",padding:15,spacing:10,items:[{type:"form",flex:0,padding:0,items:[{type:"container",label:"Templates",items:{type:"listbox",label:"Templates",name:"template",values:h,onselect:c}}]},{type:"label",name:"description",label:"Description",text:"\xa0"},{type:"iframe",flex:1,border:1}],onsubmit:function(){g(!1,e)},width:a.getParam("template_popup_width",600),height:a.getParam("template_popup_height",500)}),d.find("listbox")[0].fire("select")}function d(b,c){function d(a,b){if(a=""+a,a.length0&&(i=k.create("div",null),i.appendChild(j[0].cloneNode(!0))),h(k.select("*",i),function(b){g(b,a.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))&&(b.innerHTML=d(a.getParam("template_cdate_format",a.getLang("template.cdate_format")))),g(b,a.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(b.innerHTML=d(a.getParam("template_mdate_format",a.getLang("template.mdate_format")))),g(b,a.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))&&(b.innerHTML=l)}),e(i),a.execCommand("mceInsertContent",!1,i.innerHTML),a.addVisual()}var h=tinymce.each;a.addCommand("mceInsertTemplate",g),a.addButton("template",{title:"Insert template",onclick:b(c)}),a.addMenuItem("template",{text:"Insert template",onclick:b(c),context:"insert"}),a.on("PreProcess",function(b){var c=a.dom;h(c.select("div",b.node),function(b){c.hasClass(b,"mceTmpl")&&(h(c.select("*",b),function(b){c.hasClass(b,a.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(b.innerHTML=d(a.getParam("template_mdate_format",a.getLang("template.mdate_format"))))}),e(b))})})}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/textcolor/plugin.min.js b/assets/js/tinymce/plugins/textcolor/plugin.min.js new file mode 100644 index 0000000..7ca105a --- /dev/null +++ b/assets/js/tinymce/plugins/textcolor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("textcolor",function(a){function b(b){var c;return a.dom.getParents(a.selection.getStart(),function(a){var d;(d=a.style["forecolor"==b?"color":"background-color"])&&(c=d)}),c}function c(){var b,c,d=[];for(c=a.settings.textcolor_map||["000000","Black","993300","Burnt orange","333300","Dark olive","003300","Dark green","003366","Dark azure","000080","Navy Blue","333399","Indigo","333333","Very dark gray","800000","Maroon","FF6600","Orange","808000","Olive","008000","Green","008080","Teal","0000FF","Blue","666699","Grayish blue","808080","Gray","FF0000","Red","FF9900","Amber","99CC00","Yellow green","339966","Sea green","33CCCC","Turquoise","3366FF","Royal blue","800080","Purple","999999","Medium gray","FF00FF","Magenta","FFCC00","Gold","FFFF00","Yellow","00FF00","Lime","00FFFF","Aqua","00CCFF","Sky blue","993366","Red violet","FFFFFF","White","FF99CC","Pink","FFCC99","Peach","FFFF99","Light yellow","CCFFCC","Pale green","CCFFFF","Pale cyan","99CCFF","Light sky blue","CC99FF","Plum"],b=0;b
    '+(c?"×":"")+"
    ',g=d.length-1,k=0;j>k;k++){for(f+="",h=0;i>h;h++)l=k*i+h,l>g?f+="":(e=d[l],f+=b(e.color,e.text));f+=""}if(a.settings.color_picker_callback){for(f+='",f+="",h=0;i>h;h++)f+=b("","Custom color");f+=""}return f+="
    "}function e(b,c){a.undoManager.transact(function(){a.focus(),a.formatter.apply(b,{value:c}),a.nodeChanged()})}function f(b){a.undoManager.transact(function(){a.focus(),a.formatter.remove(b,{value:null},null,!0),a.nodeChanged()})}function g(c){function d(a){k.hidePanel(),k.color(a),e(k.settings.format,a)}function g(){k.hidePanel(),k.resetColor(),f(k.settings.format)}function h(a,b){a.style.background=b,a.setAttribute("data-mce-color",b)}var j,k=this.parent();tinymce.DOM.getParent(c.target,".mce-custom-color-btn")&&(k.hidePanel(),a.settings.color_picker_callback.call(a,function(a){var b,c,e,f=k.panel.getEl().getElementsByTagName("table")[0];for(b=tinymce.map(f.rows[f.rows.length-1].childNodes,function(a){return a.firstChild}),e=0;ee;e++)h(b[e],b[e+1].getAttribute("data-mce-color"));h(c,a),d(a)},b(k.settings.format))),j=c.target.getAttribute("data-mce-color"),j?(this.lastId&&document.getElementById(this.lastId).setAttribute("aria-selected",!1),c.target.setAttribute("aria-selected",!0),this.lastId=c.target.id,"transparent"==j?g():d(j)):null!==j&&k.hidePanel()}function h(){var a=this;a._color?e(a.settings.format,a._color):f(a.settings.format)}var i,j;j=a.settings.textcolor_rows||5,i=a.settings.textcolor_cols||8,a.addButton("forecolor",{type:"colorbutton",tooltip:"Text color",format:"forecolor",panel:{role:"application",ariaRemember:!0,html:d,onclick:g},onclick:h}),a.addButton("backcolor",{type:"colorbutton",tooltip:"Background color",format:"hilitecolor",panel:{role:"application",ariaRemember:!0,html:d,onclick:g},onclick:h})}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/textpattern/plugin.min.js b/assets/js/tinymce/plugins/textpattern/plugin.min.js new file mode 100644 index 0000000..8af96cd --- /dev/null +++ b/assets/js/tinymce/plugins/textpattern/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("textpattern",function(a){function b(){return j&&(i.sort(function(a,b){return a.start.length>b.start.length?-1:a.start.length'+a+""}function f(){var a,b="";for(a in n)b+=a;return new RegExp("["+b+"]","g")}function g(){var a,b="";for(a in n)b&&(b+=","),b+="span.mce-"+n[a];return b}var h,i,j,k,l,m,n,o,p=a.getBody(),q=a.selection;if(n={"\xa0":"nbsp","\xad":"shy"},d=!d,e.state=d,a.fire("VisualChars",{state:d}),o=f(),b&&(m=q.getBookmark()),d)for(i=[],tinymce.walk(p,function(a){3==a.nodeType&&a.nodeValue&&o.test(a.nodeValue)&&i.push(a)},"childNodes"),j=0;j=0;j--)a.dom.remove(i[j],1);q.moveToBookmark(m)}function c(){var b=this;a.on("VisualChars",function(a){b.active(a.state)})}var d,e=this;a.addCommand("mceVisualChars",b),a.addButton("visualchars",{title:"Show invisible characters",cmd:"mceVisualChars",onPostRender:c}),a.addMenuItem("visualchars",{text:"Show invisible characters",cmd:"mceVisualChars",onPostRender:c,selectable:!0,context:"view",prependToContext:!0}),a.on("beforegetcontent",function(a){d&&"raw"!=a.format&&!a.draft&&(d=!0,b(!1))})}); \ No newline at end of file diff --git a/assets/js/tinymce/plugins/wordcount/plugin.min.js b/assets/js/tinymce/plugins/wordcount/plugin.min.js new file mode 100644 index 0000000..f20e765 --- /dev/null +++ b/assets/js/tinymce/plugins/wordcount/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("wordcount",function(a){function b(){a.theme.panel.find("#wordcount").text(["Words: {0}",e.getCount()])}var c,d,e=this;c=a.getParam("wordcount_countregex",/[\w\u2019\x27\-\u00C0-\u1FFF]+/g),d=a.getParam("wordcount_cleanregex",/[0-9.(),;:!?%#$?\x27\x22_+=\\\/\-]*/g),a.on("init",function(){var c=a.theme.panel&&a.theme.panel.find("#statusbar")[0];c&&tinymce.util.Delay.setEditorTimeout(a,function(){c.insert({type:"label",name:"wordcount",text:["Words: {0}",e.getCount()],classes:"wordcount",disabled:a.settings.readonly},0),a.on("setcontent beforeaddundo",b),a.on("keyup",function(a){32==a.keyCode&&b()})},0)}),e.getCount=function(){var b=a.getContent({format:"raw"}),e=0;if(b){b=b.replace(/\.\.\./g," "),b=b.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," "),b=b.replace(/(\w+)(&#?[a-z0-9]+;)+(\w+)/i,"$1$3").replace(/&.+?;/g," "),b=b.replace(d,"");var f=b.match(c);f&&(e=f.length)}return e}}); \ No newline at end of file diff --git a/assets/js/tinymce/skins/lightgray/content.inline.min.css b/assets/js/tinymce/skins/lightgray/content.inline.min.css new file mode 100644 index 0000000..3079cc7 --- /dev/null +++ b/assets/js/tinymce/skins/lightgray/content.inline.min.css @@ -0,0 +1,154 @@ +/* Content.Inline.less */ +/* Content.Objects.less */ +.mce-content-body .mce-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + vertical-align: top; + background: transparent; + text-decoration: none; + color: black; + font-family: Arial; + font-size: 11px; + text-shadow: none; + float: none; + position: static; + width: auto; + height: auto; + white-space: nowrap; + cursor: inherit; + line-height: normal; + font-weight: normal; + text-align: left; + -webkit-tap-highlight-color: transparent; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; + direction: ltr; + max-width: none; +} +.mce-object { + border: 1px dotted #3A3A3A; + background: #d5d5d5 url(img/object.gif) no-repeat center; +} +.mce-preview-object { + display: inline-block; + position: relative; + margin: 0 2px 0 2px; + line-height: 0; + border: 1px solid gray; +} +.mce-preview-object .mce-shim { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7); +} +figure.align-left { + float: left; +} +figure.align-right { + float: right; +} +figure.image { + display: inline-block; + border: 1px solid gray; + margin: 0 2px 0 1px; + background: #f5f2f0; +} +figure.image img { + margin: 8px 8px 0 8px; +} +figure.image figcaption { + margin: 6px 8px 6px 8px; + text-align: center; +} +.mce-preview-object[data-mce-selected] .mce-shim { + display: none; +} +.mce-pagebreak { + cursor: default; + display: block; + border: 0; + width: 100%; + height: 5px; + border: 1px dashed #666; + margin-top: 15px; + page-break-before: always; +} +@media print { + .mce-pagebreak { + border: 0px; + } +} +.mce-item-anchor { + cursor: default; + display: inline-block; + -webkit-user-select: all; + -webkit-user-modify: read-only; + -moz-user-select: all; + -moz-user-modify: read-only; + user-select: all; + user-modify: read-only; + width: 9px !important; + height: 9px !important; + border: 1px dotted #3A3A3A; + background: #d5d5d5 url(img/anchor.gif) no-repeat center; +} +.mce-nbsp, +.mce-shy { + background: #AAA; +} +.mce-shy::after { + content: '-'; +} +hr { + cursor: default; +} +.mce-match-marker { + background: #AAA; + color: #fff; +} +.mce-match-marker-selected { + background: #3399ff; + color: #fff; +} +.mce-spellchecker-word { + border-bottom: 2px solid #F00; + cursor: default; +} +.mce-spellchecker-grammar { + border-bottom: 2px solid #008000; + cursor: default; +} +.mce-item-table, +.mce-item-table td, +.mce-item-table th, +.mce-item-table caption { + border: 1px dashed #BBB; +} +td.mce-item-selected, +th.mce-item-selected { + background-color: #3399ff !important; +} +.mce-edit-focus { + outline: 1px dotted #333; +} +.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus { + outline: 2px solid #2d8ac7; +} +.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover { + outline: 2px solid #7ACAFF; +} +.mce-content-body *[contentEditable=false][data-mce-selected] { + outline: 2px solid #2d8ac7; +} +.mce-resize-bar-dragging { + background-color: blue; + opacity: 0.25; + filter: alpha(opacity=25); + zoom: 1; +} diff --git a/assets/js/tinymce/skins/lightgray/content.min.css b/assets/js/tinymce/skins/lightgray/content.min.css new file mode 100644 index 0000000..f12e891 --- /dev/null +++ b/assets/js/tinymce/skins/lightgray/content.min.css @@ -0,0 +1 @@ +body{background-color:#fff;color:#000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px;scrollbar-3dlight-color:#f0f0ee;scrollbar-arrow-color:#676662;scrollbar-base-color:#f0f0ee;scrollbar-darkshadow-color:#ddd;scrollbar-face-color:#e0e0dd;scrollbar-highlight-color:#f0f0ee;scrollbar-shadow-color:#f0f0ee;scrollbar-track-color:#f5f5f5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3a3a3a;background:#d5d5d5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-preview-object[data-mce-selected] .mce-shim{display:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3a3a3a;background:#d5d5d5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#aaa}.mce-shy::after{content:'-'}hr{cursor:default}.mce-match-marker{background:#aaa;color:#fff}.mce-match-marker-selected{background:#39f;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #f00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #bbb}td.mce-item-selected,th.mce-item-selected{background-color:#39f !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2d8ac7}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #7acaff}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2d8ac7}.mce-resize-bar-dragging{background-color:blue;opacity:.25;filter:alpha(opacity=25);zoom:1} \ No newline at end of file diff --git a/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.eot b/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.eot new file mode 100644 index 0000000..b144ba0 Binary files /dev/null and b/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.eot differ diff --git a/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.svg b/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.svg new file mode 100644 index 0000000..a9076ca --- /dev/null +++ b/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.svg @@ -0,0 +1,63 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.ttf b/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.ttf new file mode 100644 index 0000000..a983e2d Binary files /dev/null and b/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.ttf differ diff --git a/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.woff b/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.woff new file mode 100644 index 0000000..d8962df Binary files /dev/null and b/assets/js/tinymce/skins/lightgray/fonts/tinymce-small.woff differ diff --git a/assets/js/tinymce/skins/lightgray/fonts/tinymce.eot b/assets/js/tinymce/skins/lightgray/fonts/tinymce.eot new file mode 100644 index 0000000..8838c8d Binary files /dev/null and b/assets/js/tinymce/skins/lightgray/fonts/tinymce.eot differ diff --git a/assets/js/tinymce/skins/lightgray/fonts/tinymce.svg b/assets/js/tinymce/skins/lightgray/fonts/tinymce.svg new file mode 100644 index 0000000..d7004a9 --- /dev/null +++ b/assets/js/tinymce/skins/lightgray/fonts/tinymce.svg @@ -0,0 +1,98 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/js/tinymce/skins/lightgray/fonts/tinymce.ttf b/assets/js/tinymce/skins/lightgray/fonts/tinymce.ttf new file mode 100644 index 0000000..ab4487f Binary files /dev/null and b/assets/js/tinymce/skins/lightgray/fonts/tinymce.ttf differ diff --git a/assets/js/tinymce/skins/lightgray/fonts/tinymce.woff b/assets/js/tinymce/skins/lightgray/fonts/tinymce.woff new file mode 100644 index 0000000..171a2a2 Binary files /dev/null and b/assets/js/tinymce/skins/lightgray/fonts/tinymce.woff differ diff --git a/assets/js/tinymce/skins/lightgray/img/anchor.gif b/assets/js/tinymce/skins/lightgray/img/anchor.gif new file mode 100644 index 0000000..606348c Binary files /dev/null and b/assets/js/tinymce/skins/lightgray/img/anchor.gif differ diff --git a/assets/js/tinymce/skins/lightgray/img/loader.gif b/assets/js/tinymce/skins/lightgray/img/loader.gif new file mode 100644 index 0000000..c69e937 Binary files /dev/null and b/assets/js/tinymce/skins/lightgray/img/loader.gif differ diff --git a/assets/js/tinymce/skins/lightgray/img/object.gif b/assets/js/tinymce/skins/lightgray/img/object.gif new file mode 100644 index 0000000..cccd7f0 Binary files /dev/null and b/assets/js/tinymce/skins/lightgray/img/object.gif differ diff --git a/assets/js/tinymce/skins/lightgray/img/trans.gif b/assets/js/tinymce/skins/lightgray/img/trans.gif new file mode 100644 index 0000000..3884865 Binary files /dev/null and b/assets/js/tinymce/skins/lightgray/img/trans.gif differ diff --git a/assets/js/tinymce/skins/lightgray/skin.ie7.min.css b/assets/js/tinymce/skins/lightgray/skin.ie7.min.css new file mode 100644 index 0000000..9185801 --- /dev/null +++ b/assets/js/tinymce/skins/lightgray/skin.ie7.min.css @@ -0,0 +1 @@ +.mce-container,.mce-container *,.mce-widget,.mce-widget *,.mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-widget button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.mce-tinymce{visibility:inherit !important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block}.mce-wordcount{position:absolute;top:0;right:0;padding:8px}div.mce-edit-area{background:#fff;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative}.mce-fullscreen .mce-resizehandle{display:none}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid rgba(0,0,0,0.2);width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:#d9d9d9}.mce-grid td.mce-grid-cell div{border:1px solid #d6d6d6;width:15px;height:15px;margin:0;cursor:pointer}.mce-grid td.mce-grid-cell div:focus{border-color:#3498db}.mce-grid td.mce-grid-cell div[disabled]{cursor:not-allowed}.mce-grid{border-spacing:2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover,.mce-grid a:focus{border-color:#3498db}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#d6d6d6;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#3498db;background:#3498db}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%}.mce-colorbtn-trans div{text-align:center;vertical-align:middle;font-weight:bold;font-size:20px;line-height:16px;color:#707070}.mce-monospace{font-family:"Courier New",Courier,monospace}.mce-toolbar-grp{padding:2px 0}.mce-toolbar-grp .mce-flow-layout-item{margin-bottom:0}.mce-rtl .mce-wordcount{left:0;right:auto}.mce-croprect-container{position:absolute;top:0;left:0}.mce-croprect-handle{position:absolute;top:0;left:0;width:20px;height:20px;border:2px solid white}.mce-croprect-handle-nw{border-width:2px 0 0 2px;margin:-2px 0 0 -2px;cursor:nw-resize;top:100px;left:100px}.mce-croprect-handle-ne{border-width:2px 2px 0 0;margin:-2px 0 0 -20px;cursor:ne-resize;top:100px;left:200px}.mce-croprect-handle-sw{border-width:0 0 2px 2px;margin:-20px 2px 0 -2px;cursor:sw-resize;top:200px;left:100px}.mce-croprect-handle-se{border-width:0 2px 2px 0;margin:-20px 0 0 -20px;cursor:se-resize;top:200px;left:200px}.mce-croprect-handle-move{position:absolute;cursor:move;border:0}.mce-croprect-block{opacity:.3;filter:alpha(opacity=30);zoom:1;position:absolute;background:black}.mce-imagepanel{overflow:auto;background:black}.mce-imagepanel img{position:absolute}.mce-imagetool.mce-btn .mce-ico{display:block;width:20px;height:20px;text-align:center;line-height:20px;font-size:20px;padding:5px}.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mce-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#aaa;opacity:.6;filter:alpha(opacity=60);zoom:1}.mce-scroll{position:relative}.mce-panel{border:0 solid #cacaca;border:0 solid rgba(0,0,0,0.2);background-color:#f0f0f0}.mce-floatpanel{position:absolute}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mce-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;top:0;left:0;background:#fff;border:1px solid rgba(0,0,0,0.2);border:1px solid rgba(0,0,0,0.25)}.mce-floatpanel.mce-popover.mce-bottom{margin-top:10px;*margin-top:0}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:rgba(0,0,0,0.2);border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mce-window{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#fff;position:fixed;top:0;left:0;opacity:0;-webkit-transition:opacity 150ms ease-in;transition:opacity 150ms ease-in}.mce-window.mce-in{opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #c5c5c5;position:relative}.mce-window-head .mce-close{position:absolute;right:15px;top:9px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20px;overflow:hidden}.mce-close:hover{color:#adadad}.mce-window-head .mce-title{line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:10px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:#fff;border-top:1px solid #c5c5c5}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window-body .mce-listbox{border-color:#ccc}.mce-rtl .mce-window-head .mce-close{position:absolute;right:auto;left:15px}.mce-rtl .mce-window-head .mce-dragh{left:auto;right:0}.mce-rtl .mce-window-head .mce-title{direction:rtl;text-align:right}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:white;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-n .mce-tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-progress{display:inline-block;position:relative;height:20px}.mce-progress .mce-bar-container{display:inline-block;width:100px;height:100%;margin-right:8px;border:1px solid #ccc;overflow:hidden}.mce-progress .mce-text{display:inline-block;margin-top:auto;margin-bottom:auto;font-size:14px;width:40px;color:#333;text-shadow:1px 1px none}.mce-bar{display:block;width:0;height:100%;background-color:#d7d7d7;-webkit-transition:width .2s ease;transition:width .2s ease}.mce-notification{position:absolute;background-color:#f0f0f0;padding:5px;margin-top:5px;opacity:.8;filter:alpha(opacity=80);zoom:1;border-width:1px;border-style:solid;border-color:#ccc}.mce-notification-success{background-color:#dff0d8;border-color:#d6e9c6}.mce-notification-info{background-color:#d9edf7;border-color:#779ecb}.mce-notification-warning{background-color:#fcf8e3;border-color:#faebcc}.mce-notification-error{background-color:#f2dede;border-color:#ebccd1}.mce-notification.mce-has-close{padding-right:15px}.mce-notification .mce-ico{margin-top:5px}.mce-notification-inner{display:inline-block;font-size:14px;margin:5px 8px 4px 8px;text-align:center;white-space:normal;color:#31708f}.mce-notification-inner a{text-decoration:underline;cursor:pointer}.mce-notification .mce-progress{margin-right:8px}.mce-notification .mce-progress .mce-text{margin-top:5px}.mce-notification *,.mce-notification .mce-progress .mce-text{color:#333}.mce-notification .mce-progress .mce-bar-container{border-color:#ccc}.mce-notification .mce-progress .mce-bar-container .mce-bar{background-color:#333}.mce-notification-success *,.mce-notification-success .mce-progress .mce-text{color:#3c763d}.mce-notification-success .mce-progress .mce-bar-container{border-color:#d6e9c6}.mce-notification-success .mce-progress .mce-bar-container .mce-bar{background-color:#3c763d}.mce-notification-info *,.mce-notification-info .mce-progress .mce-text{color:#31708f}.mce-notification-info .mce-progress .mce-bar-container{border-color:#779ecb}.mce-notification-info .mce-progress .mce-bar-container .mce-bar{background-color:#31708f}.mce-notification-warning *,.mce-notification-warning .mce-progress .mce-text{color:#8a6d3b}.mce-notification-warning .mce-progress .mce-bar-container{border-color:#faebcc}.mce-notification-warning .mce-progress .mce-bar-container .mce-bar{background-color:#8a6d3b}.mce-notification-error *,.mce-notification-error .mce-progress .mce-text{color:#a94442}.mce-notification-error .mce-progress .mce-bar-container{border-color:#ebccd1}.mce-notification-error .mce-progress .mce-bar-container .mce-bar{background-color:#a94442}.mce-notification .mce-close{position:absolute;top:6px;right:8px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20px;overflow:hidden}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-btn{border:1px solid #b1b1b1;border-color:transparent transparent transparent transparent;position:relative;text-shadow:0 1px 1px rgba(255,255,255,0.75);display:inline-block;*display:inline;*zoom:1;background-color:#f0f0f0}.mce-btn:hover,.mce-btn:focus{color:#333;background-color:#e3e3e3;border-color:#ccc}.mce-btn.mce-disabled button,.mce-btn.mce-disabled:hover button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{background-color:#dbdbdb;border-color:#ccc}.mce-btn:active{background-color:#e0e0e0;border-color:#ccc}.mce-btn button{padding:4px 8px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px none}.mce-primary{min-width:50px;color:#fff;border:1px solid transparent;border-color:transparent;background-color:#2d8ac7}.mce-primary:hover,.mce-primary:focus{background-color:#257cb6;border-color:transparent}.mce-primary.mce-disabled button,.mce-primary.mce-disabled:hover button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-primary.mce-active,.mce-primary.mce-active:hover,.mce-primary:not(.mce-disabled):active{background-color:#206ea1}.mce-primary button,.mce-primary button i{color:#fff;text-shadow:1px 1px none}.mce-btn .mce-txt{font-size:inherit;line-height:inherit;color:inherit}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:1px 5px;font-size:12px;*padding-bottom:2px}.mce-btn-small i{line-height:20px;vertical-align:top;*line-height:18px}.mce-btn .mce-caret{margin-top:8px;margin-left:0}.mce-btn-small .mce-caret{margin-top:8px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #333;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#aaa}.mce-caret.mce-up{border-bottom:4px solid #333;border-top:0}.mce-btn-flat{border:0;background:transparent;filter:none}.mce-btn-flat:hover,.mce-btn-flat.mce-active,.mce-btn-flat:focus,.mce-btn-flat:active{border:0;background:#e6e6e6;filter:none}.mce-btn-has-text .mce-ico{padding-right:5px}.mce-rtl .mce-btn button{direction:rtl}.mce-btn-group .mce-btn{border-width:1px;margin:0;margin-left:2px}.mce-btn-group:not(:first-child){border-left:1px solid #d9d9d9;padding-left:3px;margin-left:3px}.mce-btn-group .mce-first{margin-left:0}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-rtl .mce-btn-group .mce-btn{margin-left:0;margin-right:2px}.mce-rtl .mce-btn-group .mce-first{margin-right:0}.mce-rtl .mce-btn-group:not(:first-child){border-left:none;border-right:1px solid #d9d9d9;padding-right:4px;margin-right:4px}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;background-color:#f0f0f0;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0;overflow:hidden}.mce-checked i.mce-i-checkbox{color:#333;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox,.mce-checkbox.mce-focus i.mce-i-checkbox{border:1px solid rgba(82,168,236,0.8)}.mce-checkbox.mce-disabled .mce-label,.mce-checkbox.mce-disabled i.mce-i-checkbox{color:#acacac}.mce-checkbox .mce-label{vertical-align:middle}.mce-rtl .mce-checkbox{direction:rtl;text-align:right}.mce-rtl i.mce-i-checkbox{margin:0 0 0 3px}.mce-combobox{display:inline-block;*display:inline;*zoom:1;*height:32px}.mce-combobox input{border:1px solid #c5c5c5;border-right-color:#c5c5c5;height:28px}.mce-combobox.mce-disabled input{color:#adadad}.mce-combobox .mce-btn{border:1px solid #c5c5c5;border-left:0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox.mce-disabled .mce-btn button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-colorbox i{border:1px solid #c5c5c5;width:14px;height:14px}.mce-colorbutton .mce-ico{position:relative}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:6px;padding-left:6px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-17px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-16px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:1px solid transparent}.mce-colorbutton:hover .mce-open{border-color:#ccc}.mce-colorbutton.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-colorbutton{direction:rtl}.mce-rtl .mce-colorbutton .mce-preview{margin-left:0;padding-right:0;padding-left:3px}.mce-rtl .mce-colorbutton.mce-btn-small .mce-preview{margin-left:0;padding-right:0;padding-left:2px}.mce-rtl .mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:0}.mce-colorpicker{position:relative;width:250px;height:220px}.mce-colorpicker-sv{position:absolute;top:0;left:0;width:90%;height:100%;border:1px solid #c5c5c5;cursor:crosshair;overflow:hidden}.mce-colorpicker-h-chunk{width:100%}.mce-colorpicker-overlay1,.mce-colorpicker-overlay2{width:100%;height:100%;position:absolute;top:0;left:0}.mce-colorpicker-overlay1{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr='#ffffff', endColorstr='#00ffffff');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr='#ffffff', endColorstr='#00ffffff')";background:linear-gradient(to right, #fff, rgba(255,255,255,0))}.mce-colorpicker-overlay2{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#00000000', endColorstr='#000000');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#00000000', endColorstr='#000000')";background:linear-gradient(to bottom, rgba(0,0,0,0), #000)}.mce-colorpicker-selector1{background:none;position:absolute;width:12px;height:12px;margin:-8px 0 0 -8px;border:1px solid black;border-radius:50%}.mce-colorpicker-selector2{position:absolute;width:10px;height:10px;border:1px solid white;border-radius:50%}.mce-colorpicker-h{position:absolute;top:0;right:0;width:6.5%;height:100%;border:1px solid #c5c5c5;cursor:crosshair}.mce-colorpicker-h-marker{margin-top:-4px;position:absolute;top:0;left:-1px;width:100%;border:1px solid #333;background:#fff;height:4px;z-index:100}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#333}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:#666;color:#fff}.mce-path .mce-divider{display:inline}.mce-disabled .mce-path-item{color:#aaa}.mce-rtl .mce-path{direction:rtl}.mce-fieldset{border:0 solid #9e9e9e}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-tinymce-inline .mce-flow-layout{white-space:nowrap}.mce-rtl .mce-flow-layout{text-align:right;direction:rtl}.mce-rtl .mce-flow-layout-item{margin:2px 2px 2px 0}.mce-rtl .mce-flow-layout-item.mce-last{margin-left:2px}.mce-iframe{border:0 solid rgba(0,0,0,0.2);width:100%;height:100%}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label.mce-disabled{color:#aaa}.mce-label.mce-multiline{white-space:pre-wrap}.mce-label.mce-error{color:#a00}.mce-rtl .mce-label{text-align:right;direction:rtl}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;filter:none}.mce-menubar .mce-menubtn button{color:#333}.mce-menubar{border:1px solid rgba(217,217,217,0.52)}.mce-menubar .mce-menubtn button span{color:#333}.mce-menubar .mce-caret{border-top-color:#333}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:#ccc;background:#fff;filter:none}.mce-menubtn button{color:#333}.mce-menubtn.mce-btn-small span{font-size:12px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-menubtn .mce-caret{*margin-top:6px}.mce-rtl .mce-menubtn button{direction:rtl;text-align:right}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item .mce-ico,.mce-menu-item .mce-text{color:#333}.mce-menu-item.mce-disabled .mce-text,.mce-menu-item.mce-disabled .mce-ico{color:#adadad}.mce-menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text,.mce-menu-item:focus .mce-text{color:white}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:white}.mce-menu-item.mce-disabled:hover{background:#ccc}.mce-menu-shortcut{display:inline-block;color:#adadad}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item:hover .mce-menu-shortcut,.mce-menu-item.mce-selected .mce-menu-shortcut,.mce-menu-item:focus .mce-menu-shortcut{color:white}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #333}.mce-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret,.mce-menu-item:hover .mce-caret{border-left-color:white}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-menu-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item.mce-active i{visibility:visible}.mce-menu-item-normal.mce-active{background-color:#3498db}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa}.mce-menu-item-normal.mce-active .mce-text{color:white}.mce-menu-item-normal.mce-active:hover .mce-text,.mce-menu-item-normal.mce-active:hover .mce-ico{color:white}.mce-menu-item-normal.mce-active:focus .mce-text,.mce-menu-item-normal.mce-active:focus .mce-ico{color:white}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:white;background-color:#2d8ac7}div.mce-menu .mce-menu-item-sep,.mce-menu-item-sep:hover{border:0;padding:0;height:1px;margin:9px 1px;overflow:hidden;background:transparent;border-bottom:1px solid rgba(0,0,0,0.1);cursor:default;filter:none}.mce-menu.mce-rtl{direction:rtl}.mce-rtl .mce-menu-item{text-align:right;direction:rtl;padding:6px 12px 6px 15px}.mce-menu-align.mce-rtl .mce-menu-shortcut,.mce-menu-align.mce-rtl .mce-caret{right:auto;left:0}.mce-rtl .mce-menu-item .mce-caret{margin-left:6px;margin-right:0;border-right:4px solid #333;border-left:0}.mce-rtl .mce-menu-item.mce-selected .mce-caret,.mce-rtl .mce-menu-item:focus .mce-caret,.mce-rtl .mce-menu-item:hover .mce-caret{border-left-color:transparent;border-right-color:white}.mce-menu{position:absolute;left:0;top:0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:-1px 0 0;min-width:160px;background:#fff;border:1px solid #989898;border:1px solid rgba(0,0,0,0.2);z-index:1002;max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-rtl .mce-listbox .mce-caret{right:auto;left:8px}.mce-rtl .mce-listbox button{padding-right:10px;padding-left:20px}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#333}.mce-selectbox{background:#fff;border:1px solid #c5c5c5}.mce-slider{border:1px solid #aaa;background:#eee;width:100px;height:10px;position:relative;display:block}.mce-slider.mce-vertical{width:10px;height:100px}.mce-slider-handle{border:1px solid #bbb;background:#ddd;display:block;width:13px;height:13px;position:absolute;top:0;left:0;margin-left:-1px;margin-top:-2px}.mce-spacer{visibility:hidden}.mce-splitbtn .mce-open{border-left:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#ccc}.mce-splitbtn button{padding-right:6px;padding-left:6px}.mce-splitbtn .mce-open{padding-right:4px;padding-left:4px}.mce-splitbtn .mce-open.mce-active{background-color:#dbdbdb;outline:1px solid #ccc}.mce-splitbtn.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-splitbtn{direction:rtl;text-align:right}.mce-rtl .mce-splitbtn button{padding-right:4px;padding-left:4px}.mce-rtl .mce-splitbtn .mce-open{border-left:0}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #c5c5c5}.mce-tabs,.mce-tabs+.mce-container-body{background:#fff}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #c5c5c5;border-width:0 1px 0 0;background:#fff;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#fdfdfd}.mce-tab.mce-active{background:#fdfdfd;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-rtl .mce-tabs{text-align:right;direction:rtl}.mce-rtl .mce-tab{border-width:0 0 0 1px}.mce-textbox{background:#fff;border:1px solid #c5c5c5;display:inline-block;-webkit-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#333}.mce-textbox:focus,.mce-textbox.mce-focus{border-color:#3498db}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px;height:auto}.mce-textbox.mce-disabled{color:#adadad}.mce-rtl .mce-textbox{text-align:right;direction:rtl}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}.mce-throbber-inline{position:static;height:50px}@font-face{font-family:'tinymce';src:url('fonts/tinymce.eot');src:url('fonts/tinymce.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce.woff') format('woff'),url('fonts/tinymce.ttf') format('truetype'),url('fonts/tinymce.svg#tinymce') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/tinymce-small.eot');src:url('fonts/tinymce-small.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce-small.woff') format('woff'),url('fonts/tinymce-small.ttf') format('truetype'),url('fonts/tinymce-small.svg#tinymce') format('svg');font-weight:normal;font-style:normal}.mce-ico{font-family:'tinymce';font-style:normal;font-weight:normal;font-size:16px;line-height:16px;vertical-align:text-top;-webkit-font-smoothing:antialiased;display:inline-block;background:transparent center center;width:16px;height:16px;color:#333;-ie7-icon:' '}.mce-btn-small .mce-ico{font-family:'tinymce-small'}.mce-ico,i.mce-i-checkbox{zoom:expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = this.currentStyle['-ie7-icon'].substr(1, 1) + ' ')}.mce-i-save{-ie7-icon:"\e000"}.mce-i-newdocument{-ie7-icon:"\e001"}.mce-i-fullpage{-ie7-icon:"\e002"}.mce-i-alignleft{-ie7-icon:"\e003"}.mce-i-aligncenter{-ie7-icon:"\e004"}.mce-i-alignright{-ie7-icon:"\e005"}.mce-i-alignjustify{-ie7-icon:"\e006"}.mce-i-alignnone{-ie7-icon:"\e003"}.mce-i-cut{-ie7-icon:"\e007"}.mce-i-paste{-ie7-icon:"\e008"}.mce-i-searchreplace{-ie7-icon:"\e009"}.mce-i-bullist{-ie7-icon:"\e00a"}.mce-i-numlist{-ie7-icon:"\e00b"}.mce-i-indent{-ie7-icon:"\e00c"}.mce-i-outdent{-ie7-icon:"\e00d"}.mce-i-blockquote{-ie7-icon:"\e00e"}.mce-i-undo{-ie7-icon:"\e00f"}.mce-i-redo{-ie7-icon:"\e010"}.mce-i-link{-ie7-icon:"\e011"}.mce-i-unlink{-ie7-icon:"\e012"}.mce-i-anchor{-ie7-icon:"\e013"}.mce-i-image{-ie7-icon:"\e014"}.mce-i-media{-ie7-icon:"\e015"}.mce-i-help{-ie7-icon:"\e016"}.mce-i-code{-ie7-icon:"\e017"}.mce-i-insertdatetime{-ie7-icon:"\e018"}.mce-i-preview{-ie7-icon:"\e019"}.mce-i-forecolor{-ie7-icon:"\e01a"}.mce-i-backcolor{-ie7-icon:"\e01a"}.mce-i-table{-ie7-icon:"\e01b"}.mce-i-hr{-ie7-icon:"\e01c"}.mce-i-removeformat{-ie7-icon:"\e01d"}.mce-i-subscript{-ie7-icon:"\e01e"}.mce-i-superscript{-ie7-icon:"\e01f"}.mce-i-charmap{-ie7-icon:"\e020"}.mce-i-emoticons{-ie7-icon:"\e021"}.mce-i-print{-ie7-icon:"\e022"}.mce-i-fullscreen{-ie7-icon:"\e023"}.mce-i-spellchecker{-ie7-icon:"\e024"}.mce-i-nonbreaking{-ie7-icon:"\e025"}.mce-i-template{-ie7-icon:"\e026"}.mce-i-pagebreak{-ie7-icon:"\e027"}.mce-i-restoredraft{-ie7-icon:"\e028"}.mce-i-untitled{-ie7-icon:"\e029"}.mce-i-bold{-ie7-icon:"\e02a"}.mce-i-italic{-ie7-icon:"\e02b"}.mce-i-underline{-ie7-icon:"\e02c"}.mce-i-strikethrough{-ie7-icon:"\e02d"}.mce-i-visualchars{-ie7-icon:"\e02e"}.mce-i-ltr{-ie7-icon:"\e02f"}.mce-i-rtl{-ie7-icon:"\e030"}.mce-i-copy{-ie7-icon:"\e031"}.mce-i-resize{-ie7-icon:"\e032"}.mce-i-browse{-ie7-icon:"\e034"}.mce-i-pastetext{-ie7-icon:"\e035"}.mce-i-rotateleft{-ie7-icon:"\eaa8"}.mce-i-rotateright{-ie7-icon:"\eaa9"}.mce-i-crop{-ie7-icon:"\ee78"}.mce-i-editimage{-ie7-icon:"\e914"}.mce-i-options{-ie7-icon:"\ec6a"}.mce-i-flipv{-ie7-icon:"\eaaa"}.mce-i-fliph{-ie7-icon:"\eaac"}.mce-i-zoomin{-ie7-icon:"\eb35"}.mce-i-zoomout{-ie7-icon:"\eb36"}.mce-i-sun{-ie7-icon:"\eccc"}.mce-i-moon{-ie7-icon:"\eccd"}.mce-i-arrowleft{-ie7-icon:"\edc0"}.mce-i-arrowright{-ie7-icon:"\edb8"}.mce-i-drop{-ie7-icon:"\e934"}.mce-i-contrast{-ie7-icon:"\ecd4"}.mce-i-sharpen{-ie7-icon:"\eba7"}.mce-i-palette{-ie7-icon:"\e92a"}.mce-i-resize2{-ie7-icon:"\edf9"}.mce-i-orientation{-ie7-icon:"\e601"}.mce-i-invert{-ie7-icon:"\e602"}.mce-i-gamma{-ie7-icon:"\e600"}.mce-i-remove{-ie7-icon:"\ed6a"}.mce-i-codesample{-ie7-icon:"\e603"}.mce-i-checkbox,.mce-i-selected{-ie7-icon:"\e033"}.mce-i-selected{visibility:hidden}.mce-i-backcolor{background:#bbb} \ No newline at end of file diff --git a/assets/js/tinymce/skins/lightgray/skin.min.css b/assets/js/tinymce/skins/lightgray/skin.min.css new file mode 100644 index 0000000..4718a6d --- /dev/null +++ b/assets/js/tinymce/skins/lightgray/skin.min.css @@ -0,0 +1 @@ +.mce-container,.mce-container *,.mce-widget,.mce-widget *,.mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;-webkit-tap-highlight-color:transparent;line-height:normal;font-weight:normal;text-align:left;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-widget button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.mce-container *[unselectable]{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}.mce-fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.mce-fade.mce-in{opacity:1}.mce-tinymce{visibility:inherit !important;position:relative}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%;z-index:100}div.mce-fullscreen{position:fixed;top:0;left:0;width:100%;height:auto}.mce-tinymce{display:block}.mce-wordcount{position:absolute;top:0;right:0;padding:8px}div.mce-edit-area{background:#fff;filter:none}.mce-statusbar{position:relative}.mce-statusbar .mce-container-body{position:relative}.mce-fullscreen .mce-resizehandle{display:none}.mce-charmap{border-collapse:collapse}.mce-charmap td{cursor:default;border:1px solid rgba(0,0,0,0.2);width:20px;height:20px;line-height:20px;text-align:center;vertical-align:middle;padding:2px}.mce-charmap td div{text-align:center}.mce-charmap td:hover{background:#d9d9d9}.mce-grid td.mce-grid-cell div{border:1px solid #d6d6d6;width:15px;height:15px;margin:0;cursor:pointer}.mce-grid td.mce-grid-cell div:focus{border-color:#3498db}.mce-grid td.mce-grid-cell div[disabled]{cursor:not-allowed}.mce-grid{border-spacing:2px;border-collapse:separate}.mce-grid a{display:block;border:1px solid transparent}.mce-grid a:hover,.mce-grid a:focus{border-color:#3498db}.mce-grid-border{margin:0 4px 0 4px}.mce-grid-border a{border-color:#d6d6d6;width:13px;height:13px}.mce-grid-border a:hover,.mce-grid-border a.mce-active{border-color:#3498db;background:#3498db}.mce-text-center{text-align:center}div.mce-tinymce-inline{width:100%}.mce-colorbtn-trans div{text-align:center;vertical-align:middle;font-weight:bold;font-size:20px;line-height:16px;color:#707070}.mce-monospace{font-family:"Courier New",Courier,monospace}.mce-toolbar-grp{padding:2px 0}.mce-toolbar-grp .mce-flow-layout-item{margin-bottom:0}.mce-rtl .mce-wordcount{left:0;right:auto}.mce-croprect-container{position:absolute;top:0;left:0}.mce-croprect-handle{position:absolute;top:0;left:0;width:20px;height:20px;border:2px solid white}.mce-croprect-handle-nw{border-width:2px 0 0 2px;margin:-2px 0 0 -2px;cursor:nw-resize;top:100px;left:100px}.mce-croprect-handle-ne{border-width:2px 2px 0 0;margin:-2px 0 0 -20px;cursor:ne-resize;top:100px;left:200px}.mce-croprect-handle-sw{border-width:0 0 2px 2px;margin:-20px 2px 0 -2px;cursor:sw-resize;top:200px;left:100px}.mce-croprect-handle-se{border-width:0 2px 2px 0;margin:-20px 0 0 -20px;cursor:se-resize;top:200px;left:200px}.mce-croprect-handle-move{position:absolute;cursor:move;border:0}.mce-croprect-block{opacity:.3;filter:alpha(opacity=30);zoom:1;position:absolute;background:black}.mce-imagepanel{overflow:auto;background:black}.mce-imagepanel img{position:absolute}.mce-imagetool.mce-btn .mce-ico{display:block;width:20px;height:20px;text-align:center;line-height:20px;font-size:20px;padding:5px}.mce-container,.mce-container-body{display:block}.mce-autoscroll{overflow:hidden}.mce-scrollbar{position:absolute;width:7px;height:100%;top:2px;right:2px;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-scrollbar-h{top:auto;right:auto;left:2px;bottom:2px;width:100%;height:7px}.mce-scrollbar-thumb{position:absolute;background-color:#000;border:1px solid #888;border-color:rgba(85,85,85,0.6);width:5px;height:100%}.mce-scrollbar-h .mce-scrollbar-thumb{width:100%;height:5px}.mce-scrollbar:hover,.mce-scrollbar.mce-active{background-color:#aaa;opacity:.6;filter:alpha(opacity=60);zoom:1}.mce-scroll{position:relative}.mce-panel{border:0 solid #cacaca;border:0 solid rgba(0,0,0,0.2);background-color:#f0f0f0}.mce-floatpanel{position:absolute}.mce-floatpanel.mce-fixed{position:fixed}.mce-floatpanel .mce-arrow,.mce-floatpanel .mce-arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.mce-floatpanel .mce-arrow{border-width:11px}.mce-floatpanel .mce-arrow:after{border-width:10px;content:""}.mce-floatpanel.mce-popover{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;top:0;left:0;background:#fff;border:1px solid rgba(0,0,0,0.2);border:1px solid rgba(0,0,0,0.25)}.mce-floatpanel.mce-popover.mce-bottom{margin-top:10px;*margin-top:0}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:rgba(0,0,0,0.2);border-bottom-color:rgba(0,0,0,0.25);top:-11px}.mce-floatpanel.mce-popover.mce-bottom>.mce-arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.mce-floatpanel.mce-popover.mce-bottom.mce-start{margin-left:-22px}.mce-floatpanel.mce-popover.mce-bottom.mce-start>.mce-arrow{left:20px}.mce-floatpanel.mce-popover.mce-bottom.mce-end{margin-left:22px}.mce-floatpanel.mce-popover.mce-bottom.mce-end>.mce-arrow{right:10px;left:auto}.mce-fullscreen{border:0;padding:0;margin:0;overflow:hidden;height:100%}div.mce-fullscreen{position:fixed;top:0;left:0}#mce-modal-block{opacity:0;filter:alpha(opacity=0);zoom:1;position:fixed;left:0;top:0;width:100%;height:100%;background:#000}#mce-modal-block.mce-in{opacity:.3;filter:alpha(opacity=30);zoom:1}.mce-window-move{cursor:move}.mce-window{filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;background:#fff;position:fixed;top:0;left:0;opacity:0;-webkit-transition:opacity 150ms ease-in;transition:opacity 150ms ease-in}.mce-window.mce-in{opacity:1}.mce-window-head{padding:9px 15px;border-bottom:1px solid #c5c5c5;position:relative}.mce-window-head .mce-close{position:absolute;right:15px;top:9px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20px;overflow:hidden}.mce-close:hover{color:#adadad}.mce-window-head .mce-title{line-height:20px;font-size:20px;font-weight:bold;text-rendering:optimizelegibility;padding-right:10px}.mce-window .mce-container-body{display:block}.mce-foot{display:block;background-color:#fff;border-top:1px solid #c5c5c5}.mce-window-head .mce-dragh{position:absolute;top:0;left:0;cursor:move;width:90%;height:100%}.mce-window iframe{width:100%;height:100%}.mce-window-body .mce-listbox{border-color:#ccc}.mce-rtl .mce-window-head .mce-close{position:absolute;right:auto;left:15px}.mce-rtl .mce-window-head .mce-dragh{left:auto;right:0}.mce-rtl .mce-window-head .mce-title{direction:rtl;text-align:right}.mce-tooltip{position:absolute;padding:5px;opacity:.8;filter:alpha(opacity=80);zoom:1}.mce-tooltip-inner{font-size:11px;background-color:#000;color:white;max-width:200px;padding:5px 8px 4px 8px;text-align:center;white-space:normal}.mce-tooltip-arrow{position:absolute;width:0;height:0;line-height:0;border:5px dashed #000}.mce-tooltip-arrow-n{border-bottom-color:#000}.mce-tooltip-arrow-s{border-top-color:#000}.mce-tooltip-arrow-e{border-left-color:#000}.mce-tooltip-arrow-w{border-right-color:#000}.mce-tooltip-nw,.mce-tooltip-sw{margin-left:-14px}.mce-tooltip-n .mce-tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-nw .mce-tooltip-arrow{top:0;left:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-ne .mce-tooltip-arrow{top:0;right:10px;border-bottom-style:solid;border-top:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-s .mce-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-sw .mce-tooltip-arrow{bottom:0;left:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-se .mce-tooltip-arrow{bottom:0;right:10px;border-top-style:solid;border-bottom:none;border-left-color:transparent;border-right-color:transparent}.mce-tooltip-e .mce-tooltip-arrow{right:0;top:50%;margin-top:-5px;border-left-style:solid;border-right:none;border-top-color:transparent;border-bottom-color:transparent}.mce-tooltip-w .mce-tooltip-arrow{left:0;top:50%;margin-top:-5px;border-right-style:solid;border-left:none;border-top-color:transparent;border-bottom-color:transparent}.mce-progress{display:inline-block;position:relative;height:20px}.mce-progress .mce-bar-container{display:inline-block;width:100px;height:100%;margin-right:8px;border:1px solid #ccc;overflow:hidden}.mce-progress .mce-text{display:inline-block;margin-top:auto;margin-bottom:auto;font-size:14px;width:40px;color:#333;text-shadow:1px 1px none}.mce-bar{display:block;width:0;height:100%;background-color:#d7d7d7;-webkit-transition:width .2s ease;transition:width .2s ease}.mce-notification{position:absolute;background-color:#f0f0f0;padding:5px;margin-top:5px;opacity:.8;filter:alpha(opacity=80);zoom:1;border-width:1px;border-style:solid;border-color:#ccc}.mce-notification-success{background-color:#dff0d8;border-color:#d6e9c6}.mce-notification-info{background-color:#d9edf7;border-color:#779ecb}.mce-notification-warning{background-color:#fcf8e3;border-color:#faebcc}.mce-notification-error{background-color:#f2dede;border-color:#ebccd1}.mce-notification.mce-has-close{padding-right:15px}.mce-notification .mce-ico{margin-top:5px}.mce-notification-inner{display:inline-block;font-size:14px;margin:5px 8px 4px 8px;text-align:center;white-space:normal;color:#31708f}.mce-notification-inner a{text-decoration:underline;cursor:pointer}.mce-notification .mce-progress{margin-right:8px}.mce-notification .mce-progress .mce-text{margin-top:5px}.mce-notification *,.mce-notification .mce-progress .mce-text{color:#333}.mce-notification .mce-progress .mce-bar-container{border-color:#ccc}.mce-notification .mce-progress .mce-bar-container .mce-bar{background-color:#333}.mce-notification-success *,.mce-notification-success .mce-progress .mce-text{color:#3c763d}.mce-notification-success .mce-progress .mce-bar-container{border-color:#d6e9c6}.mce-notification-success .mce-progress .mce-bar-container .mce-bar{background-color:#3c763d}.mce-notification-info *,.mce-notification-info .mce-progress .mce-text{color:#31708f}.mce-notification-info .mce-progress .mce-bar-container{border-color:#779ecb}.mce-notification-info .mce-progress .mce-bar-container .mce-bar{background-color:#31708f}.mce-notification-warning *,.mce-notification-warning .mce-progress .mce-text{color:#8a6d3b}.mce-notification-warning .mce-progress .mce-bar-container{border-color:#faebcc}.mce-notification-warning .mce-progress .mce-bar-container .mce-bar{background-color:#8a6d3b}.mce-notification-error *,.mce-notification-error .mce-progress .mce-text{color:#a94442}.mce-notification-error .mce-progress .mce-bar-container{border-color:#ebccd1}.mce-notification-error .mce-progress .mce-bar-container .mce-bar{background-color:#a94442}.mce-notification .mce-close{position:absolute;top:6px;right:8px;font-size:20px;font-weight:bold;line-height:20px;color:#858585;cursor:pointer;height:20px;overflow:hidden}.mce-abs-layout{position:relative}body .mce-abs-layout-item,.mce-abs-end{position:absolute}.mce-abs-end{width:1px;height:1px}.mce-container-body.mce-abs-layout{overflow:hidden}.mce-btn{border:1px solid #b1b1b1;border-color:transparent transparent transparent transparent;position:relative;text-shadow:0 1px 1px rgba(255,255,255,0.75);display:inline-block;*display:inline;*zoom:1;background-color:#f0f0f0}.mce-btn:hover,.mce-btn:focus{color:#333;background-color:#e3e3e3;border-color:#ccc}.mce-btn.mce-disabled button,.mce-btn.mce-disabled:hover button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-btn.mce-active,.mce-btn.mce-active:hover{background-color:#dbdbdb;border-color:#ccc}.mce-btn:active{background-color:#e0e0e0;border-color:#ccc}.mce-btn button{padding:4px 8px;font-size:14px;line-height:20px;*line-height:16px;cursor:pointer;color:#333;text-align:center;overflow:visible;-webkit-appearance:none}.mce-btn button::-moz-focus-inner{border:0;padding:0}.mce-btn i{text-shadow:1px 1px none}.mce-primary{min-width:50px;color:#fff;border:1px solid transparent;border-color:transparent;background-color:#2d8ac7}.mce-primary:hover,.mce-primary:focus{background-color:#257cb6;border-color:transparent}.mce-primary.mce-disabled button,.mce-primary.mce-disabled:hover button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-primary.mce-active,.mce-primary.mce-active:hover,.mce-primary:not(.mce-disabled):active{background-color:#206ea1}.mce-primary button,.mce-primary button i{color:#fff;text-shadow:1px 1px none}.mce-btn .mce-txt{font-size:inherit;line-height:inherit;color:inherit}.mce-btn-large button{padding:9px 14px;font-size:16px;line-height:normal}.mce-btn-large i{margin-top:2px}.mce-btn-small button{padding:1px 5px;font-size:12px;*padding-bottom:2px}.mce-btn-small i{line-height:20px;vertical-align:top;*line-height:18px}.mce-btn .mce-caret{margin-top:8px;margin-left:0}.mce-btn-small .mce-caret{margin-top:8px;margin-left:0}.mce-caret{display:inline-block;*display:inline;*zoom:1;width:0;height:0;vertical-align:top;border-top:4px solid #333;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.mce-disabled .mce-caret{border-top-color:#aaa}.mce-caret.mce-up{border-bottom:4px solid #333;border-top:0}.mce-btn-flat{border:0;background:transparent;filter:none}.mce-btn-flat:hover,.mce-btn-flat.mce-active,.mce-btn-flat:focus,.mce-btn-flat:active{border:0;background:#e6e6e6;filter:none}.mce-btn-has-text .mce-ico{padding-right:5px}.mce-rtl .mce-btn button{direction:rtl}.mce-btn-group .mce-btn{border-width:1px;margin:0;margin-left:2px}.mce-btn-group:not(:first-child){border-left:1px solid #d9d9d9;padding-left:3px;margin-left:3px}.mce-btn-group .mce-first{margin-left:0}.mce-btn-group .mce-btn.mce-flow-layout-item{margin:0}.mce-rtl .mce-btn-group .mce-btn{margin-left:0;margin-right:2px}.mce-rtl .mce-btn-group .mce-first{margin-right:0}.mce-rtl .mce-btn-group:not(:first-child){border-left:none;border-right:1px solid #d9d9d9;padding-right:4px;margin-right:4px}.mce-checkbox{cursor:pointer}i.mce-i-checkbox{margin:0 3px 0 0;border:1px solid #c5c5c5;background-color:#f0f0f0;text-indent:-10em;*font-size:0;*line-height:0;*text-indent:0;overflow:hidden}.mce-checked i.mce-i-checkbox{color:#333;font-size:16px;line-height:16px;text-indent:0}.mce-checkbox:focus i.mce-i-checkbox,.mce-checkbox.mce-focus i.mce-i-checkbox{border:1px solid rgba(82,168,236,0.8)}.mce-checkbox.mce-disabled .mce-label,.mce-checkbox.mce-disabled i.mce-i-checkbox{color:#acacac}.mce-checkbox .mce-label{vertical-align:middle}.mce-rtl .mce-checkbox{direction:rtl;text-align:right}.mce-rtl i.mce-i-checkbox{margin:0 0 0 3px}.mce-combobox{display:inline-block;*display:inline;*zoom:1;*height:32px}.mce-combobox input{border:1px solid #c5c5c5;border-right-color:#c5c5c5;height:28px}.mce-combobox.mce-disabled input{color:#adadad}.mce-combobox .mce-btn{border:1px solid #c5c5c5;border-left:0}.mce-combobox button{padding-right:8px;padding-left:8px}.mce-combobox.mce-disabled .mce-btn button{cursor:default;opacity:.4;filter:alpha(opacity=40);zoom:1}.mce-colorbox i{border:1px solid #c5c5c5;width:14px;height:14px}.mce-colorbutton .mce-ico{position:relative}.mce-colorbutton-grid{margin:4px}.mce-colorbutton button{padding-right:6px;padding-left:6px}.mce-colorbutton .mce-preview{padding-right:3px;display:block;position:absolute;left:50%;top:50%;margin-left:-17px;margin-top:7px;background:gray;width:13px;height:2px;overflow:hidden}.mce-colorbutton.mce-btn-small .mce-preview{margin-left:-16px;padding-right:0;width:16px}.mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:1px solid transparent}.mce-colorbutton:hover .mce-open{border-color:#ccc}.mce-colorbutton.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-colorbutton{direction:rtl}.mce-rtl .mce-colorbutton .mce-preview{margin-left:0;padding-right:0;padding-left:3px}.mce-rtl .mce-colorbutton.mce-btn-small .mce-preview{margin-left:0;padding-right:0;padding-left:2px}.mce-rtl .mce-colorbutton .mce-open{padding-left:4px;padding-right:4px;border-left:0}.mce-colorpicker{position:relative;width:250px;height:220px}.mce-colorpicker-sv{position:absolute;top:0;left:0;width:90%;height:100%;border:1px solid #c5c5c5;cursor:crosshair;overflow:hidden}.mce-colorpicker-h-chunk{width:100%}.mce-colorpicker-overlay1,.mce-colorpicker-overlay2{width:100%;height:100%;position:absolute;top:0;left:0}.mce-colorpicker-overlay1{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr='#ffffff', endColorstr='#00ffffff');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr='#ffffff', endColorstr='#00ffffff')";background:linear-gradient(to right, #fff, rgba(255,255,255,0))}.mce-colorpicker-overlay2{filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#00000000', endColorstr='#000000');-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#00000000', endColorstr='#000000')";background:linear-gradient(to bottom, rgba(0,0,0,0), #000)}.mce-colorpicker-selector1{background:none;position:absolute;width:12px;height:12px;margin:-8px 0 0 -8px;border:1px solid black;border-radius:50%}.mce-colorpicker-selector2{position:absolute;width:10px;height:10px;border:1px solid white;border-radius:50%}.mce-colorpicker-h{position:absolute;top:0;right:0;width:6.5%;height:100%;border:1px solid #c5c5c5;cursor:crosshair}.mce-colorpicker-h-marker{margin-top:-4px;position:absolute;top:0;left:-1px;width:100%;border:1px solid #333;background:#fff;height:4px;z-index:100}.mce-path{display:inline-block;*display:inline;*zoom:1;padding:8px;white-space:normal}.mce-path .mce-txt{display:inline-block;padding-right:3px}.mce-path .mce-path-body{display:inline-block}.mce-path-item{display:inline-block;*display:inline;*zoom:1;cursor:pointer;color:#333}.mce-path-item:hover{text-decoration:underline}.mce-path-item:focus{background:#666;color:#fff}.mce-path .mce-divider{display:inline}.mce-disabled .mce-path-item{color:#aaa}.mce-rtl .mce-path{direction:rtl}.mce-fieldset{border:0 solid #9e9e9e}.mce-fieldset>.mce-container-body{margin-top:-15px}.mce-fieldset-title{margin-left:5px;padding:0 5px 0 5px}.mce-fit-layout{display:inline-block;*display:inline;*zoom:1}.mce-fit-layout-item{position:absolute}.mce-flow-layout-item{display:inline-block;*display:inline;*zoom:1}.mce-flow-layout-item{margin:2px 0 2px 2px}.mce-flow-layout-item.mce-last{margin-right:2px}.mce-flow-layout{white-space:normal}.mce-tinymce-inline .mce-flow-layout{white-space:nowrap}.mce-rtl .mce-flow-layout{text-align:right;direction:rtl}.mce-rtl .mce-flow-layout-item{margin:2px 2px 2px 0}.mce-rtl .mce-flow-layout-item.mce-last{margin-left:2px}.mce-iframe{border:0 solid rgba(0,0,0,0.2);width:100%;height:100%}.mce-label{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 1px rgba(255,255,255,0.75);overflow:hidden}.mce-label.mce-autoscroll{overflow:auto}.mce-label.mce-disabled{color:#aaa}.mce-label.mce-multiline{white-space:pre-wrap}.mce-label.mce-error{color:#a00}.mce-rtl .mce-label{text-align:right;direction:rtl}.mce-menubar .mce-menubtn{border-color:transparent;background:transparent;filter:none}.mce-menubar .mce-menubtn button{color:#333}.mce-menubar{border:1px solid rgba(217,217,217,0.52)}.mce-menubar .mce-menubtn button span{color:#333}.mce-menubar .mce-caret{border-top-color:#333}.mce-menubar .mce-menubtn:hover,.mce-menubar .mce-menubtn.mce-active,.mce-menubar .mce-menubtn:focus{border-color:#ccc;background:#fff;filter:none}.mce-menubtn button{color:#333}.mce-menubtn.mce-btn-small span{font-size:12px}.mce-menubtn.mce-fixed-width span{display:inline-block;overflow-x:hidden;text-overflow:ellipsis;width:90px}.mce-menubtn.mce-fixed-width.mce-btn-small span{width:70px}.mce-menubtn .mce-caret{*margin-top:6px}.mce-rtl .mce-menubtn button{direction:rtl;text-align:right}.mce-menu-item{display:block;padding:6px 15px 6px 12px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap;cursor:pointer;line-height:normal;border-left:4px solid transparent;margin-bottom:1px}.mce-menu-item .mce-ico,.mce-menu-item .mce-text{color:#333}.mce-menu-item.mce-disabled .mce-text,.mce-menu-item.mce-disabled .mce-ico{color:#adadad}.mce-menu-item:hover .mce-text,.mce-menu-item.mce-selected .mce-text,.mce-menu-item:focus .mce-text{color:white}.mce-menu-item:hover .mce-ico,.mce-menu-item.mce-selected .mce-ico,.mce-menu-item:focus .mce-ico{color:white}.mce-menu-item.mce-disabled:hover{background:#ccc}.mce-menu-shortcut{display:inline-block;color:#adadad}.mce-menu-shortcut{display:inline-block;*display:inline;*zoom:1;padding:0 15px 0 20px}.mce-menu-item:hover .mce-menu-shortcut,.mce-menu-item.mce-selected .mce-menu-shortcut,.mce-menu-item:focus .mce-menu-shortcut{color:white}.mce-menu-item .mce-caret{margin-top:4px;*margin-top:3px;margin-right:6px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid #333}.mce-menu-item.mce-selected .mce-caret,.mce-menu-item:focus .mce-caret,.mce-menu-item:hover .mce-caret{border-left-color:white}.mce-menu-align .mce-menu-shortcut{*margin-top:-2px}.mce-menu-align .mce-menu-shortcut,.mce-menu-align .mce-caret{position:absolute;right:0}.mce-menu-item.mce-active i{visibility:visible}.mce-menu-item-normal.mce-active{background-color:#3498db}.mce-menu-item-preview.mce-active{border-left:5px solid #aaa}.mce-menu-item-normal.mce-active .mce-text{color:white}.mce-menu-item-normal.mce-active:hover .mce-text,.mce-menu-item-normal.mce-active:hover .mce-ico{color:white}.mce-menu-item-normal.mce-active:focus .mce-text,.mce-menu-item-normal.mce-active:focus .mce-ico{color:white}.mce-menu-item:hover,.mce-menu-item.mce-selected,.mce-menu-item:focus{text-decoration:none;color:white;background-color:#2d8ac7}div.mce-menu .mce-menu-item-sep,.mce-menu-item-sep:hover{border:0;padding:0;height:1px;margin:9px 1px;overflow:hidden;background:transparent;border-bottom:1px solid rgba(0,0,0,0.1);cursor:default;filter:none}.mce-menu.mce-rtl{direction:rtl}.mce-rtl .mce-menu-item{text-align:right;direction:rtl;padding:6px 12px 6px 15px}.mce-menu-align.mce-rtl .mce-menu-shortcut,.mce-menu-align.mce-rtl .mce-caret{right:auto;left:0}.mce-rtl .mce-menu-item .mce-caret{margin-left:6px;margin-right:0;border-right:4px solid #333;border-left:0}.mce-rtl .mce-menu-item.mce-selected .mce-caret,.mce-rtl .mce-menu-item:focus .mce-caret,.mce-rtl .mce-menu-item:hover .mce-caret{border-left-color:transparent;border-right-color:white}.mce-menu{position:absolute;left:0;top:0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background:transparent;z-index:1000;padding:5px 0 5px 0;margin:-1px 0 0;min-width:160px;background:#fff;border:1px solid #989898;border:1px solid rgba(0,0,0,0.2);z-index:1002;max-height:400px;overflow:auto;overflow-x:hidden}.mce-menu i{display:none}.mce-menu-has-icons i{display:inline-block;*display:inline}.mce-menu-sub-tr-tl{margin:-6px 0 0 -1px}.mce-menu-sub-br-bl{margin:6px 0 0 -1px}.mce-menu-sub-tl-tr{margin:-6px 0 0 1px}.mce-menu-sub-bl-br{margin:6px 0 0 1px}.mce-listbox button{text-align:left;padding-right:20px;position:relative}.mce-listbox .mce-caret{position:absolute;margin-top:-2px;right:8px;top:50%}.mce-rtl .mce-listbox .mce-caret{right:auto;left:8px}.mce-rtl .mce-listbox button{padding-right:10px;padding-left:20px}.mce-container-body .mce-resizehandle{position:absolute;right:0;bottom:0;width:16px;height:16px;visibility:visible;cursor:s-resize;margin:0}.mce-container-body .mce-resizehandle-both{cursor:se-resize}i.mce-i-resize{color:#333}.mce-selectbox{background:#fff;border:1px solid #c5c5c5}.mce-slider{border:1px solid #aaa;background:#eee;width:100px;height:10px;position:relative;display:block}.mce-slider.mce-vertical{width:10px;height:100px}.mce-slider-handle{border:1px solid #bbb;background:#ddd;display:block;width:13px;height:13px;position:absolute;top:0;left:0;margin-left:-1px;margin-top:-2px}.mce-spacer{visibility:hidden}.mce-splitbtn .mce-open{border-left:1px solid transparent}.mce-splitbtn:hover .mce-open{border-left-color:#ccc}.mce-splitbtn button{padding-right:6px;padding-left:6px}.mce-splitbtn .mce-open{padding-right:4px;padding-left:4px}.mce-splitbtn .mce-open.mce-active{background-color:#dbdbdb;outline:1px solid #ccc}.mce-splitbtn.mce-btn-small .mce-open{padding:0 3px 0 3px}.mce-rtl .mce-splitbtn{direction:rtl;text-align:right}.mce-rtl .mce-splitbtn button{padding-right:4px;padding-left:4px}.mce-rtl .mce-splitbtn .mce-open{border-left:0}.mce-stack-layout-item{display:block}.mce-tabs{display:block;border-bottom:1px solid #c5c5c5}.mce-tabs,.mce-tabs+.mce-container-body{background:#fff}.mce-tab{display:inline-block;*display:inline;*zoom:1;border:1px solid #c5c5c5;border-width:0 1px 0 0;background:#fff;padding:8px;text-shadow:0 1px 1px rgba(255,255,255,0.75);height:13px;cursor:pointer}.mce-tab:hover{background:#fdfdfd}.mce-tab.mce-active{background:#fdfdfd;border-bottom-color:transparent;margin-bottom:-1px;height:14px}.mce-rtl .mce-tabs{text-align:right;direction:rtl}.mce-rtl .mce-tab{border-width:0 0 0 1px}.mce-textbox{background:#fff;border:1px solid #c5c5c5;display:inline-block;-webkit-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;height:28px;resize:none;padding:0 4px 0 4px;white-space:pre-wrap;*white-space:pre;color:#333}.mce-textbox:focus,.mce-textbox.mce-focus{border-color:#3498db}.mce-placeholder .mce-textbox{color:#aaa}.mce-textbox.mce-multiline{padding:4px;height:auto}.mce-textbox.mce-disabled{color:#adadad}.mce-rtl .mce-textbox{text-align:right;direction:rtl}.mce-throbber{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.6;filter:alpha(opacity=60);zoom:1;background:#fff url('img/loader.gif') no-repeat center center}.mce-throbber-inline{position:static;height:50px}@font-face{font-family:'tinymce';src:url('fonts/tinymce.eot');src:url('fonts/tinymce.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce.woff') format('woff'),url('fonts/tinymce.ttf') format('truetype'),url('fonts/tinymce.svg#tinymce') format('svg');font-weight:normal;font-style:normal}@font-face{font-family:'tinymce-small';src:url('fonts/tinymce-small.eot');src:url('fonts/tinymce-small.eot?#iefix') format('embedded-opentype'),url('fonts/tinymce-small.woff') format('woff'),url('fonts/tinymce-small.ttf') format('truetype'),url('fonts/tinymce-small.svg#tinymce') format('svg');font-weight:normal;font-style:normal}.mce-ico{font-family:'tinymce',Arial;font-style:normal;font-weight:normal;font-variant:normal;font-size:16px;line-height:16px;speak:none;vertical-align:text-top;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;background:transparent center center;background-size:cover;width:16px;height:16px;color:#333}.mce-btn-small .mce-ico{font-family:'tinymce-small',Arial}.mce-i-save:before{content:"\e000"}.mce-i-newdocument:before{content:"\e001"}.mce-i-fullpage:before{content:"\e002"}.mce-i-alignleft:before{content:"\e003"}.mce-i-aligncenter:before{content:"\e004"}.mce-i-alignright:before{content:"\e005"}.mce-i-alignjustify:before{content:"\e006"}.mce-i-alignnone:before{content:"\e003"}.mce-i-cut:before{content:"\e007"}.mce-i-paste:before{content:"\e008"}.mce-i-searchreplace:before{content:"\e009"}.mce-i-bullist:before{content:"\e00a"}.mce-i-numlist:before{content:"\e00b"}.mce-i-indent:before{content:"\e00c"}.mce-i-outdent:before{content:"\e00d"}.mce-i-blockquote:before{content:"\e00e"}.mce-i-undo:before{content:"\e00f"}.mce-i-redo:before{content:"\e010"}.mce-i-link:before{content:"\e011"}.mce-i-unlink:before{content:"\e012"}.mce-i-anchor:before{content:"\e013"}.mce-i-image:before{content:"\e014"}.mce-i-media:before{content:"\e015"}.mce-i-help:before{content:"\e016"}.mce-i-code:before{content:"\e017"}.mce-i-insertdatetime:before{content:"\e018"}.mce-i-preview:before{content:"\e019"}.mce-i-forecolor:before{content:"\e01a"}.mce-i-backcolor:before{content:"\e01a"}.mce-i-table:before{content:"\e01b"}.mce-i-hr:before{content:"\e01c"}.mce-i-removeformat:before{content:"\e01d"}.mce-i-subscript:before{content:"\e01e"}.mce-i-superscript:before{content:"\e01f"}.mce-i-charmap:before{content:"\e020"}.mce-i-emoticons:before{content:"\e021"}.mce-i-print:before{content:"\e022"}.mce-i-fullscreen:before{content:"\e023"}.mce-i-spellchecker:before{content:"\e024"}.mce-i-nonbreaking:before{content:"\e025"}.mce-i-template:before{content:"\e026"}.mce-i-pagebreak:before{content:"\e027"}.mce-i-restoredraft:before{content:"\e028"}.mce-i-untitled:before{content:"\e029"}.mce-i-bold:before{content:"\e02a"}.mce-i-italic:before{content:"\e02b"}.mce-i-underline:before{content:"\e02c"}.mce-i-strikethrough:before{content:"\e02d"}.mce-i-visualchars:before{content:"\e02e"}.mce-i-visualblocks:before{content:"\e02e"}.mce-i-ltr:before{content:"\e02f"}.mce-i-rtl:before{content:"\e030"}.mce-i-copy:before{content:"\e031"}.mce-i-resize:before{content:"\e032"}.mce-i-browse:before{content:"\e034"}.mce-i-pastetext:before{content:"\e035"}.mce-i-rotateleft:before{content:"\eaa8"}.mce-i-rotateright:before{content:"\eaa9"}.mce-i-crop:before{content:"\ee78"}.mce-i-editimage:before{content:"\e914"}.mce-i-options:before{content:"\ec6a"}.mce-i-flipv:before{content:"\eaaa"}.mce-i-fliph:before{content:"\eaac"}.mce-i-zoomin:before{content:"\eb35"}.mce-i-zoomout:before{content:"\eb36"}.mce-i-sun:before{content:"\eccc"}.mce-i-moon:before{content:"\eccd"}.mce-i-arrowleft:before{content:"\edc0"}.mce-i-arrowright:before{content:"\edb8"}.mce-i-drop:before{content:"\e934"}.mce-i-contrast:before{content:"\ecd4"}.mce-i-sharpen:before{content:"\eba7"}.mce-i-palette:before{content:"\e92a"}.mce-i-resize2:before{content:"\edf9"}.mce-i-orientation:before{content:"\e601"}.mce-i-invert:before{content:"\e602"}.mce-i-gamma:before{content:"\e600"}.mce-i-remove:before{content:"\ed6a"}.mce-i-tablerowprops:before{content:"\e604"}.mce-i-tablecellprops:before{content:"\e605"}.mce-i-table2:before{content:"\e606"}.mce-i-tablemergecells:before{content:"\e607"}.mce-i-tableinsertcolbefore:before{content:"\e608"}.mce-i-tableinsertcolafter:before{content:"\e609"}.mce-i-tableinsertrowbefore:before{content:"\e60a"}.mce-i-tableinsertrowafter:before{content:"\e60b"}.mce-i-tablesplitcells:before{content:"\e60d"}.mce-i-tabledelete:before{content:"\e60e"}.mce-i-tableleftheader:before{content:"\e62a"}.mce-i-tabletopheader:before{content:"\e62b"}.mce-i-tabledeleterow:before{content:"\e800"}.mce-i-tabledeletecol:before{content:"\e801"}.mce-i-codesample:before{content:"\e603"}.mce-i-checkbox:before,.mce-i-selected:before{content:"\e033"}.mce-i-selected{visibility:hidden}i.mce-i-backcolor{text-shadow:none;background:#bbb} \ No newline at end of file diff --git a/assets/js/tinymce/themes/modern/theme.min.js b/assets/js/tinymce/themes/modern/theme.min.js new file mode 100644 index 0000000..d101fc6 --- /dev/null +++ b/assets/js/tinymce/themes/modern/theme.min.js @@ -0,0 +1 @@ +tinymce.ThemeManager.add("modern",function(a){function b(b,c){var d,e=[];if(b)return n(b.split(/[ ,]/),function(b){function f(){function c(a){return function(c,d){for(var e,f=d.parents.length;f--&&(e=d.parents[f].nodeName,"OL"!=e&&"UL"!=e););b.active(c&&e==a)}}var d=a.selection;"bullist"==g&&d.selectorChanged("ul > li",c("UL")),"numlist"==g&&d.selectorChanged("ol > li",c("OL")),b.settings.stateSelector&&d.selectorChanged(b.settings.stateSelector,function(a){b.active(a)},!0),b.settings.disabledStateSelector&&d.selectorChanged(b.settings.disabledStateSelector,function(a){b.disabled(a)})}var g;"|"==b?d=null:m.has(b)?(b={type:b,size:c},e.push(b),d=null):(d||(d={type:"buttongroup",items:[]},e.push(d)),a.buttons[b]&&(g=b,b=a.buttons[g],"function"==typeof b&&(b=b()),b.type=b.type||"button",b.size=c,b=m.create(b),d.items.push(b),a.initialized?f():a.on("init",f)))}),{type:"toolbar",layout:"flow",items:e}}function c(a){function c(c){return c?(d.push(b(c,a)),!0):void 0}var d=[];if(tinymce.isArray(l.toolbar)){if(0===l.toolbar.length)return;tinymce.each(l.toolbar,function(a,b){l["toolbar"+(b+1)]=a}),delete l.toolbar}for(var e=1;10>e&&c(l["toolbar"+e]);e++);return d.length||l.toolbar===!1||c(l.toolbar||s),d.length?{type:"panel",layout:"stack",classes:"toolbar-grp",ariaRoot:!0,ariaRemember:!0,items:d}:void 0}function d(){function b(b){var c;return"|"==b?{text:"|"}:c=a.menuItems[b]}function c(c){var d,e,f,g,h;if(h=tinymce.makeMap((l.removed_menuitems||"").split(/[ ,]/)),l.menu?(e=l.menu[c],g=!0):e=r[c],e){d={text:e.title},f=[],n((e.items||"").split(/[ ,]/),function(a){var c=b(a);c&&!h[a]&&f.push(b(a))}),g||n(a.menuItems,function(a){a.context==c&&("before"==a.separator&&f.push({text:"|"}),a.prependToContext?f.unshift(a):f.push(a),"after"==a.separator&&f.push({text:"|"}))});for(var i=0;i=0;d--)for(e=g.length-1;e>=0;e--)if(g[e].predicate(f[d]))return{toolbar:g[e],element:f[d]};return null}var l;a.on("click keyup setContent",function(b){("setcontent"!=b.type||b.selection)&&tinymce.util.Delay.setEditorTimeout(a,function(){var b;b=k(a.selection.getNode()),b?(j(),i(b)):j()})}),a.on("blur hide",j),a.on("ObjectResizeStart",function(){var b=k(a.selection.getNode());b&&b.toolbar.panel&&b.toolbar.panel.hide()}),a.on("nodeChange ResizeEditor ResizeWindow",g),a.on("remove",function(){tinymce.each(c(),function(a){a.panel&&a.panel.remove()}),a.contextToolbars={}})}function i(b){function f(){if(n&&n.moveRel&&n.visible()&&!n._fixed){var b=a.selection.getScrollContainer(),c=a.getBody(),d=0,e=0;if(b){var f=o.getPos(c),g=o.getPos(b);d=Math.max(0,g.x-f.x),e=Math.max(0,g.y-f.y)}n.fixed(!1).moveRel(c,a.rtl?["tr-br","br-tr"]:["tl-bl","bl-tl","tr-br"]).moveBy(d,e)}}function g(){n&&(n.show(),f(),o.addClass(a.getBody(),"mce-edit-focus"))}function i(){n&&(n.hide(),q.hideAll(),o.removeClass(a.getBody(),"mce-edit-focus"))}function j(){return n?void(n.visible()||g()):(n=k.panel=m.create({type:p?"panel":"floatpanel",role:"application",classes:"tinymce tinymce-inline",layout:"flex",direction:"column",align:"stretch",autohide:!1,autofix:!0,fixed:!!p,border:1,items:[l.menubar===!1?null:{type:"menubar",border:"0 0 1 0",items:d()},c(l.toolbar_items_size)]}),a.fire("BeforeRenderUI"),n.renderTo(p||document.body).reflow(),e(n),g(),h(),a.on("nodeChange",f),a.on("activate",g),a.on("deactivate",i),void a.nodeChanged())}var n,p;return l.fixed_toolbar_container&&(p=o.select(l.fixed_toolbar_container)[0]),l.content_editable=!0,a.on("focus",function(){b.skinUiCss?tinymce.DOM.styleSheetLoader.load(b.skinUiCss,j,j):j()}),a.on("blur hide",i),a.on("remove",function(){n&&(n.remove(),n=null)}),b.skinUiCss&&tinymce.DOM.styleSheetLoader.load(b.skinUiCss),{}}function j(b){function g(){return function(a){"readonly"==a.mode?i.find("*").disabled(!0):i.find("*").disabled(!1)}}var i,j,n;return b.skinUiCss&&tinymce.DOM.loadCSS(b.skinUiCss),i=k.panel=m.create({type:"panel",role:"application",classes:"tinymce",style:"visibility: hidden",layout:"stack",border:1,items:[l.menubar===!1?null:{type:"menubar",border:"0 0 1 0",items:d()},c(l.toolbar_items_size),{type:"panel",name:"iframe",layout:"stack",classes:"edit-area",html:"",border:"1 0 0 0"}]}),l.resize!==!1&&(j={type:"resizehandle",direction:l.resize,onResizeStart:function(){var b=a.getContentAreaContainer().firstChild;n={width:b.clientWidth,height:b.clientHeight}},onResize:function(a){"both"==l.resize?f(n.width+a.deltaX,n.height+a.deltaY):f(null,n.height+a.deltaY)}}),l.statusbar!==!1&&i.add({type:"panel",name:"statusbar",classes:"statusbar",layout:"flow",border:"1 0 0 0",ariaRoot:!0,items:[{type:"elementpath"},j]}),l.readonly&&i.find("*").disabled(!0),a.fire("BeforeRenderUI"),a.on("SwitchMode",g()),i.renderBefore(b.targetNode).reflow(),l.width&&tinymce.DOM.setStyle(i.getEl(),"width",l.width),a.on("remove",function(){i.remove(),i=null}),e(i),h(),{iframeContainer:i.find("#iframe")[0].getEl(),editorContainer:i.getEl()}}var k=this,l=a.settings,m=tinymce.ui.Factory,n=tinymce.each,o=tinymce.DOM,p=tinymce.geom.Rect,q=tinymce.ui.FloatPanel,r={file:{title:"File",items:"newdocument"},edit:{title:"Edit",items:"undo redo | cut copy paste pastetext | selectall"},insert:{title:"Insert",items:"|"},view:{title:"View",items:"visualaid |"},format:{title:"Format",items:"bold italic underline strikethrough superscript subscript | formats | removeformat"},table:{title:"Table"},tools:{title:"Tools"}},s="undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image";k.renderUI=function(b){var c=l.skin!==!1?l.skin||"lightgray":!1;if(c){var d=l.skin_url;d=d?a.documentBaseURI.toAbsolute(d):tinymce.baseURL+"/skins/"+c,tinymce.Env.documentMode<=7?b.skinUiCss=d+"/skin.ie7.min.css":b.skinUiCss=d+"/skin.min.css",a.contentCSS.push(d+"/content"+(a.inline?".inline":"")+".min.css")}return a.on("ProgressState",function(a){k.throbber=k.throbber||new tinymce.ui.Throbber(k.panel.getEl("body")),a.state?k.throbber.show(a.time):k.throbber.hide()}),l.inline?i(b):j(b)},k.resizeTo=f,k.resizeBy=g}); \ No newline at end of file diff --git a/assets/js/tinymce/tinymce.gzip.js b/assets/js/tinymce/tinymce.gzip.js new file mode 100644 index 0000000..8926bb0 --- /dev/null +++ b/assets/js/tinymce/tinymce.gzip.js @@ -0,0 +1 @@ +!function(){function n(n,e){function t(){o.parentNode.removeChild(o),o&&(o.onreadystatechange=o.onload=o=null),e()}function i(){"undefined"!=typeof console&&console.log&&console.log("Failed to load: "+n)}var o,a=document.getElementsByTagName("head")[0]||document.body;o=document.createElement("script"),o.type="text/javascript","onload"in o?(o.onload=t,a.appendChild(o),o.src=n):(o.onreadystatechange=function(){o.src&&/loaded|complete/.test(o.readyState)&&t()},o.src=n,a.appendChild(o)),o.onerror=i}function e(n,e,t){function i(n,e){if(e){for(var t=e.length-1;t>=0;t--)u[n+"_"+e[t]]?e.splice(t,1):u[n+"_"+e[t]]=!0;if(e.length)return"&"+n+"s="+e.join(",")}return""}var o="";return o+=i("plugin",e),o+=i("theme",n),o+=i("language",t),o&&(u.core?o+="&core=false":u.core=!0,o=r.baseURL+"/index.php?js=true"+o),o}function t(n){if("string"==typeof n)return n.split(/[, ]/);var e=[];if(n)for(var i=0;i=r.x&&o.x+o.w<=r.w+r.x&&o.y>=r.y&&o.y+o.h<=r.h+r.y)return i[a];return null}function n(e,t,n){return o(e.x-t,e.y-n,e.w+2*t,e.h+2*n)}function r(e,t){var n,r,i,a;return n=l(e.x,t.x),r=l(e.y,t.y),i=s(e.x+e.w,t.x+t.w),a=s(e.y+e.h,t.y+t.h),0>i-n||0>a-r?null:o(n,r,i-n,a-r)}function i(e,t,n){var r,i,a,s,c,u,d,f,h,p;return c=e.x,u=e.y,d=e.x+e.w,f=e.y+e.h,h=t.x+t.w,p=t.y+t.h,r=l(0,t.x-c),i=l(0,t.y-u),a=l(0,d-h),s=l(0,f-p),c+=r,u+=i,n&&(d+=r,f+=i,c-=a,u-=s),d-=a,f-=s,o(c,u,d-c,f-u)}function o(e,t,n,r){return{x:e,y:t,w:n,h:r}}function a(e){return o(e.left,e.top,e.width,e.height)}var s=Math.min,l=Math.max,c=Math.round;return{inflate:n,relativePosition:e,findBestRelativePosition:t,intersect:r,clamp:i,create:o,fromClientRect:a}}),r(c,[],function(){function e(e,t){return function(){e.apply(t,arguments)}}function t(t){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],s(t,e(r,this),e(i,this))}function n(e){var t=this;return null===this._state?void this._deferreds.push(e):void l(function(){var n=t._state?e.onFulfilled:e.onRejected;if(null===n)return void(t._state?e.resolve:e.reject)(t._value);var r;try{r=n(t._value)}catch(i){return void e.reject(i)}e.resolve(r)})}function r(t){try{if(t===this)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"==typeof t||"function"==typeof t)){var n=t.then;if("function"==typeof n)return void s(e(n,t),e(r,this),e(i,this))}this._state=!0,this._value=t,o.call(this)}catch(a){i.call(this,a)}}function i(e){this._state=!1,this._value=e,o.call(this)}function o(){for(var e=0,t=this._deferreds.length;t>e;e++)n.call(this,this._deferreds[e]);this._deferreds=null}function a(e,t,n,r){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.resolve=n,this.reject=r}function s(e,t,n){var r=!1;try{e(function(e){r||(r=!0,t(e))},function(e){r||(r=!0,n(e))})}catch(i){if(r)return;r=!0,n(i)}}if(window.Promise)return window.Promise;var l=t.immediateFn||"function"==typeof setImmediate&&setImmediate||function(e){setTimeout(e,1)},c=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};return t.prototype["catch"]=function(e){return this.then(null,e)},t.prototype.then=function(e,r){var i=this;return new t(function(t,o){n.call(i,new a(e,r,t,o))})},t.all=function(){var e=Array.prototype.slice.call(1===arguments.length&&c(arguments[0])?arguments[0]:arguments);return new t(function(t,n){function r(o,a){try{if(a&&("object"==typeof a||"function"==typeof a)){var s=a.then;if("function"==typeof s)return void s.call(a,function(e){r(o,e)},n)}e[o]=a,0===--i&&t(e)}catch(l){n(l)}}if(0===e.length)return t([]);for(var i=e.length,o=0;or;r++)e[r].then(t,n)})},t}),r(u,[c],function(e){function t(e,t){function n(e){window.setTimeout(e,0)}var r,i=window.requestAnimationFrame,o=["ms","moz","webkit"];for(r=0;rr;r++)if(o=n[r],o&&o.func.call(o.scope,e)===!1&&e.preventDefault(),e.isImmediatePropagationStopped())return}var o=this,s={},l,c,u,d,f;c=a+(+new Date).toString(32),d="onmouseenter"in document.documentElement,u="onfocusin"in document.documentElement,f={mouseenter:"mouseover",mouseleave:"mouseout"},l=1,o.domLoaded=!1,o.events=s,o.bind=function(n,a,h,p){function m(t){e(r(t||N.event),g)}var g,v,y,b,C,x,w,N=window;if(n&&3!==n.nodeType&&8!==n.nodeType){for(n[c]?g=n[c]:(g=l++,n[c]=g,s[g]={}),p=p||n,a=a.split(" "),y=a.length;y--;)b=a[y],x=m,C=w=!1,"DOMContentLoaded"===b&&(b="ready"),o.domLoaded&&"ready"===b&&"complete"==n.readyState?h.call(p,r({type:b})):(d||(C=f[b],C&&(x=function(t){var n,i;if(n=t.currentTarget,i=t.relatedTarget,i&&n.contains)i=n.contains(i);else for(;i&&i!==n;)i=i.parentNode;i||(t=r(t||N.event),t.type="mouseout"===t.type?"mouseleave":"mouseenter",t.target=n,e(t,g))})),u||"focusin"!==b&&"focusout"!==b||(w=!0,C="focusin"===b?"focus":"blur",x=function(t){t=r(t||N.event),t.type="focus"===t.type?"focusin":"focusout",e(t,g)}),v=s[g][b],v?"ready"===b&&o.domLoaded?h({type:b}):v.push({func:h,scope:p}):(s[g][b]=v=[{func:h,scope:p}],v.fakeName=C,v.capture=w,v.nativeHandler=x,"ready"===b?i(n,x,o):t(n,C||b,x,w)));return n=v=0,h}},o.unbind=function(e,t,r){var i,a,l,u,d,f;if(!e||3===e.nodeType||8===e.nodeType)return o;if(i=e[c]){if(f=s[i],t){for(t=t.split(" "),l=t.length;l--;)if(d=t[l],a=f[d]){if(r)for(u=a.length;u--;)if(a[u].func===r){var h=a.nativeHandler,p=a.fakeName,m=a.capture;a=a.slice(0,u).concat(a.slice(u+1)),a.nativeHandler=h,a.fakeName=p,a.capture=m,f[d]=a}r&&0!==a.length||(delete f[d],n(e,a.fakeName||d,a.nativeHandler,a.capture))}}else{for(d in f)a=f[d],n(e,a.fakeName||d,a.nativeHandler,a.capture);f={}}for(d in f)return o;delete s[i];try{delete e[c]}catch(g){e[c]=null}}return o},o.fire=function(t,n,i){var a;if(!t||3===t.nodeType||8===t.nodeType)return o;i=r(null,i),i.type=n,i.target=t;do a=t[c],a&&e(i,a),t=t.parentNode||t.ownerDocument||t.defaultView||t.parentWindow;while(t&&!i.isPropagationStopped());return o},o.clean=function(e){var t,n,r=o.unbind;if(!e||3===e.nodeType||8===e.nodeType)return o;if(e[c]&&r(e),e.getElementsByTagName||(e=e.document),e&&e.getElementsByTagName)for(r(e),n=e.getElementsByTagName("*"),t=n.length;t--;)e=n[t],e[c]&&r(e);return o},o.destroy=function(){s={}},o.cancel=function(e){return e&&(e.preventDefault(),e.stopImmediatePropagation()),!1}}var a="mce-data-",s=/^(?:mouse|contextmenu)|click/,l={keyLocation:1,layerX:1,layerY:1,returnValue:1,webkitMovementX:1,webkitMovementY:1};return o.Event=new o,o.Event.bind(window,"ready",function(){}),o}),r(f,[],function(){function e(e,t,n,r){var i,o,a,s,l,c,d,h,p,m;if((t?t.ownerDocument||t:z)!==D&&B(t),t=t||D,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(L&&!r){if(i=ve.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&I(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return Z.apply(n,t.getElementsByTagName(e)),n;if((a=i[3])&&x.getElementsByClassName)return Z.apply(n,t.getElementsByClassName(a)),n}if(x.qsa&&(!P||!P.test(e))){if(h=d=F,p=t,m=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){for(c=_(e),(d=t.getAttribute("id"))?h=d.replace(be,"\\$&"):t.setAttribute("id",h),h="[id='"+h+"'] ",l=c.length;l--;)c[l]=h+f(c[l]);p=ye.test(e)&&u(t.parentNode)||t,m=c.join(",")}if(m)try{return Z.apply(n,p.querySelectorAll(m)),n}catch(g){}finally{d||t.removeAttribute("id")}}}return k(e.replace(se,"$1"),t,n,r)}function n(){function e(n,r){return t.push(n+" ")>w.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[F]=!0,e}function i(e){var t=D.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=e.length;r--;)w.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||X)-(~e.sourceIndex||X);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function l(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function c(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function u(e){return e&&typeof e.getElementsByTagName!==Y&&e}function d(){}function f(e){for(var t=0,n=e.length,r="";n>t;t++)r+=e[t].value;return r}function h(e,t,n){var r=t.dir,i=n&&"parentNode"===r,o=V++;return t.first?function(t,n,o){for(;t=t[r];)if(1===t.nodeType||i)return e(t,n,o)}:function(t,n,a){var s,l,c=[W,o];if(a){for(;t=t[r];)if((1===t.nodeType||i)&&e(t,n,a))return!0}else for(;t=t[r];)if(1===t.nodeType||i){if(l=t[F]||(t[F]={}),(s=l[r])&&s[0]===W&&s[1]===o)return c[2]=s[2];if(l[r]=c,c[2]=e(t,n,a))return!0}}}function p(e){return e.length>1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function m(t,n,r){for(var i=0,o=n.length;o>i;i++)e(t,n[i],r);return r}function g(e,t,n,r,i){for(var o,a=[],s=0,l=e.length,c=null!=t;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),c&&t.push(s));return a}function v(e,t,n,i,o,a){return i&&!i[F]&&(i=v(i)),o&&!o[F]&&(o=v(o,a)),r(function(r,a,s,l){var c,u,d,f=[],h=[],p=a.length,v=r||m(t||"*",s.nodeType?[s]:s,[]),y=!e||!r&&t?v:g(v,f,e,s,l),b=n?o||(r?e:p||i)?[]:a:y;if(n&&n(y,b,s,l),i)for(c=g(b,h),i(c,[],s,l),u=c.length;u--;)(d=c[u])&&(b[h[u]]=!(y[h[u]]=d));if(r){if(o||e){if(o){for(c=[],u=b.length;u--;)(d=b[u])&&c.push(y[u]=d);o(null,b=[],c,l)}for(u=b.length;u--;)(d=b[u])&&(c=o?te.call(r,d):f[u])>-1&&(r[c]=!(a[c]=d))}}else b=g(b===a?b.splice(p,b.length):b),o?o(null,a,b,l):Z.apply(a,b)})}function y(e){for(var t,n,r,i=e.length,o=w.relative[e[0].type],a=o||w.relative[" "],s=o?1:0,l=h(function(e){return e===t},a,!0),c=h(function(e){return te.call(t,e)>-1},a,!0),u=[function(e,n,r){return!o&&(r||n!==T)||((t=n).nodeType?l(e,n,r):c(e,n,r))}];i>s;s++)if(n=w.relative[e[s].type])u=[h(p(u),n)];else{if(n=w.filter[e[s].type].apply(null,e[s].matches),n[F]){for(r=++s;i>r&&!w.relative[e[r].type];r++);return v(s>1&&p(u),s>1&&f(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(se,"$1"),n,r>s&&y(e.slice(s,r)),i>r&&y(e=e.slice(r)),i>r&&f(e))}u.push(n)}return p(u)}function b(t,n){var i=n.length>0,o=t.length>0,a=function(r,a,s,l,c){var u,d,f,h=0,p="0",m=r&&[],v=[],y=T,b=r||o&&w.find.TAG("*",c),C=W+=null==y?1:Math.random()||.1,x=b.length;for(c&&(T=a!==D&&a);p!==x&&null!=(u=b[p]);p++){if(o&&u){for(d=0;f=t[d++];)if(f(u,a,s)){l.push(u);break}c&&(W=C)}i&&((u=!f&&u)&&h--,r&&m.push(u))}if(h+=p,i&&p!==h){for(d=0;f=n[d++];)f(m,v,a,s);if(r){if(h>0)for(;p--;)m[p]||v[p]||(v[p]=J.call(l));v=g(v)}Z.apply(l,v),c&&!r&&v.length>0&&h+n.length>1&&e.uniqueSort(l)}return c&&(W=C,T=y),m};return i?r(a):a}var C,x,w,N,E,_,S,k,T,R,A,B,D,M,L,P,H,O,I,F="sizzle"+-new Date,z=window.document,W=0,V=0,U=n(),$=n(),q=n(),j=function(e,t){return e===t&&(A=!0),0},Y=typeof t,X=1<<31,K={}.hasOwnProperty,G=[],J=G.pop,Q=G.push,Z=G.push,ee=G.slice,te=G.indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(this[t]===e)return t;return-1},ne="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",re="[\\x20\\t\\r\\n\\f]",ie="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",oe="\\["+re+"*("+ie+")(?:"+re+"*([*^$|!~]?=)"+re+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+ie+"))|)"+re+"*\\]",ae=":("+ie+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+oe+")*)|.*)\\)|)",se=new RegExp("^"+re+"+|((?:^|[^\\\\])(?:\\\\.)*)"+re+"+$","g"),le=new RegExp("^"+re+"*,"+re+"*"),ce=new RegExp("^"+re+"*([>+~]|"+re+")"+re+"*"),ue=new RegExp("="+re+"*([^\\]'\"]*?)"+re+"*\\]","g"),de=new RegExp(ae),fe=new RegExp("^"+ie+"$"),he={ID:new RegExp("^#("+ie+")"),CLASS:new RegExp("^\\.("+ie+")"),TAG:new RegExp("^("+ie+"|[*])"),ATTR:new RegExp("^"+oe),PSEUDO:new RegExp("^"+ae),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+re+"*(even|odd|(([+-]|)(\\d*)n|)"+re+"*(?:([+-]|)"+re+"*(\\d+)|))"+re+"*\\)|)","i"),bool:new RegExp("^(?:"+ne+")$","i"),needsContext:new RegExp("^"+re+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+re+"*((?:-\\d)?\\d*)"+re+"*\\)|)(?=[^-]|$)","i")},pe=/^(?:input|select|textarea|button)$/i,me=/^h\d$/i,ge=/^[^{]+\{\s*\[native \w/,ve=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ye=/[+~]/,be=/'|\\/g,Ce=new RegExp("\\\\([\\da-f]{1,6}"+re+"?|("+re+")|.)","ig"),xe=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)};try{Z.apply(G=ee.call(z.childNodes),z.childNodes),G[z.childNodes.length].nodeType}catch(we){Z={apply:G.length?function(e,t){Q.apply(e,ee.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}x=e.support={},E=e.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},B=e.setDocument=function(e){var t,n=e?e.ownerDocument||e:z,r=n.defaultView;return n!==D&&9===n.nodeType&&n.documentElement?(D=n,M=n.documentElement,L=!E(n),r&&r!==r.top&&(r.addEventListener?r.addEventListener("unload",function(){B()},!1):r.attachEvent&&r.attachEvent("onunload",function(){B()})),x.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),x.getElementsByTagName=i(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),x.getElementsByClassName=ge.test(n.getElementsByClassName),x.getById=i(function(e){return M.appendChild(e).id=F,!n.getElementsByName||!n.getElementsByName(F).length}),x.getById?(w.find.ID=function(e,t){if(typeof t.getElementById!==Y&&L){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},w.filter.ID=function(e){var t=e.replace(Ce,xe);return function(e){return e.getAttribute("id")===t}}):(delete w.find.ID,w.filter.ID=function(e){var t=e.replace(Ce,xe);return function(e){var n=typeof e.getAttributeNode!==Y&&e.getAttributeNode("id");return n&&n.value===t}}),w.find.TAG=x.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==Y?t.getElementsByTagName(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},w.find.CLASS=x.getElementsByClassName&&function(e,t){return L?t.getElementsByClassName(e):void 0},H=[],P=[],(x.qsa=ge.test(n.querySelectorAll))&&(i(function(e){e.innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&P.push("[*^$]="+re+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||P.push("\\["+re+"*(?:value|"+ne+")"),e.querySelectorAll(":checked").length||P.push(":checked")}),i(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&P.push("name"+re+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||P.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),P.push(",.*:")})),(x.matchesSelector=ge.test(O=M.matches||M.webkitMatchesSelector||M.mozMatchesSelector||M.oMatchesSelector||M.msMatchesSelector))&&i(function(e){x.disconnectedMatch=O.call(e,"div"),O.call(e,"[s!='']:x"),H.push("!=",ae)}),P=P.length&&new RegExp(P.join("|")),H=H.length&&new RegExp(H.join("|")),t=ge.test(M.compareDocumentPosition),I=t||ge.test(M.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return A=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r?r:(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&r||!x.sortDetached&&t.compareDocumentPosition(e)===r?e===n||e.ownerDocument===z&&I(z,e)?-1:t===n||t.ownerDocument===z&&I(z,t)?1:R?te.call(R,e)-te.call(R,t):0:4&r?-1:1)}:function(e,t){if(e===t)return A=!0,0;var r,i=0,o=e.parentNode,s=t.parentNode,l=[e],c=[t];if(!o||!s)return e===n?-1:t===n?1:o?-1:s?1:R?te.call(R,e)-te.call(R,t):0;if(o===s)return a(e,t);for(r=e;r=r.parentNode;)l.unshift(r);for(r=t;r=r.parentNode;)c.unshift(r);for(;l[i]===c[i];)i++;return i?a(l[i],c[i]):l[i]===z?-1:c[i]===z?1:0},n):D},e.matches=function(t,n){return e(t,null,null,n)},e.matchesSelector=function(t,n){if((t.ownerDocument||t)!==D&&B(t),n=n.replace(ue,"='$1']"),x.matchesSelector&&L&&(!H||!H.test(n))&&(!P||!P.test(n)))try{var r=O.call(t,n);if(r||x.disconnectedMatch||t.document&&11!==t.document.nodeType)return r}catch(i){}return e(n,D,null,[t]).length>0},e.contains=function(e,t){return(e.ownerDocument||e)!==D&&B(e),I(e,t)},e.attr=function(e,n){(e.ownerDocument||e)!==D&&B(e);var r=w.attrHandle[n.toLowerCase()],i=r&&K.call(w.attrHandle,n.toLowerCase())?r(e,n,!L):t;return i!==t?i:x.attributes||!L?e.getAttribute(n):(i=e.getAttributeNode(n))&&i.specified?i.value:null},e.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},e.uniqueSort=function(e){var t,n=[],r=0,i=0;if(A=!x.detectDuplicates,R=!x.sortStable&&e.slice(0),e.sort(j),A){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return R=null,e},N=e.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=N(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=N(t);return n},w=e.selectors={cacheLength:50,createPseudo:r,match:he,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Ce,xe),e[3]=(e[3]||e[4]||e[5]||"").replace(Ce,xe),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(t){return t[1]=t[1].toLowerCase(),"nth"===t[1].slice(0,3)?(t[3]||e.error(t[0]),t[4]=+(t[4]?t[5]+(t[6]||1):2*("even"===t[3]||"odd"===t[3])),t[5]=+(t[7]+t[8]||"odd"===t[3])):t[3]&&e.error(t[0]),t},PSEUDO:function(e){var t,n=!e[6]&&e[2];return he.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&de.test(n)&&(t=_(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Ce,xe).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=U[e+" "];return t||(t=new RegExp("(^|"+re+")"+e+"("+re+"|$)"))&&U(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==Y&&e.getAttribute("class")||"")})},ATTR:function(t,n,r){return function(i){var o=e.attr(i,t);return null==o?"!="===n:n?(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o+" ").indexOf(r)>-1:"|="===n?o===r||o.slice(0,r.length+1)===r+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var c,u,d,f,h,p,m=o!==a?"nextSibling":"previousSibling",g=t.parentNode,v=s&&t.nodeName.toLowerCase(),y=!l&&!s;if(g){if(o){for(;m;){for(d=t;d=d[m];)if(s?d.nodeName.toLowerCase()===v:1===d.nodeType)return!1;p=m="only"===e&&!p&&"nextSibling"}return!0}if(p=[a?g.firstChild:g.lastChild],a&&y){for(u=g[F]||(g[F]={}),c=u[e]||[],h=c[0]===W&&c[1],f=c[0]===W&&c[2],d=h&&g.childNodes[h];d=++h&&d&&d[m]||(f=h=0)||p.pop();)if(1===d.nodeType&&++f&&d===t){u[e]=[W,h,f];break}}else if(y&&(c=(t[F]||(t[F]={}))[e])&&c[0]===W)f=c[1];else for(;(d=++h&&d&&d[m]||(f=h=0)||p.pop())&&((s?d.nodeName.toLowerCase()!==v:1!==d.nodeType)||!++f||(y&&((d[F]||(d[F]={}))[e]=[W,f]),d!==t)););return f-=i,f===r||f%r===0&&f/r>=0}}},PSEUDO:function(t,n){var i,o=w.pseudos[t]||w.setFilters[t.toLowerCase()]||e.error("unsupported pseudo: "+t);return o[F]?o(n):o.length>1?(i=[t,t,"",n],w.setFilters.hasOwnProperty(t.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=te.call(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=S(e.replace(se,"$1"));return i[F]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),!n.pop()}}),has:r(function(t){return function(n){return e(t,n).length>0}}),contains:r(function(e){return e=e.replace(Ce,xe),function(t){return(t.textContent||t.innerText||N(t)).indexOf(e)>-1}}),lang:r(function(t){return fe.test(t||"")||e.error("unsupported lang: "+t),t=t.replace(Ce,xe).toLowerCase(),function(e){var n;do if(n=L?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return n=n.toLowerCase(),n===t||0===n.indexOf(t+"-");while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=window.location&&window.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===M},focus:function(e){return e===D.activeElement&&(!D.hasFocus||D.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!w.pseudos.empty(e)},header:function(e){return me.test(e.nodeName)},input:function(e){return pe.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:c(function(){return[0]}),last:c(function(e,t){return[t-1]}),eq:c(function(e,t,n){return[0>n?n+t:n]}),even:c(function(e,t){for(var n=0;t>n;n+=2)e.push(n);return e}),odd:c(function(e,t){for(var n=1;t>n;n+=2)e.push(n);return e}),lt:c(function(e,t,n){for(var r=0>n?n+t:n;--r>=0;)e.push(r);return e}),gt:c(function(e,t,n){for(var r=0>n?n+t:n;++r2&&"ID"===(a=o[0]).type&&x.getById&&9===t.nodeType&&L&&w.relative[o[1].type]){if(t=(w.find.ID(a.matches[0].replace(Ce,xe),t)||[])[0],!t)return n;c&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=he.needsContext.test(e)?0:o.length;i--&&(a=o[i],!w.relative[s=a.type]);)if((l=w.find[s])&&(r=l(a.matches[0].replace(Ce,xe),ye.test(o[0].type)&&u(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&f(o),!e)return Z.apply(n,r),n;break}}return(c||S(e,d))(r,t,!L,n,ye.test(e)&&u(t.parentNode)||t),n},x.sortStable=F.split("").sort(j).join("")===F,x.detectDuplicates=!!A,B(),x.sortDetached=i(function(e){return 1&e.compareDocumentPosition(D.createElement("div"))}),i(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){return n?void 0:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),x.attributes&&i(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?void 0:e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(ne,function(e,t,n){var r;return n?void 0:e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),e}),r(h,[],function(){var e=navigator,t=e.userAgent,n,r,i,o,a,s,l,c,u,d;n=window.opera&&window.opera.buildNumber,u=/Android/.test(t),r=/WebKit/.test(t),i=!r&&!n&&/MSIE/gi.test(t)&&/Explorer/gi.test(e.appName),i=i&&/MSIE (\w+)\./.exec(t)[1],o=-1==t.indexOf("Trident/")||-1==t.indexOf("rv:")&&-1==e.appName.indexOf("Netscape")?!1:11,a=-1==t.indexOf("Edge/")||i||o?!1:12,i=i||o||a,s=!r&&!o&&/Gecko/.test(t),l=-1!=t.indexOf("Mac"),c=/(iPad|iPhone)/.test(t),d="FormData"in window&&"FileReader"in window&&"URL"in window&&!!URL.createObjectURL,a&&(r=!1);var f=!c||d||t.match(/AppleWebKit\/(\d*)/)[1]>=534;return{ +opera:n,webkit:r,ie:i,gecko:s,mac:l,iOS:c,android:u,contentEditable:f,transparentSrc:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",caretAfter:8!=i,range:window.getSelection&&"Range"in window,documentMode:i&&!a?document.documentMode||7:10,fileApi:d,ceFalse:i===!1||i>8}}),r(p,[],function(){function e(e){var t=e,n,r;if(!u(e))for(t=[],n=0,r=e.length;r>n;n++)t[n]=e[n];return t}function n(e,n,r){var i,o;if(!e)return 0;if(r=r||e,e.length!==t){for(i=0,o=e.length;o>i;i++)if(n.call(r,e[i],i,e)===!1)return 0}else for(i in e)if(e.hasOwnProperty(i)&&n.call(r,e[i],i,e)===!1)return 0;return 1}function r(e,t){var r=[];return n(e,function(n,i){r.push(t(n,i,e))}),r}function i(e,t){var r=[];return n(e,function(n,i){(!t||t(n,i,e))&&r.push(n)}),r}function o(e,t){var n,r;if(e)for(n=0,r=e.length;r>n;n++)if(e[n]===t)return n;return-1}function a(e,t,n,r){var i=0;for(arguments.length<3&&(n=e[0]);ir;r++)if(t.call(n,e[r],r,e))return r;return-1}function l(e,n,r){var i=s(e,n,r);return-1!==i?e[i]:t}function c(e){return e[e.length-1]}var u=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};return{isArray:u,toArray:e,each:n,map:r,filter:i,indexOf:o,reduce:a,findIndex:s,find:l,last:c}}),r(m,[h,p],function(e,n){function r(e){return null===e||e===t?"":(""+e).replace(h,"")}function i(e,r){return r?"array"==r&&n.isArray(e)?!0:typeof e==r:e!==t}function o(e,t,n){var r;for(e=e||[],t=t||",","string"==typeof e&&(e=e.split(t)),n=n||{},r=e.length;r--;)n[e[r]]={};return n}function a(e,t,n){var r=this,i,o,a,s,l,c=0;if(e=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(e),a=e[3].match(/(^|\.)(\w+)$/i)[2],o=r.createNS(e[3].replace(/\.\w+$/,""),n),!o[a]){if("static"==e[2])return o[a]=t,void(this.onCreate&&this.onCreate(e[2],e[3],o[a]));t[a]||(t[a]=function(){},c=1),o[a]=t[a],r.extend(o[a].prototype,t),e[5]&&(i=r.resolve(e[5]).prototype,s=e[5].match(/\.(\w+)$/i)[1],l=o[a],c?o[a]=function(){return i[s].apply(this,arguments)}:o[a]=function(){return this.parent=i[s],l.apply(this,arguments)},o[a].prototype[a]=o[a],r.each(i,function(e,t){o[a].prototype[t]=i[t]}),r.each(t,function(e,t){i[t]?o[a].prototype[t]=function(){return this.parent=i[t],e.apply(this,arguments)}:t!=a&&(o[a].prototype[t]=e)})),r.each(t["static"],function(e,t){o[a][t]=e})}}function s(e,n){var r,i,o,a=arguments,s;for(r=1,i=a.length;i>r;r++){n=a[r];for(o in n)n.hasOwnProperty(o)&&(s=n[o],s!==t&&(e[o]=s))}return e}function l(e,t,r,i){i=i||this,e&&(r&&(e=e[r]),n.each(e,function(e,n){return t.call(i,e,n,r)===!1?!1:void l(e,t,r,i)}))}function c(e,t){var n,r;for(t=t||window,e=e.split("."),n=0;nn&&(t=t[e[n]],t);n++);return t}function d(e,t){return!e||i(e,"array")?e:n.map(e.split(t||","),r)}function f(t){var n=e.cacheSuffix;return n&&(t+=(-1===t.indexOf("?")?"?":"&")+n),t}var h=/^\s*|\s*$/g;return{trim:r,isArray:n.isArray,is:i,toArray:n.toArray,makeMap:o,each:n.each,map:n.map,grep:n.filter,inArray:n.indexOf,extend:s,create:a,walk:l,createNS:c,resolve:u,explode:d,_addCacheSuffix:f}}),r(g,[d,f,m,h],function(e,n,r,i){function o(e){return"undefined"!=typeof e}function a(e){return"string"==typeof e}function s(e){return e&&e==e.window}function l(e,t){var n,r,i;for(t=t||w,i=t.createElement("div"),n=t.createDocumentFragment(),i.innerHTML=e;r=i.firstChild;)n.appendChild(r);return n}function c(e,t,n,r){var i;if(a(t))t=l(t,v(e[0]));else if(t.length&&!t.nodeType){if(t=f.makeArray(t),r)for(i=t.length-1;i>=0;i--)c(e,t[i],n,r);else for(i=0;ii&&(a=e[i],t.call(a,i,a)!==!1);i++);return e}function g(e,t){var n=[];return m(e,function(e,r){t(r,e)&&n.push(r)}),n}function v(e){return e?9==e.nodeType?e:e.ownerDocument:w}function y(e,n,r){var i=[],o=e[n];for("string"!=typeof r&&r instanceof f&&(r=r[0]);o&&9!==o.nodeType;){if(r!==t){if(o===r)break;if("string"==typeof r&&f(o).is(r))break}1===o.nodeType&&i.push(o),o=o[n]}return i}function b(e,n,r,i){var o=[];for(i instanceof f&&(i=i[0]);e;e=e[n])if(!r||e.nodeType===r){if(i!==t){if(e===i)break;if("string"==typeof i&&f(e).is(i))break}o.push(e)}return o}function C(e,t,n){for(e=e[t];e;e=e[t])if(e.nodeType==n)return e;return null}function x(e,t,n){m(n,function(n,r){e[n]=e[n]||{},e[n][t]=r})}var w=document,N=Array.prototype.push,E=Array.prototype.slice,_=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,S=e.Event,k,T=r.makeMap("children,contents,next,prev"),R=r.makeMap("fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom"," "),A=r.makeMap("checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected"," "),B={"for":"htmlFor","class":"className",readonly:"readOnly"},D={"float":"cssFloat"},M={},L={},P=/^\s*|\s*$/g;return f.fn=f.prototype={constructor:f,selector:"",context:null,length:0,init:function(e,t){var n=this,r,i;if(!e)return n;if(e.nodeType)return n.context=n[0]=e,n.length=1,n;if(t&&t.nodeType)n.context=t;else{if(t)return f(e).attr(t);n.context=t=document}if(a(e)){if(n.selector=e,r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:_.exec(e),!r)return f(t).find(e);if(r[1])for(i=l(e,v(t)).firstChild;i;)N.call(n,i),i=i.nextSibling;else{if(i=v(t).getElementById(r[2]),!i)return n;if(i.id!==r[2])return n.find(e);n.length=1,n[0]=i}}else this.add(e,!1);return n},toArray:function(){return r.toArray(this)},add:function(e,t){var n=this,r,i;if(a(e))return n.add(f(e));if(t!==!1)for(r=f.unique(n.toArray().concat(f.makeArray(e))),n.length=r.length,i=0;it;t++)f.find(e,this[t],r);return f(r)},filter:function(e){return f("function"==typeof e?g(this.toArray(),function(t,n){return e(n,t)}):f.filter(e,this.toArray()))},closest:function(e){var t=[];return e instanceof f&&(e=e[0]),this.each(function(n,r){for(;r;){if("string"==typeof e&&f(r).is(e)){t.push(r);break}if(r==e){t.push(r);break}r=r.parentNode}}),f(t)},offset:function(e){var t,n,r,i=0,o=0,a;return e?this.css(e):(t=this[0],t&&(n=t.ownerDocument,r=n.documentElement,t.getBoundingClientRect&&(a=t.getBoundingClientRect(),i=a.left+(r.scrollLeft||n.body.scrollLeft)-r.clientLeft,o=a.top+(r.scrollTop||n.body.scrollTop)-r.clientTop)),{left:i,top:o})},push:N,sort:[].sort,splice:[].splice},r.extend(f,{extend:r.extend,makeArray:function(e){return s(e)||e.nodeType?[e]:r.toArray(e)},inArray:h,isArray:r.isArray,each:m,trim:p,grep:g,find:n,expr:n.selectors,unique:n.uniqueSort,text:n.getText,contains:n.contains,filter:function(e,t,n){var r=t.length;for(n&&(e=":not("+e+")");r--;)1!=t[r].nodeType&&t.splice(r,1);return t=1===t.length?f.find.matchesSelector(t[0],e)?[t[0]]:[]:f.find.matches(e,t)}}),m({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return y(e,"parentNode")},next:function(e){return C(e,"nextSibling",1)},prev:function(e){return C(e,"previousSibling",1)},children:function(e){return b(e.firstChild,"nextSibling",1)},contents:function(e){return r.toArray(("iframe"===e.nodeName?e.contentDocument||e.contentWindow.document:e).childNodes)}},function(e,t){f.fn[e]=function(n){var r=this,i=[];return r.each(function(){var e=t.call(i,this,n,i);e&&(f.isArray(e)?i.push.apply(i,e):i.push(e))}),this.length>1&&(T[e]||(i=f.unique(i)),0===e.indexOf("parents")&&(i=i.reverse())),i=f(i),n?i.filter(n):i}}),m({parentsUntil:function(e,t){return y(e,"parentNode",t)},nextUntil:function(e,t){return b(e,"nextSibling",1,t).slice(1)},prevUntil:function(e,t){return b(e,"previousSibling",1,t).slice(1)}},function(e,t){f.fn[e]=function(n,r){var i=this,o=[];return i.each(function(){var e=t.call(o,this,n,o);e&&(f.isArray(e)?o.push.apply(o,e):o.push(e))}),this.length>1&&(o=f.unique(o),(0===e.indexOf("parents")||"prevUntil"===e)&&(o=o.reverse())),o=f(o),r?o.filter(r):o}}),f.fn.is=function(e){return!!e&&this.filter(e).length>0},f.fn.init.prototype=f.fn,f.overrideDefaults=function(e){function t(r,i){return n=n||e(),0===arguments.length&&(r=n.element),i||(i=n.context),new t.fn.init(r,i)}var n;return f.extend(t,this),t},i.ie&&i.ie<8&&(x(M,"get",{maxlength:function(e){var t=e.maxLength;return 2147483647===t?k:t},size:function(e){var t=e.size;return 20===t?k:t},"class":function(e){return e.className},style:function(e){var t=e.style.cssText;return 0===t.length?k:t}}),x(M,"set",{"class":function(e,t){e.className=t},style:function(e,t){e.style.cssText=t}})),i.ie&&i.ie<9&&(D["float"]="styleFloat",x(L,"set",{opacity:function(e,t){var n=e.style;null===t||""===t?n.removeAttribute("filter"):(n.zoom=1,n.filter="alpha(opacity="+100*t+")")}})),f.attrHooks=M,f.cssHooks=L,f}),r(v,[],function(){return function(e,t){function n(e,t,n,r){function i(e){return e=parseInt(e,10).toString(16),e.length>1?e:"0"+e}return"#"+i(t)+i(n)+i(r)}var r=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,i=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,o=/\s*([^:]+):\s*([^;]+);?/g,a=/\s+$/,s,l,c={},u,d,f,h="\ufeff";for(e=e||{},t&&(d=t.getValidStyles(),f=t.getInvalidStyles()),u=("\\\" \\' \\; \\: ; : "+h).split(" "),l=0;l-1&&n||(m[e+t]=-1==l?s[0]:s.join(" "),delete m[e+"-top"+t],delete m[e+"-right"+t],delete m[e+"-bottom"+t],delete m[e+"-left"+t])}}function u(e){var t=m[e],n;if(t){for(t=t.split(" "),n=t.length;n--;)if(t[n]!==t[0])return!1;return m[e]=t[0],!0}}function d(e,t,n,r){u(t)&&u(n)&&u(r)&&(m[e]=m[t]+" "+m[n]+" "+m[r],delete m[t],delete m[n],delete m[r])}function f(e){return b=!0,c[e]}function h(e,t){return b&&(e=e.replace(/\uFEFF[0-9]/g,function(e){return c[e]})),t||(e=e.replace(/\\([\'\";:])/g,"$1")),e}function p(t,n,r,i,o,a){if(o=o||a)return o=h(o),"'"+o.replace(/\'/g,"\\'")+"'";if(n=h(n||r||i),!e.allow_script_urls){var s=n.replace(/[\s\r\n]+/,"");if(/(java|vb)script:/i.test(s))return"";if(!e.allow_svg_data_urls&&/^data:image\/svg/i.test(s))return""}return C&&(n=C.call(x,n,"style")),"url('"+n.replace(/\'/g,"\\'")+"')"}var m={},g,v,y,b,C=e.url_converter,x=e.url_converter_scope||this;if(t){for(t=t.replace(/[\u0000-\u001F]/g,""),t=t.replace(/\\[\"\';:\uFEFF]/g,f).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(e){return e.replace(/[;:]/g,f)});g=o.exec(t);){if(v=g[1].replace(a,"").toLowerCase(),y=g[2].replace(a,""),y=y.replace(/\\[0-9a-f]+/g,function(e){return String.fromCharCode(parseInt(e.substr(1),16))}),v&&y.length>0){if(!e.allow_script_urls&&("behavior"==v||/expression\s*\(|\/\*|\*\//.test(y)))continue;"font-weight"===v&&"700"===y?y="bold":("color"===v||"background-color"===v)&&(y=y.toLowerCase()),y=y.replace(r,n),y=y.replace(i,p),m[v]=b?h(y,!0):y}o.lastIndex=g.index+g[0].length}s("border","",!0),s("border","-width"),s("border","-color"),s("border","-style"),s("padding",""),s("margin",""),d("border","border-width","border-style","border-color"),"medium none"===m.border&&delete m.border,"none"===m["border-image"]&&delete m["border-image"]}return m},serialize:function(e,t){function n(t){var n,r,o,a;if(n=d[t])for(r=0,o=n.length;o>r;r++)t=n[r],a=e[t],a!==s&&a.length>0&&(i+=(i.length>0?" ":"")+t+": "+a+";")}function r(e,t){var n;return n=f["*"],n&&n[e]?!1:(n=f[t],n&&n[e]?!1:!0)}var i="",o,a;if(t&&d)n("*"),n(t);else for(o in e)a=e[o],a!==s&&a.length>0&&(!f||r(o,t))&&(i+=(i.length>0?" ":"")+o+": "+a+";");return i}}}}),r(y,[],function(){return function(e,t){function n(e,n,r,i){var o,a;if(e){if(!i&&e[n])return e[n];if(e!=t){if(o=e[r])return o;for(a=e.parentNode;a&&a!=t;a=a.parentNode)if(o=a[r])return o}}}var r=e;this.current=function(){return r},this.next=function(e){return r=n(r,"firstChild","nextSibling",e)},this.prev=function(e){return r=n(r,"lastChild","previousSibling",e)}}}),r(b,[m],function(e){function t(n){function r(){return P.createDocumentFragment()}function i(e,t){N(F,e,t)}function o(e,t){N(z,e,t)}function a(e){i(e.parentNode,j(e))}function s(e){i(e.parentNode,j(e)+1)}function l(e){o(e.parentNode,j(e))}function c(e){o(e.parentNode,j(e)+1)}function u(e){e?(L[U]=L[V],L[$]=L[W]):(L[V]=L[U],L[W]=L[$]),L.collapsed=F}function d(e){a(e),c(e)}function f(e){i(e,0),o(e,1===e.nodeType?e.childNodes.length:e.nodeValue.length)}function h(e,t){var n=L[V],r=L[W],i=L[U],o=L[$],a=t.startContainer,s=t.startOffset,l=t.endContainer,c=t.endOffset;return 0===e?w(n,r,a,s):1===e?w(i,o,a,s):2===e?w(i,o,l,c):3===e?w(n,r,l,c):void 0}function p(){E(I)}function m(){return E(H)}function g(){return E(O)}function v(e){var t=this[V],r=this[W],i,o;3!==t.nodeType&&4!==t.nodeType||!t.nodeValue?(t.childNodes.length>0&&(o=t.childNodes[r]),o?t.insertBefore(e,o):3==t.nodeType?n.insertAfter(e,t):t.appendChild(e)):r?r>=t.nodeValue.length?n.insertAfter(e,t):(i=t.splitText(r),t.parentNode.insertBefore(e,i)):t.parentNode.insertBefore(e,t)}function y(e){var t=L.extractContents();L.insertNode(e),e.appendChild(t),L.selectNode(e)}function b(){return q(new t(n),{startContainer:L[V],startOffset:L[W],endContainer:L[U],endOffset:L[$],collapsed:L.collapsed,commonAncestorContainer:L.commonAncestorContainer})}function C(e,t){var n;if(3==e.nodeType)return e;if(0>t)return e;for(n=e.firstChild;n&&t>0;)--t,n=n.nextSibling;return n?n:e}function x(){return L[V]==L[U]&&L[W]==L[$]}function w(e,t,r,i){var o,a,s,l,c,u;if(e==r)return t==i?0:i>t?-1:1;for(o=r;o&&o.parentNode!=e;)o=o.parentNode;if(o){for(a=0,s=e.firstChild;s!=o&&t>a;)a++,s=s.nextSibling;return a>=t?-1:1}for(o=e;o&&o.parentNode!=r;)o=o.parentNode;if(o){for(a=0,s=r.firstChild;s!=o&&i>a;)a++,s=s.nextSibling;return i>a?-1:1}for(l=n.findCommonAncestor(e,r),c=e;c&&c.parentNode!=l;)c=c.parentNode;for(c||(c=l),u=r;u&&u.parentNode!=l;)u=u.parentNode;if(u||(u=l),c==u)return 0;for(s=l.firstChild;s;){if(s==c)return-1;if(s==u)return 1;s=s.nextSibling}}function N(e,t,r){var i,o;for(e?(L[V]=t,L[W]=r):(L[U]=t,L[$]=r),i=L[U];i.parentNode;)i=i.parentNode;for(o=L[V];o.parentNode;)o=o.parentNode;o==i?w(L[V],L[W],L[U],L[$])>0&&L.collapse(e):L.collapse(e),L.collapsed=x(),L.commonAncestorContainer=n.findCommonAncestor(L[V],L[U])}function E(e){var t,n=0,r=0,i,o,a,s,l,c;if(L[V]==L[U])return _(e);for(t=L[U],i=t.parentNode;i;t=i,i=i.parentNode){if(i==L[V])return S(t,e);++n}for(t=L[V],i=t.parentNode;i;t=i,i=i.parentNode){if(i==L[U])return k(t,e);++r}for(o=r-n,a=L[V];o>0;)a=a.parentNode,o--;for(s=L[U];0>o;)s=s.parentNode,o++;for(l=a.parentNode,c=s.parentNode;l!=c;l=l.parentNode,c=c.parentNode)a=l,s=c;return T(a,s,e)}function _(e){var t,n,i,o,a,s,l,c,u;if(e!=I&&(t=r()),L[W]==L[$])return t;if(3==L[V].nodeType){if(n=L[V].nodeValue,i=n.substring(L[W],L[$]),e!=O&&(o=L[V],c=L[W],u=L[$]-L[W],0===c&&u>=o.nodeValue.length-1?o.parentNode.removeChild(o):o.deleteData(c,u),L.collapse(F)),e==I)return;return i.length>0&&t.appendChild(P.createTextNode(i)),t}for(o=C(L[V],L[W]),a=L[$]-L[W];o&&a>0;)s=o.nextSibling,l=D(o,e),t&&t.appendChild(l),--a,o=s;return e!=O&&L.collapse(F),t}function S(e,t){var n,i,o,a,s,l;if(t!=I&&(n=r()),i=R(e,t),n&&n.appendChild(i),o=j(e),a=o-L[W],0>=a)return t!=O&&(L.setEndBefore(e),L.collapse(z)),n;for(i=e.previousSibling;a>0;)s=i.previousSibling,l=D(i,t),n&&n.insertBefore(l,n.firstChild),--a,i=s;return t!=O&&(L.setEndBefore(e),L.collapse(z)),n}function k(e,t){var n,i,o,a,s,l;for(t!=I&&(n=r()),o=A(e,t),n&&n.appendChild(o),i=j(e),++i,a=L[$]-i,o=e.nextSibling;o&&a>0;)s=o.nextSibling,l=D(o,t),n&&n.appendChild(l),--a,o=s;return t!=O&&(L.setStartAfter(e),L.collapse(F)),n}function T(e,t,n){var i,o,a,s,l,c,u;for(n!=I&&(o=r()),i=A(e,n),o&&o.appendChild(i),a=j(e),s=j(t),++a,l=s-a,c=e.nextSibling;l>0;)u=c.nextSibling,i=D(c,n),o&&o.appendChild(i),c=u,--l;return i=R(t,n),o&&o.appendChild(i),n!=O&&(L.setStartAfter(e),L.collapse(F)),o}function R(e,t){var n=C(L[U],L[$]-1),r,i,o,a,s,l=n!=L[U];if(n==e)return B(n,l,z,t);for(r=n.parentNode,i=B(r,z,z,t);r;){for(;n;)o=n.previousSibling,a=B(n,l,z,t),t!=I&&i.insertBefore(a,i.firstChild),l=F,n=o;if(r==e)return i;n=r.previousSibling,r=r.parentNode,s=B(r,z,z,t),t!=I&&s.appendChild(i),i=s}}function A(e,t){var n=C(L[V],L[W]),r=n!=L[V],i,o,a,s,l;if(n==e)return B(n,r,F,t);for(i=n.parentNode,o=B(i,z,F,t);i;){for(;n;)a=n.nextSibling,s=B(n,r,F,t),t!=I&&o.appendChild(s),r=F,n=a;if(i==e)return o;n=i.nextSibling,i=i.parentNode,l=B(i,z,F,t),t!=I&&l.appendChild(o),o=l}}function B(e,t,r,i){var o,a,s,l,c;if(t)return D(e,i);if(3==e.nodeType){if(o=e.nodeValue,r?(l=L[W],a=o.substring(l),s=o.substring(0,l)):(l=L[$],a=o.substring(0,l),s=o.substring(l)),i!=O&&(e.nodeValue=s),i==I)return;return c=n.clone(e,z),c.nodeValue=a,c}if(i!=I)return n.clone(e,z)}function D(e,t){return t!=I?t==O?n.clone(e,F):e:void e.parentNode.removeChild(e)}function M(){return n.create("body",null,g()).outerText}var L=this,P=n.doc,H=0,O=1,I=2,F=!0,z=!1,W="startOffset",V="startContainer",U="endContainer",$="endOffset",q=e.extend,j=n.nodeIndex;return q(L,{startContainer:P,startOffset:0,endContainer:P,endOffset:0,collapsed:F,commonAncestorContainer:P,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:i,setEnd:o,setStartBefore:a,setStartAfter:s,setEndBefore:l,setEndAfter:c,collapse:u,selectNode:d,selectNodeContents:f,compareBoundaryPoints:h,deleteContents:p,extractContents:m,cloneContents:g,insertNode:v,surroundContents:y,cloneRange:b,toStringIE:M}),L}return t.prototype.toString=function(){return this.toStringIE()},t}),r(C,[m],function(e){function t(e){var t;return t=document.createElement("div"),t.innerHTML=e,t.textContent||t.innerText||e}function n(e,t){var n,r,i,a={};if(e){for(e=e.split(","),t=t||10,n=0;n\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,l=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,c=/[<>&\"\']/g,u=/&#([a-z0-9]+);?|&([a-z0-9]+);/gi,d={128:"\u20ac",130:"\u201a",131:"\u0192",132:"\u201e",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02c6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017d",145:"\u2018",146:"\u2019",147:"\u201c",148:"\u201d",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02dc",153:"\u2122",154:"\u0161",155:"\u203a",156:"\u0153",158:"\u017e",159:"\u0178"};o={'"':""","'":"'","<":"<",">":">","&":"&","`":"`"},a={"<":"<",">":">","&":"&",""":'"',"'":"'"},i=n("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",32);var f={encodeRaw:function(e,t){return e.replace(t?s:l,function(e){return o[e]||e})},encodeAllRaw:function(e){return(""+e).replace(c,function(e){return o[e]||e})},encodeNumeric:function(e,t){return e.replace(t?s:l,function(e){return e.length>1?"&#"+(1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536)+";":o[e]||"&#"+e.charCodeAt(0)+";"})},encodeNamed:function(e,t,n){return n=n||i,e.replace(t?s:l,function(e){return o[e]||n[e]||e})},getEncodeFunc:function(e,t){function a(e,n){return e.replace(n?s:l,function(e){return o[e]||t[e]||"&#"+e.charCodeAt(0)+";"||e})}function c(e,n){return f.encodeNamed(e,n,t)}return t=n(t)||i,e=r(e.replace(/\+/g,",")),e.named&&e.numeric?a:e.named?t?c:f.encodeNamed:e.numeric?f.encodeNumeric:f.encodeRaw},decode:function(e){return e.replace(u,function(e,n){return n?(n="x"===n.charAt(0).toLowerCase()?parseInt(n.substr(1),16):parseInt(n,10),n>65535?(n-=65536,String.fromCharCode(55296+(n>>10),56320+(1023&n))):d[n]||String.fromCharCode(n)):a[e]||i[e]||t(e)})}};return f}),r(x,[m,u],function(e,t){return function(n,r){function i(e){n.getElementsByTagName("head")[0].appendChild(e)}function o(r,o,c){function u(){for(var e=b.passed,t=e.length;t--;)e[t]();b.status=2,b.passed=[],b.failed=[]}function d(){for(var e=b.failed,t=e.length;t--;)e[t]();b.status=3,b.passed=[],b.failed=[]}function f(){var e=navigator.userAgent.match(/WebKit\/(\d*)/);return!!(e&&e[1]<536)}function h(e,n){e()||((new Date).getTime()-y0)return v=n.createElement("style"),v.textContent='@import "'+r+'"',m(),void i(v);p()}i(g),g.href=r}}var a=0,s={},l;r=r||{},l=r.maxLoadTime||5e3,this.load=o}}),r(w,[f,g,v,d,y,b,C,h,m,x],function(e,n,r,i,o,a,s,l,c,u){function d(e,t){var n={},r=t.keep_values,i;return i={set:function(n,r,i){t.url_converter&&(r=t.url_converter.call(t.url_converter_scope||e,r,i,n[0])),n.attr("data-mce-"+i,r).attr(i,r)},get:function(e,t){return e.attr("data-mce-"+t)||e.attr(t)}},n={style:{set:function(e,t){return null!==t&&"object"==typeof t?void e.css(t):(r&&e.attr("data-mce-style",t),void e.attr("style",t))},get:function(t){var n=t.attr("data-mce-style")||t.attr("style");return n=e.serializeStyle(e.parseStyle(n),t[0].nodeName)}}},r&&(n.href=n.src=i),n}function f(e,t){var n=t.attr("style");n=e.serializeStyle(e.parseStyle(n),t[0].nodeName),n||(n=null),t.attr("data-mce-style",n)}function h(e,t){var n=0,r,i;if(e)for(r=e.nodeType,e=e.previousSibling;e;e=e.previousSibling)i=e.nodeType,(!t||3!=i||i!=r&&e.nodeValue.length)&&(n++,r=i);return n}function p(e,t){var o=this,a;o.doc=e,o.win=window,o.files={},o.counter=0,o.stdMode=!b||e.documentMode>=8,o.boxModel=!b||"CSS1Compat"==e.compatMode||o.stdMode,o.styleSheetLoader=new u(e),o.boundEvents=[],o.settings=t=t||{},o.schema=t.schema,o.styles=new r({url_converter:t.url_converter,url_converter_scope:t.url_converter_scope},t.schema),o.fixDoc(e),o.events=t.ownEvents?new i(t.proxy):i.Event,o.attrHooks=d(o,t),a=t.schema?t.schema.getBlockElements():{},o.$=n.overrideDefaults(function(){return{context:e,element:o.getRoot()}}),o.isBlock=function(e){if(!e)return!1;var t=e.nodeType;return t?!(1!==t||!a[e.nodeName]):!!a[e]}}var m=c.each,g=c.is,v=c.grep,y=c.trim,b=l.ie,C=/^([a-z0-9],?)+$/i,x=/^[ \t\r\n]*$/;return p.prototype={$$:function(e){return"string"==typeof e&&(e=this.get(e)),this.$(e)},root:null,fixDoc:function(e){var t=this.settings,n;if(b&&t.schema){"abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video".replace(/\w+/g,function(t){e.createElement(t)});for(n in t.schema.getCustomElements())e.createElement(n)}},clone:function(e,t){var n=this,r,i;return!b||1!==e.nodeType||t?e.cloneNode(t):(i=n.doc,t?r.firstChild:(r=i.createElement(e.nodeName),m(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),r))},getRoot:function(){var e=this;return e.settings.root_element||e.doc.body},getViewPort:function(e){var t,n;return e=e?e:this.win,t=e.document,n=this.boxModel?t.documentElement:t.body,{x:e.pageXOffset||n.scrollLeft,y:e.pageYOffset||n.scrollTop,w:e.innerWidth||n.clientWidth,h:e.innerHeight||n.clientHeight}},getRect:function(e){var t=this,n,r;return e=t.get(e),n=t.getPos(e),r=t.getSize(e),{x:n.x,y:n.y,w:r.w,h:r.h}},getSize:function(e){var t=this,n,r;return e=t.get(e),n=t.getStyle(e,"width"),r=t.getStyle(e,"height"),-1===n.indexOf("px")&&(n=0),-1===r.indexOf("px")&&(r=0),{w:parseInt(n,10)||e.offsetWidth||e.clientWidth,h:parseInt(r,10)||e.offsetHeight||e.clientHeight}},getParent:function(e,t,n){return this.getParents(e,t,n,!1)},getParents:function(e,n,r,i){var o=this,a,s=[];for(e=o.get(e),i=i===t,r=r||("BODY"!=o.getRoot().nodeName?o.getRoot().parentNode:null),g(n,"string")&&(a=n,n="*"===n?function(e){return 1==e.nodeType}:function(e){return o.is(e,a)});e&&e!=r&&e.nodeType&&9!==e.nodeType;){if(!n||n(e)){if(!i)return e;s.push(e)}e=e.parentNode}return i?s:null},get:function(e){var t;return e&&this.doc&&"string"==typeof e&&(t=e,e=this.doc.getElementById(e),e&&e.id!==t)?this.doc.getElementsByName(t)[1]:e},getNext:function(e,t){return this._findSib(e,t,"nextSibling")},getPrev:function(e,t){return this._findSib(e,t,"previousSibling")},select:function(t,n){var r=this;return e(t,r.get(n)||r.settings.root_element||r.doc,[])},is:function(n,r){var i;if(n.length===t){if("*"===r)return 1==n.nodeType;if(C.test(r)){for(r=r.toLowerCase().split(/,/),n=n.nodeName.toLowerCase(),i=r.length-1;i>=0;i--)if(r[i]==n)return!0;return!1}}if(n.nodeType&&1!=n.nodeType)return!1;var o=n.nodeType?[n]:n;return e(r,o[0].ownerDocument||o[0],null,o).length>0},add:function(e,t,n,r,i){var o=this;return this.run(e,function(e){var a;return a=g(t,"string")?o.doc.createElement(t):t,o.setAttribs(a,n),r&&(r.nodeType?a.appendChild(r):o.setHTML(a,r)),i?a:e.appendChild(a)})},create:function(e,t,n){return this.add(this.doc.createElement(e),e,t,n,1); +},createHTML:function(e,t,n){var r="",i;r+="<"+e;for(i in t)t.hasOwnProperty(i)&&null!==t[i]&&"undefined"!=typeof t[i]&&(r+=" "+i+'="'+this.encode(t[i])+'"');return"undefined"!=typeof n?r+">"+n+"":r+" />"},createFragment:function(e){var t,n,r=this.doc,i;for(i=r.createElement("div"),t=r.createDocumentFragment(),e&&(i.innerHTML=e);n=i.firstChild;)t.appendChild(n);return t},remove:function(e,t){return e=this.$$(e),t?e.each(function(){for(var e;e=this.firstChild;)3==e.nodeType&&0===e.data.length?this.removeChild(e):this.parentNode.insertBefore(e,this)}).remove():e.remove(),e.length>1?e.toArray():e[0]},setStyle:function(e,t,n){e=this.$$(e).css(t,n),this.settings.update_styles&&f(this,e)},getStyle:function(e,n,r){return e=this.$$(e),r?e.css(n):(n=n.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}),"float"==n&&(n=l.ie&&l.ie<12?"styleFloat":"cssFloat"),e[0]&&e[0].style?e[0].style[n]:t)},setStyles:function(e,t){e=this.$$(e).css(t),this.settings.update_styles&&f(this,e)},removeAllAttribs:function(e){return this.run(e,function(e){var t,n=e.attributes;for(t=n.length-1;t>=0;t--)e.removeAttributeNode(n.item(t))})},setAttrib:function(e,t,n){var r=this,i,o,a=r.settings;""===n&&(n=null),e=r.$$(e),i=e.attr(t),e.length&&(o=r.attrHooks[t],o&&o.set?o.set(e,n,t):e.attr(t,n),i!=n&&a.onSetAttrib&&a.onSetAttrib({attrElm:e,attrName:t,attrValue:n}))},setAttribs:function(e,t){var n=this;n.$$(e).each(function(e,r){m(t,function(e,t){n.setAttrib(r,t,e)})})},getAttrib:function(e,t,n){var r=this,i,o;return e=r.$$(e),e.length&&(i=r.attrHooks[t],o=i&&i.get?i.get(e,t):e.attr(t)),"undefined"==typeof o&&(o=n||""),o},getPos:function(e,t){var r=this,i=0,o=0,a,s=r.doc,l=s.body,c;if(e=r.get(e),t=t||l,e){if(t===l&&e.getBoundingClientRect&&"static"===n(l).css("position"))return c=e.getBoundingClientRect(),t=r.boxModel?s.documentElement:l,i=c.left+(s.documentElement.scrollLeft||l.scrollLeft)-t.clientLeft,o=c.top+(s.documentElement.scrollTop||l.scrollTop)-t.clientTop,{x:i,y:o};for(a=e;a&&a!=t&&a.nodeType;)i+=a.offsetLeft||0,o+=a.offsetTop||0,a=a.offsetParent;for(a=e.parentNode;a&&a!=t&&a.nodeType;)i-=a.scrollLeft||0,o-=a.scrollTop||0,a=a.parentNode}return{x:i,y:o}},parseStyle:function(e){return this.styles.parse(e)},serializeStyle:function(e,t){return this.styles.serialize(e,t)},addStyle:function(e){var t=this,n=t.doc,r,i;if(t!==p.DOM&&n===document){var o=p.DOM.addedStyles;if(o=o||[],o[e])return;o[e]=!0,p.DOM.addedStyles=o}i=n.getElementById("mceDefaultStyles"),i||(i=n.createElement("style"),i.id="mceDefaultStyles",i.type="text/css",r=n.getElementsByTagName("head")[0],r.firstChild?r.insertBefore(i,r.firstChild):r.appendChild(i)),i.styleSheet?i.styleSheet.cssText+=e:i.appendChild(n.createTextNode(e))},loadCSS:function(e){var t=this,n=t.doc,r;return t!==p.DOM&&n===document?void p.DOM.loadCSS(e):(e||(e=""),r=n.getElementsByTagName("head")[0],void m(e.split(","),function(e){var i;e=c._addCacheSuffix(e),t.files[e]||(t.files[e]=!0,i=t.create("link",{rel:"stylesheet",href:e}),b&&n.documentMode&&n.recalc&&(i.onload=function(){n.recalc&&n.recalc(),i.onload=null}),r.appendChild(i))}))},addClass:function(e,t){this.$$(e).addClass(t)},removeClass:function(e,t){this.toggleClass(e,t,!1)},hasClass:function(e,t){return this.$$(e).hasClass(t)},toggleClass:function(e,t,r){this.$$(e).toggleClass(t,r).each(function(){""===this.className&&n(this).attr("class",null)})},show:function(e){this.$$(e).show()},hide:function(e){this.$$(e).hide()},isHidden:function(e){return"none"==this.$$(e).css("display")},uniqueId:function(e){return(e?e:"mce_")+this.counter++},setHTML:function(e,t){e=this.$$(e),b?e.each(function(e,r){if(r.canHaveHTML!==!1){for(;r.firstChild;)r.removeChild(r.firstChild);try{r.innerHTML="
    "+t,r.removeChild(r.firstChild)}catch(i){n("
    ").html("
    "+t).contents().slice(1).appendTo(r)}return t}}):e.html(t)},getOuterHTML:function(e){return e=this.get(e),1==e.nodeType&&"outerHTML"in e?e.outerHTML:n("
    ").append(n(e).clone()).html()},setOuterHTML:function(e,t){var r=this;r.$$(e).each(function(){try{if("outerHTML"in this)return void(this.outerHTML=t)}catch(e){}r.remove(n(this).html(t),!0)})},decode:s.decode,encode:s.encodeAllRaw,insertAfter:function(e,t){return t=this.get(t),this.run(e,function(e){var n,r;return n=t.parentNode,r=t.nextSibling,r?n.insertBefore(e,r):n.appendChild(e),e})},replace:function(e,t,n){var r=this;return r.run(t,function(t){return g(t,"array")&&(e=e.cloneNode(!0)),n&&m(v(t.childNodes),function(t){e.appendChild(t)}),t.parentNode.replaceChild(e,t)})},rename:function(e,t){var n=this,r;return e.nodeName!=t.toUpperCase()&&(r=n.create(t),m(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),n.replace(r,e,1)),r||e},findCommonAncestor:function(e,t){for(var n=e,r;n;){for(r=t;r&&n!=r;)r=r.parentNode;if(n==r)break;n=n.parentNode}return!n&&e.ownerDocument?e.ownerDocument.documentElement:n},toHex:function(e){return this.styles.toHex(c.trim(e))},run:function(e,t,n){var r=this,i;return"string"==typeof e&&(e=r.get(e)),e?(n=n||this,e.nodeType||!e.length&&0!==e.length?t.call(n,e):(i=[],m(e,function(e,o){e&&("string"==typeof e&&(e=r.get(e)),i.push(t.call(n,e,o)))}),i)):!1},getAttribs:function(e){var t;if(e=this.get(e),!e)return[];if(b){if(t=[],"OBJECT"==e.nodeName)return e.attributes;"OPTION"===e.nodeName&&this.getAttrib(e,"selected")&&t.push({specified:1,nodeName:"selected"});var n=/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi;return e.cloneNode(!1).outerHTML.replace(n,"").replace(/[\w:\-]+/gi,function(e){t.push({specified:1,nodeName:e})}),t}return e.attributes},isEmpty:function(e,t){var n=this,r,i,a,s,l,c=0;if(e=e.firstChild){s=new o(e,e.parentNode),t=t||(n.schema?n.schema.getNonEmptyElements():null);do{if(a=e.nodeType,1===a){if(e.getAttribute("data-mce-bogus"))continue;if(l=e.nodeName.toLowerCase(),t&&t[l]){if("br"===l){c++;continue}return!1}for(i=n.getAttribs(e),r=i.length;r--;)if(l=i[r].nodeName,"name"===l||"data-mce-bookmark"===l)return!1}if(8==a)return!1;if(3===a&&!x.test(e.nodeValue))return!1}while(e=s.next())}return 1>=c},createRng:function(){var e=this.doc;return e.createRange?e.createRange():new a(this)},nodeIndex:h,split:function(e,t,n){function r(e){function t(e){var t=e.previousSibling&&"SPAN"==e.previousSibling.nodeName,n=e.nextSibling&&"SPAN"==e.nextSibling.nodeName;return t&&n}var n,o=e.childNodes,a=e.nodeType;if(1!=a||"bookmark"!=e.getAttribute("data-mce-type")){for(n=o.length-1;n>=0;n--)r(o[n]);if(9!=a){if(3==a&&e.nodeValue.length>0){var s=y(e.nodeValue).length;if(!i.isBlock(e.parentNode)||s>0||0===s&&t(e))return}else if(1==a&&(o=e.childNodes,1==o.length&&o[0]&&1==o[0].nodeType&&"bookmark"==o[0].getAttribute("data-mce-type")&&e.parentNode.insertBefore(o[0],e),o.length||/^(br|hr|input|img)$/i.test(e.nodeName)))return;i.remove(e)}return e}}var i=this,o=i.createRng(),a,s,l;return e&&t?(o.setStart(e.parentNode,i.nodeIndex(e)),o.setEnd(t.parentNode,i.nodeIndex(t)),a=o.extractContents(),o=i.createRng(),o.setStart(t.parentNode,i.nodeIndex(t)+1),o.setEnd(e.parentNode,i.nodeIndex(e)+1),s=o.extractContents(),l=e.parentNode,l.insertBefore(r(a),e),n?l.insertBefore(n,e):l.insertBefore(t,e),l.insertBefore(r(s),e),i.remove(e),n||t):void 0},bind:function(e,t,n,r){var i=this;if(c.isArray(e)){for(var o=e.length;o--;)e[o]=i.bind(e[o],t,n,r);return e}return!i.settings.collect||e!==i.doc&&e!==i.win||i.boundEvents.push([e,t,n,r]),i.events.bind(e,t,n,r||i)},unbind:function(e,t,n){var r=this,i;if(c.isArray(e)){for(i=e.length;i--;)e[i]=r.unbind(e[i],t,n);return e}if(r.boundEvents&&(e===r.doc||e===r.win))for(i=r.boundEvents.length;i--;){var o=r.boundEvents[i];e!=o[0]||t&&t!=o[1]||n&&n!=o[2]||this.events.unbind(o[0],o[1],o[2])}return this.events.unbind(e,t,n)},fire:function(e,t,n){return this.events.fire(e,t,n)},getContentEditable:function(e){var t;return e&&1==e.nodeType?(t=e.getAttribute("data-mce-contenteditable"),t&&"inherit"!==t?t:"inherit"!==e.contentEditable?e.contentEditable:null):null},getContentEditableParent:function(e){for(var t=this.getRoot(),n=null;e&&e!==t&&(n=this.getContentEditable(e),null===n);e=e.parentNode);return n},destroy:function(){var t=this;if(t.boundEvents){for(var n=t.boundEvents.length;n--;){var r=t.boundEvents[n];this.events.unbind(r[0],r[1],r[2])}t.boundEvents=null}e.setDocument&&e.setDocument(),t.win=t.doc=t.root=t.events=t.frag=null},isChildOf:function(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1},dumpRng:function(e){return"startContainer: "+e.startContainer.nodeName+", startOffset: "+e.startOffset+", endContainer: "+e.endContainer.nodeName+", endOffset: "+e.endOffset},_findSib:function(e,t,n){var r=this,i=t;if(e)for("string"==typeof i&&(i=function(e){return r.is(e,t)}),e=e[n];e;e=e[n])if(i(e))return e;return null}},p.DOM=new p(document),p.nodeIndex=h,p}),r(N,[w,m],function(e,t){function n(){function e(e,n){function i(){a.remove(l),s&&(s.onreadystatechange=s.onload=s=null),n()}function o(){"undefined"!=typeof console&&console.log&&console.log("Failed to load: "+e)}var a=r,s,l;l=a.uniqueId(),s=document.createElement("script"),s.id=l,s.type="text/javascript",s.src=t._addCacheSuffix(e),"onreadystatechange"in s?s.onreadystatechange=function(){/loaded|complete/.test(s.readyState)&&i()}:s.onload=i,s.onerror=o,(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}var n=0,a=1,s=2,l={},c=[],u={},d=[],f=0,h;this.isDone=function(e){return l[e]==s},this.markDone=function(e){l[e]=s},this.add=this.load=function(e,t,r){var i=l[e];i==h&&(c.push(e),l[e]=n),t&&(u[e]||(u[e]=[]),u[e].push({func:t,scope:r||this}))},this.loadQueue=function(e,t){this.loadScripts(c,e,t)},this.loadScripts=function(t,n,r){function c(e){i(u[e],function(e){e.func.call(e.scope)}),u[e]=h}var p;d.push({func:n,scope:r||this}),(p=function(){var n=o(t);t.length=0,i(n,function(t){return l[t]==s?void c(t):void(l[t]!=a&&(l[t]=a,f++,e(t,function(){l[t]=s,f--,c(t),p()})))}),f||(i(d,function(e){e.func.call(e.scope)}),d.length=0)})()}}var r=e.DOM,i=t.each,o=t.grep;return n.ScriptLoader=new n,n}),r(E,[N,m],function(e,n){function r(){var e=this;e.items=[],e.urls={},e.lookup={}}var i=n.each;return r.prototype={get:function(e){return this.lookup[e]?this.lookup[e].instance:t},dependencies:function(e){var t;return this.lookup[e]&&(t=this.lookup[e].dependencies),t||[]},requireLangPack:function(t,n){var i=r.language;if(i&&r.languageLoad!==!1){if(n)if(n=","+n+",",-1!=n.indexOf(","+i.substr(0,2)+","))i=i.substr(0,2);else if(-1==n.indexOf(","+i+","))return;e.ScriptLoader.add(this.urls[t]+"/langs/"+i+".js")}},add:function(e,t,n){return this.items.push(t),this.lookup[e]={instance:t,dependencies:n},t},createUrl:function(e,t){return"object"==typeof t?t:{prefix:e.prefix,resource:t,suffix:e.suffix}},addComponents:function(t,n){var r=this.urls[t];i(n,function(t){e.ScriptLoader.add(r+"/"+t)})},load:function(n,o,a,s){function l(){var r=c.dependencies(n);i(r,function(e){var n=c.createUrl(o,e);c.load(n.resource,n,t,t)}),a&&(s?a.call(s):a.call(e))}var c=this,u=o;c.urls[n]||("object"==typeof o&&(u=o.prefix+o.resource+o.suffix),0!==u.indexOf("/")&&-1==u.indexOf("://")&&(u=r.baseURL+"/"+u),c.urls[n]=u.substring(0,u.lastIndexOf("/")),c.lookup[n]?l():e.ScriptLoader.add(u,l,s))}},r.PluginManager=new r,r.ThemeManager=new r,r}),r(_,[],function(){function e(e){return function(t){return!!t&&t.nodeType==e}}function t(e){return e=e.toLowerCase().split(" "),function(t){var n,r;if(t&&t.nodeType)for(r=t.nodeName.toLowerCase(),n=0;nn.length-1?t=n.length-1:0>t&&(t=0),n[t]||e}function o(e){this.walk=function(t,n){function r(e){var t;return t=e[0],3===t.nodeType&&t===c&&u>=t.nodeValue.length&&e.splice(0,1),t=e[e.length-1],0===f&&e.length>0&&t===d&&3===t.nodeType&&e.splice(e.length-1,1),e}function o(e,t,n){for(var r=[];e&&e!=n;e=e[t])r.push(e);return r}function a(e,t){do{if(e.parentNode==t)return e;e=e.parentNode}while(e)}function l(e,t,i){var a=i?"nextSibling":"previousSibling";for(g=e,v=g.parentNode;g&&g!=t;g=v)v=g.parentNode,y=o(g==e?g:g[a],a),y.length&&(i||y.reverse(),n(r(y)))}var c=t.startContainer,u=t.startOffset,d=t.endContainer,f=t.endOffset,h,p,m,g,v,y,b;if(b=e.select("td.mce-item-selected,th.mce-item-selected"),b.length>0)return void s(b,function(e){n([e])});if(1==c.nodeType&&c.hasChildNodes()&&(c=c.childNodes[u]),1==d.nodeType&&d.hasChildNodes()&&(d=i(d,f)),c==d)return n(r([c]));for(h=e.findCommonAncestor(c,d),g=c;g;g=g.parentNode){if(g===d)return l(c,h,!0);if(g===h)break}for(g=d;g;g=g.parentNode){if(g===c)return l(d,h);if(g===h)break}p=a(c,h)||c,m=a(d,h)||d,l(c,p,!0),y=o(p==c?p:p.nextSibling,"nextSibling",m==d?m.nextSibling:m),y.length&&n(r(y)),l(d,m)},this.split=function(e){function t(e,t){return e.splitText(t)}var n=e.startContainer,r=e.startOffset,i=e.endContainer,o=e.endOffset;return n==i&&3==n.nodeType?r>0&&rr?(o-=r,n=i=t(i,o).previousSibling,o=i.nodeValue.length,r=0):o=0):(3==n.nodeType&&r>0&&r0&&o0)return h=v,p=n?v.nodeValue.length:0,void(i=!0);if(e.isBlock(v)||y[v.nodeName.toLowerCase()])return;s=v}o&&s&&(h=s,i=!0,p=0)}var h,p,m,g=e.getRoot(),v,y,b,C;if(h=n[(r?"start":"end")+"Container"],p=n[(r?"start":"end")+"Offset"],C=1==h.nodeType&&p===h.childNodes.length,y=e.schema.getNonEmptyElements(),b=r,!c(h)){if(1==h.nodeType&&p>h.childNodes.length-1&&(b=!1),9===h.nodeType&&(h=e.getRoot(),p=0),h===g){if(b&&(v=h.childNodes[p>0?p-1:0])){if(c(v))return;if(y[v.nodeName]||"TABLE"==v.nodeName)return}if(h.hasChildNodes()){if(p=Math.min(!b&&p>0?p-1:p,h.childNodes.length-1),h=h.childNodes[p],p=0,u(h)||c(h))return;if(h.hasChildNodes()&&!/TABLE/.test(h.nodeName)){v=h,m=new t(h,g);do{if(l(v)||c(v)){i=!1;break}if(3===v.nodeType&&v.nodeValue.length>0){p=b?0:v.nodeValue.length,h=v,i=!0;break}if(y[v.nodeName.toLowerCase()]&&!a(v)){p=e.nodeIndex(v),h=v.parentNode,"IMG"!=v.nodeName||b||p++,i=!0;break}}while(v=b?m.next():m.prev())}}}o&&(3===h.nodeType&&0===p&&f(!0),1===h.nodeType&&(v=h.childNodes[p],v||(v=h.childNodes[p-1]),!v||"BR"!==v.nodeName||d(v,"A")||s(v)||s(v,!0)||f(!0,v))),b&&!o&&3===h.nodeType&&p===h.nodeValue.length&&f(!1),i&&n["set"+(r?"Start":"End")](h,p)}}var i,o;return o=n.collapsed,r(!0),o||r(),i&&o&&n.collapse(!0),i}}function a(t,n,r){var i,o,a;if(i=r.elementFromPoint(t,n),o=r.body.createTextRange(),"HTML"==i.tagName&&(i=r.body),o.moveToElementText(i),a=e.toArray(o.getClientRects()),a=a.sort(function(e,t){return e=Math.abs(Math.max(e.top-n,e.bottom-n)),t=Math.abs(Math.max(t.top-n,t.bottom-n)),e-t}),a.length>0){n=(a[0].bottom+a[0].top)/2;try{return o.moveToPoint(t,n),o.collapse(!0),o}catch(s){}}return null}var s=e.each,l=n.isContentEditableFalse,c=r.isCaretContainer;return o.compareRanges=function(e,t){if(e&&t){if(!e.item&&!e.duplicate)return e.startContainer==t.startContainer&&e.startOffset==t.startOffset;if(e.item&&t.item&&e.item(0)===t.item(0))return!0;if(e.isEqual&&t.isEqual&&t.isEqual(e))return!0}return!1},o.getCaretRangeFromPoint=function(e,t,n){var r,i;if(n.caretPositionFromPoint)i=n.caretPositionFromPoint(e,t),r=n.createRange(),r.setStart(i.offsetNode,i.offset),r.collapse(!0);else if(n.caretRangeFromPoint)r=n.caretRangeFromPoint(e,t);else if(n.body.createTextRange){r=n.body.createTextRange();try{r.moveToPoint(e,t),r.collapse(!0)}catch(o){r=a(e,t,n)}}return r},o.getSelectedNode=function(e){var t=e.startContainer,n=e.startOffset;return t.hasChildNodes()&&e.endOffset==n+1?t.childNodes[n]:null},o.getNode=function(e,t){return 1==e.nodeType&&e.hasChildNodes()&&(t>=e.childNodes.length&&(t=e.childNodes.length-1),e=e.childNodes[t]),e},o}),r(R,[T,h,u],function(e,t,n){return function(r){function i(e){var t,n;if(n=r.$(e).parentsUntil(r.getBody()).add(e),n.length===a.length){for(t=n.length;t>=0&&n[t]===a[t];t--);if(-1===t)return a=n,!0}return a=n,!1}var o,a=[];"onselectionchange"in r.getDoc()||r.on("NodeChange Click MouseUp KeyUp Focus",function(t){var n,i;n=r.selection.getRng(),i={startContainer:n.startContainer,startOffset:n.startOffset,endContainer:n.endContainer,endOffset:n.endOffset},"nodechange"!=t.type&&e.compareRanges(i,o)||r.fire("SelectionChange"),o=i}),r.on("contextmenu",function(){r.fire("SelectionChange")}),r.on("SelectionChange",function(){var e=r.selection.getStart(!0);(t.range||!r.selection.isCollapsed())&&!i(e)&&r.dom.isChildOf(e,r.getBody())&&r.nodeChanged({selectionChange:!0})}),r.on("MouseUp",function(e){e.isDefaultPrevented()||("IMG"==r.selection.getNode().nodeName?n.setEditorTimeout(r,function(){r.nodeChanged()}):r.nodeChanged())}),this.nodeChanged=function(e){var t=r.selection,n,i,o;r.initialized&&t&&!r.settings.disable_nodechange&&!r.readonly&&(o=r.getBody(),n=t.getStart()||o,n=n.ownerDocument!=r.getDoc()?r.getBody():n,"IMG"==n.nodeName&&t.isCollapsed()&&(n=n.parentNode),i=[],r.dom.getParent(n,function(e){return e===o?!0:void i.push(e)}),e=e||{},e.element=n,e.parents=i,r.fire("NodeChange",e))}}}),r(A,[],function(){function e(e,t,n){var r,i,o=n?"lastChild":"firstChild",a=n?"prev":"next";if(e[o])return e[o];if(e!==t){if(r=e[a])return r;for(i=e.parent;i&&i!==t;i=i.parent)if(r=i[a])return r}}function t(e,t){this.name=e,this.type=t,1===t&&(this.attributes=[],this.attributes.map={})}var n=/^[ \t\r\n]*$/,r={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};return t.prototype={replace:function(e){var t=this;return e.parent&&e.remove(),t.insert(e,t),t.remove(),t},attr:function(e,t){var n=this,r,i,o;if("string"!=typeof e){for(i in e)n.attr(i,e[i]);return n}if(r=n.attributes){if(t!==o){if(null===t){if(e in r.map)for(delete r.map[e],i=r.length;i--;)if(r[i].name===e)return r=r.splice(i,1),n;return n}if(e in r.map){for(i=r.length;i--;)if(r[i].name===e){r[i].value=t;break}}else r.push({name:e,value:t});return r.map[e]=t,n}return r.map[e]}},clone:function(){var e=this,n=new t(e.name,e.type),r,i,o,a,s;if(o=e.attributes){for(s=[],s.map={},r=0,i=o.length;i>r;r++)a=o[r],"id"!==a.name&&(s[s.length]={name:a.name,value:a.value},s.map[a.name]=a.value);n.attributes=s}return n.value=e.value,n.shortEnded=e.shortEnded,n},wrap:function(e){var t=this;return t.parent.insert(e,t),e.append(t),t},unwrap:function(){var e=this,t,n;for(t=e.firstChild;t;)n=t.next,e.insert(t,e,!0),t=n;e.remove()},remove:function(){var e=this,t=e.parent,n=e.next,r=e.prev;return t&&(t.firstChild===e?(t.firstChild=n,n&&(n.prev=null)):r.next=n,t.lastChild===e?(t.lastChild=r,r&&(r.next=null)):n.prev=r,e.parent=e.next=e.prev=null),e},append:function(e){var t=this,n;return e.parent&&e.remove(),n=t.lastChild,n?(n.next=e,e.prev=n,t.lastChild=e):t.lastChild=t.firstChild=e,e.parent=t,e},insert:function(e,t,n){var r;return e.parent&&e.remove(),r=t.parent||this,n?(t===r.firstChild?r.firstChild=e:t.prev.next=e,e.prev=t.prev,e.next=t,t.prev=e):(t===r.lastChild?r.lastChild=e:t.next.prev=e,e.next=t.next,e.prev=t,t.next=e),e.parent=r,e},getAll:function(t){var n=this,r,i=[];for(r=n.firstChild;r;r=e(r,n))r.name===t&&i.push(r);return i},empty:function(){var t=this,n,r,i;if(t.firstChild){for(n=[],i=t.firstChild;i;i=e(i,t))n.push(i);for(r=n.length;r--;)i=n[r],i.parent=i.firstChild=i.lastChild=i.next=i.prev=null}return t.firstChild=t.lastChild=null,t},isEmpty:function(t){var r=this,i=r.firstChild,o,a;if(i)do{if(1===i.type){if(i.attributes.map["data-mce-bogus"])continue;if(t[i.name])return!1;for(o=i.attributes.length;o--;)if(a=i.attributes[o].name,"name"===a||0===a.indexOf("data-mce-bookmark"))return!1}if(8===i.type)return!1;if(3===i.type&&!n.test(i.value))return!1}while(i=e(i,r));return!0},walk:function(t){return e(this,null,t)}},t.create=function(e,n){var i,o;if(i=new t(e,r[e]||1),n)for(o in n)i.attr(o,n[o]);return i},t}),r(B,[m],function(e){function t(e,t){return e?e.split(t||" "):[]}function n(e){function n(e,n,r){function i(e,t){var n={},r,i;for(r=0,i=e.length;i>r;r++)n[e[r]]=t||{};return n}var s,c,u,d=arguments;for(r=r||[],n=n||"","string"==typeof r&&(r=t(r)),c=3;co;o++)i.attributes[n[o]]={},i.attributesOrder.push(n[o])}var a={},l,c,u,d,f,h;return i[e]?i[e]:(l=t("id accesskey class dir lang style tabindex title"),c=t("address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul"),u=t("a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd label map noscript object q s samp script select small span strong sub sup textarea u var #text #comment"),"html4"!=e&&(l.push.apply(l,t("contenteditable contextmenu draggable dropzone hidden spellcheck translate")),c.push.apply(c,t("article aside details dialog figure header footer hgroup section nav")),u.push.apply(u,t("audio canvas command datalist mark meter output picture progress time wbr video ruby bdi keygen"))),"html5-strict"!=e&&(l.push("xml:lang"),h=t("acronym applet basefont big font strike tt"),u.push.apply(u,h),s(h,function(e){n(e,"",u)}),f=t("center dir isindex noframes"),c.push.apply(c,f),d=[].concat(c,u),s(f,function(e){n(e,"",d)})),d=d||[].concat(c,u),n("html","manifest","head body"),n("head","","base command link meta noscript script style title"),n("title hr noscript br"),n("base","href target"),n("link","href rel media hreflang type sizes hreflang"),n("meta","name http-equiv content charset"),n("style","media type scoped"),n("script","src async defer type charset"),n("body","onafterprint onbeforeprint onbeforeunload onblur onerror onfocus onhashchange onload onmessage onoffline ononline onpagehide onpageshow onpopstate onresize onscroll onstorage onunload",d),n("address dt dd div caption","",d),n("h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn","",u),n("blockquote","cite",d),n("ol","reversed start type","li"),n("ul","","li"),n("li","value",d),n("dl","","dt dd"),n("a","href target rel media hreflang type",u),n("q","cite",u),n("ins del","cite datetime",d),n("img","src sizes srcset alt usemap ismap width height"),n("iframe","src name width height",d),n("embed","src type width height"),n("object","data type typemustmatch name usemap form width height",d,"param"),n("param","name value"),n("map","name",d,"area"),n("area","alt coords shape href target rel media hreflang type"),n("table","border","caption colgroup thead tfoot tbody tr"+("html4"==e?" col":"")),n("colgroup","span","col"),n("col","span"),n("tbody thead tfoot","","tr"),n("tr","","td th"),n("td","colspan rowspan headers",d),n("th","colspan rowspan headers scope abbr",d),n("form","accept-charset action autocomplete enctype method name novalidate target",d),n("fieldset","disabled form name",d,"legend"),n("label","form for",u),n("input","accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"),n("button","disabled form formaction formenctype formmethod formnovalidate formtarget name type value","html4"==e?d:u),n("select","disabled form multiple name required size","option optgroup"),n("optgroup","disabled label","option"),n("option","disabled label selected value"),n("textarea","cols dirname disabled form maxlength name readonly required rows wrap"),n("menu","type label",d,"li"),n("noscript","",d),"html4"!=e&&(n("wbr"),n("ruby","",u,"rt rp"),n("figcaption","",d),n("mark rt rp summary bdi","",u),n("canvas","width height",d),n("video","src crossorigin poster preload autoplay mediagroup loop muted controls width height buffered",d,"track source"),n("audio","src crossorigin preload autoplay mediagroup loop muted controls buffered volume",d,"track source"),n("picture","","img source"),n("source","src srcset type media sizes"),n("track","kind src srclang label default"),n("datalist","",u,"option"),n("article section nav aside header footer","",d),n("hgroup","","h1 h2 h3 h4 h5 h6"),n("figure","",d,"figcaption"),n("time","datetime",u),n("dialog","open",d),n("command","type label icon disabled checked radiogroup command"),n("output","for form name",u),n("progress","value max",u),n("meter","value min max low high optimum",u),n("details","open",d,"summary"),n("keygen","autofocus challenge disabled form keytype name")),"html5-strict"!=e&&(r("script","language xml:space"),r("style","xml:space"),r("object","declare classid code codebase codetype archive standby align border hspace vspace"),r("embed","align name hspace vspace"),r("param","valuetype type"),r("a","charset name rev shape coords"),r("br","clear"),r("applet","codebase archive code object alt name width height align hspace vspace"),r("img","name longdesc align border hspace vspace"),r("iframe","longdesc frameborder marginwidth marginheight scrolling align"),r("font basefont","size color face"),r("input","usemap align"),r("select","onchange"),r("textarea"),r("h1 h2 h3 h4 h5 h6 div p legend caption","align"),r("ul","type compact"),r("li","type"),r("ol dl menu dir","compact"),r("pre","width xml:space"),r("hr","align noshade size width"),r("isindex","prompt"),r("table","summary width frame rules cellspacing cellpadding align bgcolor"),r("col","width align char charoff valign"),r("colgroup","width align char charoff valign"),r("thead","align char charoff valign"),r("tr","align char charoff valign bgcolor"),r("th","axis align char charoff valign nowrap bgcolor width height"),r("form","accept"),r("td","abbr axis scope align char charoff valign nowrap bgcolor width height"),r("tfoot","align char charoff valign"),r("tbody","align char charoff valign"),r("area","nohref"),r("body","background bgcolor text link vlink alink")),"html4"!=e&&(r("input button select textarea","autofocus"),r("input textarea","placeholder"),r("a","download"),r("link script img","crossorigin"),r("iframe","sandbox seamless allowfullscreen")),s(t("a form meter progress dfn"),function(e){a[e]&&delete a[e].children[e]}),delete a.caption.children.table,delete a.script,i[e]=a,a)}function r(e,t){var n;return e&&(n={},"string"==typeof e&&(e={"*":e}),s(e,function(e,r){n[r]=n[r.toUpperCase()]="map"==t?a(e,/[, ]/):c(e,/[, ]/)})),n}var i={},o={},a=e.makeMap,s=e.each,l=e.extend,c=e.explode,u=e.inArray;return function(e){function o(t,n,r){var o=e[t];return o?o=a(o,/[, ]/,a(o.toUpperCase(),/[, ]/)):(o=i[t],o||(o=a(n," ",a(n.toUpperCase()," ")),o=l(o,r),i[t]=o)),o}function d(e){return new RegExp("^"+e.replace(/([?+*])/g,".$1")+"$")}function f(e){var n,r,i,o,s,l,c,f,h,p,m,g,v,b,x,w,N,E,_,S=/^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/,k=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,T=/[*?+]/;if(e)for(e=t(e,","),y["@"]&&(w=y["@"].attributes,N=y["@"].attributesOrder),n=0,r=e.length;r>n;n++)if(s=S.exec(e[n])){if(b=s[1],h=s[2],x=s[3],f=s[5],g={},v=[],l={attributes:g,attributesOrder:v},"#"===b&&(l.paddEmpty=!0),"-"===b&&(l.removeEmpty=!0),"!"===s[4]&&(l.removeEmptyAttrs=!0),w){for(E in w)g[E]=w[E];v.push.apply(v,N)}if(f)for(f=t(f,"|"),i=0,o=f.length;o>i;i++)if(s=k.exec(f[i])){if(c={},m=s[1],p=s[2].replace(/::/g,":"),b=s[3],_=s[4],"!"===m&&(l.attributesRequired=l.attributesRequired||[],l.attributesRequired.push(p),c.required=!0),"-"===m){delete g[p],v.splice(u(v,p),1);continue}b&&("="===b&&(l.attributesDefault=l.attributesDefault||[],l.attributesDefault.push({name:p,value:_}),c.defaultValue=_),":"===b&&(l.attributesForced=l.attributesForced||[],l.attributesForced.push({name:p,value:_}),c.forcedValue=_),"<"===b&&(c.validValues=a(_,"?"))),T.test(p)?(l.attributePatterns=l.attributePatterns||[],c.pattern=d(p),l.attributePatterns.push(c)):(g[p]||v.push(p),g[p]=c)}w||"@"!=h||(w=g,N=v),x&&(l.outputName=h,y[x]=l),T.test(h)?(l.pattern=d(h),C.push(l)):y[h]=l}}function h(e){y={},C=[],f(e),s(N,function(e,t){b[t]=e.children})}function p(e){var n=/^(~)?(.+)$/;e&&(i.text_block_elements=i.block_elements=null,s(t(e,","),function(e){var t=n.exec(e),r="~"===t[1],i=r?"span":"div",o=t[2];if(b[o]=b[i],L[o]=i,r||(R[o.toUpperCase()]={},R[o]={}),!y[o]){var a=y[i];a=l({},a),delete a.removeEmptyAttrs,delete a.removeEmpty,y[o]=a}s(b,function(e,t){e[i]&&(b[t]=e=l({},b[t]),e[o]=e[i])})}))}function m(n){var r=/^([+\-]?)(\w+)\[([^\]]+)\]$/;i[e.schema]=null,n&&s(t(n,","),function(e){var n=r.exec(e),i,o;n&&(o=n[1],i=o?b[n[2]]:b[n[2]]={"#comment":{}},i=b[n[2]],s(t(n[3],"|"),function(e){"-"===o?delete i[e]:i[e]={}}))})}function g(e){var t=y[e],n;if(t)return t;for(n=C.length;n--;)if(t=C[n],t.pattern.test(e))return t}var v=this,y={},b={},C=[],x,w,N,E,_,S,k,T,R,A,B,D,M,L={},P={};e=e||{},N=n(e.schema),e.verify_html===!1&&(e.valid_elements="*[*]"),x=r(e.valid_styles),w=r(e.invalid_styles,"map"),T=r(e.valid_classes,"map"),E=o("whitespace_elements","pre script noscript style textarea video audio iframe object"),_=o("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr"),S=o("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source wbr track"), +k=o("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls"),A=o("non_empty_elements","td th iframe video audio object script",S),B=o("move_caret_before_on_enter_elements","table",A),D=o("text_block_elements","h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside nav figure"),R=o("block_elements","hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex option datalist select optgroup figcaption",D),M=o("text_inline_elements","span strong b em i font strike u var cite dfn code mark q sup sub samp"),s((e.special||"script noscript style textarea").split(" "),function(e){P[e]=new RegExp("]*>","gi")}),e.valid_elements?h(e.valid_elements):(s(N,function(e,t){y[t]={attributes:e.attributes,attributesOrder:e.attributesOrder},b[t]=e.children}),"html5"!=e.schema&&s(t("strong/b em/i"),function(e){e=t(e,"/"),y[e[1]].outputName=e[0]}),y.img.attributesDefault=[{name:"alt",value:""}],s(t("ol ul sub sup blockquote span font a table tbody tr strong em b i"),function(e){y[e]&&(y[e].removeEmpty=!0)}),s(t("p h1 h2 h3 h4 h5 h6 th td pre div address caption"),function(e){y[e].paddEmpty=!0}),s(t("span"),function(e){y[e].removeEmptyAttrs=!0})),p(e.custom_elements),m(e.valid_children),f(e.extended_valid_elements),m("+ol[ul|ol],+ul[ul|ol]"),e.invalid_elements&&s(c(e.invalid_elements),function(e){y[e]&&delete y[e]}),g("span")||f("span[!data-mce-type|*]"),v.children=b,v.getValidStyles=function(){return x},v.getInvalidStyles=function(){return w},v.getValidClasses=function(){return T},v.getBoolAttrs=function(){return k},v.getBlockElements=function(){return R},v.getTextBlockElements=function(){return D},v.getTextInlineElements=function(){return M},v.getShortEndedElements=function(){return S},v.getSelfClosingElements=function(){return _},v.getNonEmptyElements=function(){return A},v.getMoveCaretBeforeOnEnterElements=function(){return B},v.getWhiteSpaceElements=function(){return E},v.getSpecialElements=function(){return P},v.isValidChild=function(e,t){var n=b[e];return!(!n||!n[t])},v.isValid=function(e,t){var n,r,i=g(e);if(i){if(!t)return!0;if(i.attributes[t])return!0;if(n=i.attributePatterns)for(r=n.length;r--;)if(n[r].pattern.test(e))return!0}return!1},v.getElementRule=g,v.getCustomElements=function(){return L},v.addValidElements=f,v.setValidElements=h,v.addCustomElements=p,v.addValidChildren=m,v.elements=y}}),r(D,[B,C,m],function(e,t,n){function r(e,t,n){var r=1,i,o,a,s;for(s=e.getShortEndedElements(),a=/<([!?\/])?([A-Za-z0-9\-_\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g,a.lastIndex=i=n;o=a.exec(t);){if(i=a.lastIndex,"/"===o[1])r--;else if(!o[1]){if(o[2]in s)continue;r++}if(0===r)break}return i}function i(i,a){function s(){}var l=this;i=i||{},l.schema=a=a||new e,i.fix_self_closing!==!1&&(i.fix_self_closing=!0),o("comment cdata text start end pi doctype".split(" "),function(e){e&&(l[e]=i[e]||s)}),l.parse=function(e){function o(e){var t,n;for(t=h.length;t--&&h[t].name!==e;);if(t>=0){for(n=h.length-1;n>=t;n--)e=h[n],e.valid&&l.end(e.name);h.length=t}}function s(e,t,n,r,o){var a,s,l=/[\s\u0000-\u001F]+/g;if(t=t.toLowerCase(),n=t in x?t:z(n||r||o||""),N&&!y&&0!==t.indexOf("data-")){if(a=T[t],!a&&R){for(s=R.length;s--&&(a=R[s],!a.pattern.test(t)););-1===s&&(a=null)}if(!a)return;if(a.validValues&&!(n in a.validValues))return}if(V[t]&&!i.allow_script_urls){var c=n.replace(l,"");try{c=decodeURIComponent(c)}catch(u){c=unescape(c)}if(U.test(c))return;if(!i.allow_html_data_urls&&$.test(c)&&!/^data:image\//i.test(c))return}p.map[t]=n,p.push({name:t,value:n})}var l=this,c,u=0,d,f,h=[],p,m,g,v,y,b,C,x,w,N,E,_,S,k,T,R,A,B,D,M,L,P,H,O,I,F=0,z=t.decode,W,V=n.makeMap("src,href,data,background,formaction,poster"),U=/((java|vb)script|mhtml):/i,$=/^data:/i;for(P=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-_\\:\\.]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g"),H=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g,C=a.getShortEndedElements(),L=i.self_closing_elements||a.getSelfClosingElements(),x=a.getBoolAttrs(),N=i.validate,b=i.remove_internals,W=i.fix_self_closing,O=a.getSpecialElements();c=P.exec(e);){if(u0&&h[h.length-1].name===d&&o(d),!N||(E=a.getElementRule(d))){if(_=!0,N&&(T=E.attributes,R=E.attributePatterns),(k=c[8])?(y=-1!==k.indexOf("data-mce-type"),y&&b&&(_=!1),p=[],p.map={},k.replace(H,s)):(p=[],p.map={}),N&&!y){if(A=E.attributesRequired,B=E.attributesDefault,D=E.attributesForced,M=E.removeEmptyAttrs,M&&!p.length&&(_=!1),D)for(m=D.length;m--;)S=D[m],v=S.name,I=S.value,"{$uid}"===I&&(I="mce_"+F++),p.map[v]=I,p.push({name:v,value:I});if(B)for(m=B.length;m--;)S=B[m],v=S.name,v in p.map||(I=S.value,"{$uid}"===I&&(I="mce_"+F++),p.map[v]=I,p.push({name:v,value:I}));if(A){for(m=A.length;m--&&!(A[m]in p.map););-1===m&&(_=!1)}if(S=p.map["data-mce-bogus"]){if("all"===S){u=r(a,e,P.lastIndex),P.lastIndex=u;continue}_=!1}}_&&l.start(d,p,w)}else _=!1;if(f=O[d]){f.lastIndex=u=c.index+c[0].length,(c=f.exec(e))?(_&&(g=e.substr(u,c.index-u)),u=c.index+c[0].length):(g=e.substr(u),u=e.length),_&&(g.length>0&&l.text(g,!0),l.end(d)),P.lastIndex=u;continue}w||(k&&k.indexOf("/")==k.length-1?_&&l.end(d):h.push({name:d,valid:_}))}else(d=c[1])?(">"===d.charAt(0)&&(d=" "+d),i.allow_conditional_comments||"[if"!==d.substr(0,3)||(d=" "+d),l.comment(d)):(d=c[2])?l.cdata(d):(d=c[3])?l.doctype(d):(d=c[4])&&l.pi(d,c[5]);u=c.index+c[0].length}for(u=0;m--)d=h[m],d.valid&&l.end(d.name)}}var o=n.each;return i.findEndTag=r,i}),r(M,[A,B,D,m],function(e,t,n,r){var i=r.makeMap,o=r.each,a=r.explode,s=r.extend;return function(r,l){function c(t){var n,r,o,a,s,c,d,f,h,p,m,g,v,y,b;for(m=i("tr,td,th,tbody,thead,tfoot,table"),p=l.getNonEmptyElements(),g=l.getTextBlockElements(),v=l.getSpecialElements(),n=0;n1){for(a.reverse(),s=c=u.filterNode(a[0].clone()),h=0;h0)return void(t.value=r);if(n=t.next){if(3==n.type&&n.value.length){t=t.prev;continue}if(!o[n.name]&&"script"!=n.name&&"style"!=n.name){t=t.prev;continue}}i=t.prev,t.remove(),t=i}}function g(e){var t,n={};for(t in e)"li"!==t&&"p"!=t&&(n[t]=e[t]);return n}var v,y,b,C,x,w,N,E,_,S,k,T,R,A=[],B,D,M,L,P,H,O,I;if(o=o||{},h={},p={},T=s(i("script,style,head,html,body,title,meta,param"),l.getBlockElements()),O=l.getNonEmptyElements(),H=l.children,k=r.validate,I="forced_root_block"in o?o.forced_root_block:r.forced_root_block,P=l.getWhiteSpaceElements(),R=/^[ \t\r\n]+/,D=/[ \t\r\n]+$/,M=/[ \t\r\n]+/g,L=/^[ \t\r\n]+$/,v=new n({validate:k,allow_script_urls:r.allow_script_urls,allow_conditional_comments:r.allow_conditional_comments,self_closing_elements:g(l.getSelfClosingElements()),cdata:function(e){b.append(u("#cdata",4)).value=e},text:function(e,t){var n;B||(e=e.replace(M," "),b.lastChild&&T[b.lastChild.name]&&(e=e.replace(R,""))),0!==e.length&&(n=u("#text",3),n.raw=!!t,b.append(n).value=e)},comment:function(e){b.append(u("#comment",8)).value=e},pi:function(e,t){b.append(u(e,7)).value=t,m(b)},doctype:function(e){var t;t=b.append(u("#doctype",10)),t.value=e,m(b)},start:function(e,t,n){var r,i,o,a,s;if(o=k?l.getElementRule(e):{}){for(r=u(o.outputName||e,1),r.attributes=t,r.shortEnded=n,b.append(r),s=H[b.name],s&&H[r.name]&&!s[r.name]&&A.push(r),i=f.length;i--;)a=f[i].name,a in t.map&&(_=p[a],_?_.push(r):p[a]=[r]);T[e]&&m(r),n||(b=r),!B&&P[e]&&(B=!0)}},end:function(t){var n,r,i,o,a;if(r=k?l.getElementRule(t):{}){if(T[t]&&!B){if(n=b.firstChild,n&&3===n.type)if(i=n.value.replace(R,""),i.length>0)n.value=i,n=n.next;else for(o=n.next,n.remove(),n=o;n&&3===n.type;)i=n.value,o=n.next,(0===i.length||L.test(i))&&(n.remove(),n=o),n=o;if(n=b.lastChild,n&&3===n.type)if(i=n.value.replace(D,""),i.length>0)n.value=i,n=n.prev;else for(o=n.prev,n.remove(),n=o;n&&3===n.type;)i=n.value,o=n.prev,(0===i.length||L.test(i))&&(n.remove(),n=o),n=o}if(B&&P[t]&&(B=!1),(r.removeEmpty||r.paddEmpty)&&b.isEmpty(O))if(r.paddEmpty)b.empty().append(new e("#text","3")).value="\xa0";else if(!b.attributes.map.name&&!b.attributes.map.id)return a=b.parent,T[b.name]?b.empty().remove():b.unwrap(),void(b=a);b=b.parent}}},l),y=b=new e(o.context||r.root_name,11),v.parse(t),k&&A.length&&(o.context?o.invalid=!0:c(A)),I&&("body"==y.name||o.isRootContent)&&a(),!o.invalid){for(S in h){for(_=d[S],C=h[S],N=C.length;N--;)C[N].parent||C.splice(N,1);for(x=0,w=_.length;w>x;x++)_[x](C,S,o)}for(x=0,w=f.length;w>x;x++)if(_=f[x],_.name in p){for(C=p[_.name],N=C.length;N--;)C[N].parent||C.splice(N,1);for(N=0,E=_.callbacks.length;E>N;N++)_.callbacks[N](C,_.name,o)}}return y},r.remove_trailing_brs&&u.addNodeFilter("br",function(t){var n,r=t.length,i,o=s({},l.getBlockElements()),a=l.getNonEmptyElements(),c,u,d,f,h,p;for(o.body=1,n=0;r>n;n++)if(i=t[n],c=i.parent,o[i.parent.name]&&i===c.lastChild){for(d=i.prev;d;){if(f=d.name,"span"!==f||"bookmark"!==d.attr("data-mce-type")){if("br"!==f)break;if("br"===f){i=null;break}}d=d.prev}i&&(i.remove(),c.isEmpty(a)&&(h=l.getElementRule(c.name),h&&(h.removeEmpty?c.remove():h.paddEmpty&&(c.empty().append(new e("#text",3)).value="\xa0"))))}else{for(u=i;c&&c.firstChild===u&&c.lastChild===u&&(u=c,!o[c.name]);)c=c.parent;u===c&&(p=new e("#text",3),p.value="\xa0",i.replace(p))}}),r.allow_html_in_named_anchor||u.addAttributeFilter("id,name",function(e){for(var t=e.length,n,r,i,o;t--;)if(o=e[t],"a"===o.name&&o.firstChild&&!o.attr("href")){i=o.parent,n=o.lastChild;do r=n.prev,i.insert(n,o),n=r;while(n)}}),r.validate&&l.getValidClasses()&&u.addAttributeFilter("class",function(e){for(var t=e.length,n,r,i,o,a,s=l.getValidClasses(),c,u;t--;){for(n=e[t],r=n.attr("class").split(" "),a="",i=0;i0&&(f=r[r.length-1],f.length>0&&"\n"!==f&&r.push("\n")),r.push("<",e),t)for(c=0,u=t.length;u>c;c++)d=t[c],r.push(" ",d.name,'="',s(d.value,!0),'"');!n||l?r[r.length]=">":r[r.length]=" />",n&&i&&a[e]&&r.length>0&&(f=r[r.length-1],f.length>0&&"\n"!==f&&r.push("\n"))},end:function(e){var t;r.push(""),i&&a[e]&&r.length>0&&(t=r[r.length-1],t.length>0&&"\n"!==t&&r.push("\n"))},text:function(e,t){e.length>0&&(r[r.length]=t?e:s(e))},cdata:function(e){r.push("")},comment:function(e){r.push("")},pi:function(e,t){t?r.push(""):r.push(""),i&&r.push("\n")},doctype:function(e){r.push("",i?"\n":"")},reset:function(){r.length=0},getContent:function(){return r.join("").replace(/\n$/,"")}}}}),r(P,[L,B],function(e,t){return function(n,r){var i=this,o=new e(n);n=n||{},n.validate="validate"in n?n.validate:!0,i.schema=r=r||new t,i.writer=o,i.serialize=function(e){function t(e){var n=i[e.type],s,l,c,u,d,f,h,p,m;if(n)n(e);else{if(s=e.name,l=e.shortEnded,c=e.attributes,a&&c&&c.length>1&&(f=[],f.map={},m=r.getElementRule(e.name))){for(h=0,p=m.attributesOrder.length;p>h;h++)u=m.attributesOrder[h],u in c.map&&(d=c.map[u],f.map[u]=d,f.push({name:u,value:d}));for(h=0,p=c.length;p>h;h++)u=c[h].name,u in f.map||(d=c.map[u],f.map[u]=d,f.push({name:u,value:d}));c=f}if(o.start(e.name,c,l),!l){if(e=e.firstChild)do t(e);while(e=e.next);o.end(s)}}}var i,a;return a=n.validate,i={3:function(e){o.text(e.value,e.raw)},8:function(e){o.comment(e.value)},7:function(e){o.pi(e.name,e.value)},10:function(e){o.doctype(e.value)},4:function(e){o.cdata(e.value)},11:function(e){if(e=e.firstChild)do t(e);while(e=e.next)}},o.reset(),1!=e.type||n.inner?i[11](e):t(e),o.getContent()}}}),r(H,[w,M,D,C,P,A,B,h,m,S],function(e,t,n,r,i,o,a,s,l,c){function u(e){function t(e){return e&&"br"===e.name}var n,r;n=e.lastChild,t(n)&&(r=n.prev,t(r)&&(n.remove(),r.remove()))}var d=l.each,f=l.trim,h=e.DOM,p=new RegExp(["]+data-mce-bogus[^>]+>[\u200b\ufeff]+<\\/span>",'\\s?data-mce-selected="[^"]+"'].join("|"),"gi");return function(e,o){function l(){var e=o.getBody().innerHTML,t=/<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g,r,i,a,s,l,u=o.schema;for(e=c.trim(e.replace(p,"")),l=u.getShortEndedElements();s=t.exec(e);)i=t.lastIndex,a=s[0].length,r=l[s[1]]?i:n.findEndTag(u,e,i),e=e.substring(0,i-a)+e.substring(r),t.lastIndex=i-a;return f(e)}var m,g,v;return o&&(m=o.dom,g=o.schema),m=m||h,g=g||new a(e),e.entity_encoding=e.entity_encoding||"named",e.remove_trailing_brs="remove_trailing_brs"in e?e.remove_trailing_brs:!0,v=new t(e,g),v.addAttributeFilter("data-mce-tabindex",function(e,t){for(var n=e.length,r;n--;)r=e[n],r.attr("tabindex",r.attributes.map["data-mce-tabindex"]),r.attr(t,null)}),v.addAttributeFilter("src,href,style",function(t,n){for(var r=t.length,i,o,a="data-mce-"+n,s=e.url_converter,l=e.url_converter_scope,c;r--;)i=t[r],o=i.attributes.map[a],o!==c?(i.attr(n,o.length>0?o:null),i.attr(a,null)):(o=i.attributes.map[n],"style"===n?o=m.serializeStyle(m.parseStyle(o),i.name):s&&(o=s.call(l,o,n,i.name)),i.attr(n,o.length>0?o:null))}),v.addAttributeFilter("class",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.attr("class"),r&&(r=n.attr("class").replace(/(?:^|\s)mce-item-\w+(?!\S)/g,""),n.attr("class",r.length>0?r:null))}),v.addAttributeFilter("data-mce-type",function(e,t,n){for(var r=e.length,i;r--;)i=e[r],"bookmark"!==i.attributes.map["data-mce-type"]||n.cleanup||i.remove()}),v.addNodeFilter("noscript",function(e){for(var t=e.length,n;t--;)n=e[t].firstChild,n&&(n.value=r.decode(n.value))}),v.addNodeFilter("script,style",function(e,t){function n(e){return e.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}for(var r=e.length,i,o,a;r--;)i=e[r],o=i.firstChild?i.firstChild.value:"","script"===t?(a=i.attr("type"),a&&i.attr("type","mce-no/type"==a?null:a.replace(/^mce\-/,"")),o.length>0&&(i.firstChild.value="// ")):o.length>0&&(i.firstChild.value="")}),v.addNodeFilter("#comment",function(e){for(var t=e.length,n;t--;)n=e[t],0===n.value.indexOf("[CDATA[")?(n.name="#cdata",n.type=4,n.value=n.value.replace(/^\[CDATA\[|\]\]$/g,"")):0===n.value.indexOf("mce:protected ")&&(n.name="#text",n.type=3,n.raw=!0,n.value=unescape(n.value).substr(14))}),v.addNodeFilter("xml:namespace,input",function(e,t){for(var n=e.length,r;n--;)r=e[n],7===r.type?r.remove():1===r.type&&("input"!==t||"type"in r.attributes.map||r.attr("type","text"))}),e.fix_list_elements&&v.addNodeFilter("ul,ol",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.parent,("ul"===r.name||"ol"===r.name)&&n.prev&&"li"===n.prev.name&&n.prev.append(n)}),v.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style,data-mce-selected,data-mce-expando,data-mce-type,data-mce-resize",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),{schema:g,addNodeFilter:v.addNodeFilter,addAttributeFilter:v.addAttributeFilter,serialize:function(t,n){var r=this,o,a,l,h,p,y;return s.ie&&m.select("script,style,select,map").length>0?(p=t.innerHTML,t=t.cloneNode(!1),m.setHTML(t,p)):t=t.cloneNode(!0),o=t.ownerDocument.implementation,o.createHTMLDocument&&(a=o.createHTMLDocument(""),d("BODY"==t.nodeName?t.childNodes:[t],function(e){a.body.appendChild(a.importNode(e,!0))}),t="BODY"!=t.nodeName?a.body.firstChild:a.body,l=m.doc,m.doc=a),n=n||{},n.format=n.format||"html",n.selection&&(n.forced_root_block=""),n.no_events||(n.node=t,r.onPreProcess(n)),y=v.parse(f(n.getInner?t.innerHTML:m.getOuterHTML(t)),n),u(y),h=new i(e,g),n.content=h.serialize(y),n.cleanup||(n.content=c.trim(n.content),n.content=n.content.replace(/\uFEFF/g,"")),n.no_events||r.onPostProcess(n),l&&(m.doc=l),n.node=null,n.content},addRules:function(e){g.addValidElements(e)},setRules:function(e){g.setValidElements(e)},onPreProcess:function(e){o&&o.fire("PreProcess",e)},onPostProcess:function(e){o&&o.fire("PostProcess",e)},getTrimmedContent:l}}}),r(O,[],function(){function e(e){function t(t,n){var r,i=0,o,a,s,l,c,u,d=-1,f;if(r=t.duplicate(),r.collapse(n),f=r.parentElement(),f.ownerDocument===e.dom.doc){for(;"false"===f.contentEditable;)f=f.parentNode;if(!f.hasChildNodes())return{node:f,inside:1};for(s=f.children,o=s.length-1;o>=i;)if(u=Math.floor((i+o)/2),l=s[u],r.moveToElementText(l),d=r.compareEndPoints(n?"StartToStart":"EndToEnd",t),d>0)o=u-1;else{if(!(0>d))return{node:l};i=u+1}if(0>d)for(l?r.collapse(!1):(r.moveToElementText(f),r.collapse(!0),l=f,a=!0),c=0;0!==r.compareEndPoints(n?"StartToStart":"StartToEnd",t)&&0!==r.move("character",1)&&f==r.parentElement();)c++;else for(r.collapse(!0),c=0;0!==r.compareEndPoints(n?"StartToStart":"StartToEnd",t)&&0!==r.move("character",-1)&&f==r.parentElement();)c++;return{node:l,position:d,offset:c,inside:a}}}function n(){function n(e){var n=t(o,e),r,i,s=0,l,c,u;if(r=n.node,i=n.offset,n.inside&&!r.hasChildNodes())return void a[e?"setStart":"setEnd"](r,0);if(i===c)return void a[e?"setStartBefore":"setEndAfter"](r);if(n.position<0){if(l=n.inside?r.firstChild:r.nextSibling,!l)return void a[e?"setStartAfter":"setEndAfter"](r);if(!i)return void(3==l.nodeType?a[e?"setStart":"setEnd"](l,0):a[e?"setStartBefore":"setEndBefore"](l));for(;l;){if(3==l.nodeType&&(u=l.nodeValue,s+=u.length,s>=i)){r=l,s-=i,s=u.length-s;break}l=l.nextSibling}}else{if(l=r.previousSibling,!l)return a[e?"setStartBefore":"setEndBefore"](r);if(!i)return void(3==r.nodeType?a[e?"setStart":"setEnd"](l,r.nodeValue.length):a[e?"setStartAfter":"setEndAfter"](l));for(;l;){if(3==l.nodeType&&(s+=l.nodeValue.length,s>=i)){r=l,s-=i;break}l=l.previousSibling}}a[e?"setStart":"setEnd"](r,s)}var o=e.getRng(),a=i.createRng(),s,l,c,u,d;if(s=o.item?o.item(0):o.parentElement(),s.ownerDocument!=i.doc)return a;if(l=e.isCollapsed(),o.item)return a.setStart(s.parentNode,i.nodeIndex(s)),a.setEnd(a.startContainer,a.startOffset+1),a;try{n(!0),l||n()}catch(f){if(-2147024809!=f.number)throw f;d=r.getBookmark(2),c=o.duplicate(),c.collapse(!0),s=c.parentElement(),l||(c=o.duplicate(),c.collapse(!1),u=c.parentElement(),u.innerHTML=u.innerHTML),s.innerHTML=s.innerHTML,r.moveToBookmark(d),o=e.getRng(),n(!0),l||n()}return a}var r=this,i=e.dom,o=!1;this.getBookmark=function(n){function r(e){var t,n,r,o,a=[];for(t=e.parentNode,n=i.getRoot().parentNode;t!=n&&9!==t.nodeType;){for(r=t.children,o=r.length;o--;)if(e===r[o]){a.push(o);break}e=t,t=t.parentNode}return a}function o(e){var n;return n=t(a,e),n?{position:n.position,offset:n.offset,indexes:r(n.node),inside:n.inside}:void 0}var a=e.getRng(),s={};return 2===n&&(a.item?s.start={ctrl:!0,indexes:r(a.item(0))}:(s.start=o(!0),e.isCollapsed()||(s.end=o()))),s},this.moveToBookmark=function(e){function t(e){var t,n,r,o;for(t=i.getRoot(),n=e.length-1;n>=0;n--)o=t.children,r=e[n],r<=o.length-1&&(t=o[r]);return t}function n(n){var i=e[n?"start":"end"],a,s,l,c;i&&(a=i.position>0,s=o.createTextRange(),s.moveToElementText(t(i.indexes)),c=i.offset,c!==l?(s.collapse(i.inside||a),s.moveStart("character",a?-c:c)):s.collapse(n),r.setEndPoint(n?"StartToStart":"EndToStart",s),n&&r.collapse(!0))}var r,o=i.doc.body;e.start&&(e.start.ctrl?(r=o.createControlRange(),r.addElement(t(e.start.indexes)),r.select()):(r=o.createTextRange(),n(!0),n(),r.select()))},this.addRange=function(t){function n(e){var t,n,a,d,p;a=i.create("a"),t=e?s:c,n=e?l:u,d=r.duplicate(),(t==f||t==f.documentElement)&&(t=h,n=0),3==t.nodeType?(t.parentNode.insertBefore(a,t),d.moveToElementText(a),d.moveStart("character",n),i.remove(a),r.setEndPoint(e?"StartToStart":"EndToEnd",d)):(p=t.childNodes,p.length?(n>=p.length?i.insertAfter(a,p[p.length-1]):t.insertBefore(a,p[n]),d.moveToElementText(a)):t.canHaveHTML&&(t.innerHTML="",a=t.firstChild,d.moveToElementText(a),d.collapse(o)),r.setEndPoint(e?"StartToStart":"EndToEnd",d),i.remove(a))}var r,a,s,l,c,u,d,f=e.dom.doc,h=f.body,p,m;if(s=t.startContainer,l=t.startOffset,c=t.endContainer,u=t.endOffset,r=h.createTextRange(),s==c&&1==s.nodeType){if(l==u&&!s.hasChildNodes()){if(s.canHaveHTML)return d=s.previousSibling,d&&!d.hasChildNodes()&&i.isBlock(d)?d.innerHTML="":d=null,s.innerHTML="",r.moveToElementText(s.lastChild),r.select(),i.doc.selection.clear(),s.innerHTML="",void(d&&(d.innerHTML=""));l=i.nodeIndex(s),s=s.parentNode}if(l==u-1)try{if(m=s.childNodes[l],a=h.createControlRange(),a.addElement(m),a.select(),p=e.getRng(),p.item&&m===p.item(0))return}catch(g){}}n(!0),n(),r.select()},this.getRangeAt=n}return e}),r(I,[h],function(e){return{BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(e){return e.shiftKey||e.ctrlKey||e.altKey||this.metaKeyPressed(e)},metaKeyPressed:function(t){return e.mac?t.metaKey:t.ctrlKey&&!t.altKey}}}),r(F,[I,m,u,h,_],function(e,t,n,r,i){var o=i.isContentEditableFalse;return function(i,a){function s(e){var t=a.settings.object_resizing;return t===!1||r.iOS?!1:("string"!=typeof t&&(t="table,img,div"),"false"===e.getAttribute("data-mce-resize")?!1:e==a.getBody()?!1:a.dom.is(e,t))}function l(t){var n,r,i,o,s;n=t.screenX-B,r=t.screenY-D,F=n*R[2]+P,z=r*R[3]+H,F=5>F?5:F,z=5>z?5:z,i="IMG"==_.nodeName&&a.settings.resize_img_proportional!==!1?!e.modifierPressed(t):e.modifierPressed(t)||"IMG"==_.nodeName&&R[2]*R[3]!==0,i&&($(n)>$(r)?(z=q(F*O),F=q(z/O)):(F=q(z/O),z=q(F*O))),N.setStyles(S,{width:F,height:z}),o=R.startPos.x+n,s=R.startPos.y+r,o=o>0?o:0,s=s>0?s:0,N.setStyles(k,{left:o,top:s,display:"block"}),k.innerHTML=F+" × "+z,R[2]<0&&S.clientWidth<=F&&N.setStyle(S,"left",M+(P-F)),R[3]<0&&S.clientHeight<=z&&N.setStyle(S,"top",L+(H-z)),n=j.scrollWidth-Y,r=j.scrollHeight-X,n+r!==0&&N.setStyles(k,{left:o-n,top:s-r}),I||(a.fire("ObjectResizeStart",{target:_,width:P,height:H}),I=!0)}function c(){function e(e,t){t&&(_.style[e]||!a.schema.isValid(_.nodeName.toLowerCase(),e)?N.setStyle(_,e,t):N.setAttrib(_,e,t))}I=!1,e("width",F),e("height",z),N.unbind(W,"mousemove",l),N.unbind(W,"mouseup",c),V!=W&&(N.unbind(V,"mousemove",l),N.unbind(V,"mouseup",c)),N.remove(S),N.remove(k),U&&"TABLE"!=_.nodeName||u(_),a.fire("ObjectResized",{target:_,width:F,height:z}),N.setAttrib(_,"style",N.getAttrib(_,"style")),a.nodeChanged()}function u(e,t,n){var i,o,u,f,h;d(),b(),i=N.getPos(e,j),M=i.x,L=i.y,h=e.getBoundingClientRect(),o=h.width||h.right-h.left,u=h.height||h.bottom-h.top,_!=e&&(y(),_=e,F=z=0),f=a.fire("ObjectSelected",{target:e}),s(e)&&!f.isDefaultPrevented()?E(T,function(e,i){function a(t){B=t.screenX,D=t.screenY,P=_.clientWidth,H=_.clientHeight,O=H/P,R=e,e.startPos={x:o*e[0]+M,y:u*e[1]+L},Y=j.scrollWidth,X=j.scrollHeight,S=_.cloneNode(!0),N.addClass(S,"mce-clonedresizable"),N.setAttrib(S,"data-mce-bogus","all"),S.contentEditable=!1,S.unSelectabe=!0,N.setStyles(S,{left:M,top:L,margin:0}),S.removeAttribute("data-mce-selected"),j.appendChild(S),N.bind(W,"mousemove",l),N.bind(W,"mouseup",c),V!=W&&(N.bind(V,"mousemove",l),N.bind(V,"mouseup",c)),k=N.add(j,"div",{"class":"mce-resize-helper","data-mce-bogus":"all"},P+" × "+H)}var s;return t?void(i==t&&a(n)):(s=N.get("mceResizeHandle"+i),s&&N.remove(s),s=N.add(j,"div",{id:"mceResizeHandle"+i,"data-mce-bogus":"all","class":"mce-resizehandle",unselectable:!0,style:"cursor:"+i+"-resize; margin:0; padding:0"}),r.ie&&(s.contentEditable=!1),N.bind(s,"mousedown",function(e){e.stopImmediatePropagation(),e.preventDefault(),a(e)}),e.elm=s,void N.setStyles(s,{left:o*e[0]+M-s.offsetWidth/2,top:u*e[1]+L-s.offsetHeight/2}))}):d(),_.setAttribute("data-mce-selected","1")}function d(){var e,t;b(),_&&_.removeAttribute("data-mce-selected");for(e in T)t=N.get("mceResizeHandle"+e),t&&(N.unbind(t),N.remove(t))}function f(e){function t(e,t){if(e)do if(e===t)return!0;while(e=e.parentNode)}var n,r;if(!I&&!a.removed)return E(N.select("img[data-mce-selected],hr[data-mce-selected]"),function(e){e.removeAttribute("data-mce-selected")}),r="mousedown"==e.type?e.target:i.getNode(),r=N.$(r).closest(U?"table":"table,img,hr")[0],t(r,j)&&(C(),n=i.getStart(!0),t(n,r)&&t(i.getEnd(!0),r)&&(!U||r!=n&&"IMG"!==n.nodeName))?void u(r):void d()}function h(e,t,n){e&&e.attachEvent&&e.attachEvent("on"+t,n)}function p(e,t,n){e&&e.detachEvent&&e.detachEvent("on"+t,n)}function m(e){var t=e.srcElement,n,r,i,o,s,l,c;n=t.getBoundingClientRect(),l=A.clientX-n.left,c=A.clientY-n.top;for(r in T)if(i=T[r],o=t.offsetWidth*i[0],s=t.offsetHeight*i[1],$(o-l)<8&&$(s-c)<8){R=i;break}I=!0,a.fire("ObjectResizeStart",{target:_,width:_.clientWidth,height:_.clientHeight}),a.getDoc().selection.empty(),u(t,r,A)}function g(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function v(e){var t=e.srcElement;if(o(t))return void g(e);if(t!=_){if(a.fire("ObjectSelected",{target:t}),y(),0===t.id.indexOf("mceResizeHandle"))return void(e.returnValue=!1);("IMG"==t.nodeName||"TABLE"==t.nodeName)&&(d(),_=t,h(t,"resizestart",m))}}function y(){p(_,"resizestart",m)}function b(){for(var e in T){var t=T[e];t.elm&&(N.unbind(t.elm),delete t.elm)}}function C(){try{a.getDoc().execCommand("enableObjectResizing",!1,!1)}catch(e){}}function x(e){var t;if(U){t=W.body.createControlRange();try{return t.addElement(e),t.select(),!0}catch(n){}}}function w(){_=S=null,U&&(y(),p(j,"controlselect",v))}var N=a.dom,E=t.each,_,S,k,T,R,A,B,D,M,L,P,H,O,I,F,z,W=a.getDoc(),V=document,U=r.ie&&r.ie<11,$=Math.abs,q=Math.round,j=a.getBody(),Y,X;T={nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]};var K=".mce-content-body";return a.contentStyles.push(K+" div.mce-resizehandle {position: absolute;border: 1px solid black;background: #FFF;width: 7px;height: 7px;z-index: 10000}"+K+" .mce-resizehandle:hover {background: #000}"+K+" *[data-mce-selected] {outline: 1px solid black;resize: none}"+K+" .mce-clonedresizable {position: absolute;"+(r.gecko?"":"outline: 1px dashed black;")+"opacity: .5;filter: alpha(opacity=50);z-index: 10000}"+K+" .mce-resize-helper {background: #555;background: rgba(0,0,0,0.75);border-radius: 3px;border: 1px;color: white;display: none;font-family: sans-serif;font-size: 12px;white-space: nowrap;line-height: 14px;margin: 5px 10px;padding: 5px;position: absolute;z-index: 10001}"),a.on("init",function(){U?(a.on("ObjectResized",function(e){"TABLE"!=e.target.nodeName&&(d(),x(e.target))}),h(j,"controlselect",v),a.on("mousedown",function(e){A=e})):(C(),r.ie>=11&&(a.on("mousedown click",function(e){var t=e.target.nodeName;!I&&/^(TABLE|IMG|HR)$/.test(t)&&(a.selection.select(e.target,"TABLE"==t),"mousedown"==e.type&&a.nodeChanged())}),a.dom.bind(j,"mscontrolselect",function(e){function t(e){n.setEditorTimeout(a,function(){a.selection.select(e)})}return o(e.target)?(e.preventDefault(),void t(e.target)):void(/^(TABLE|IMG|HR)$/.test(e.target.nodeName)&&(e.preventDefault(),"IMG"==e.target.tagName&&t(e.target)))}))),a.on("nodechange ResizeEditor ResizeWindow drop",function(e){n.requestAnimationFrame(function(){f(e)})}),a.on("keydown keyup",function(e){_&&"TABLE"==_.nodeName&&f(e)}),a.on("hide blur",d)}),a.on("remove",b),{isResizable:s,showResizeRect:u,hideResizeRect:d,updateResizeRect:f,controlSelect:x,destroy:w}}}),r(z,[],function(){function e(e){return function(){return e}}function t(e){return function(t){return!e(t)}}function n(e,t){return function(n){return e(t(n))}}function r(){var e=a.call(arguments);return function(t){for(var n=0;n=e.length?e.apply(this,t.slice(1)):function(){var e=t.concat([].slice.call(arguments));return o.apply(this,e)}}var a=[].slice;return{constant:e,negate:t,and:i,or:r,curry:o,compose:n}}),r(W,[_,p,k],function(e,t,n){function r(e){return m(e)?!1:d(e)?f(e.parentNode)?!1:!0:h(e)||u(e)||p(e)||c(e)}function i(e,t){for(e=e.parentNode;e&&e!=t;e=e.parentNode){if(c(e))return!1;if(l(e))return!0}return!0}function o(e){return c(e)?t.reduce(e.getElementsByTagName("*"),function(e,t){return e||l(t)},!1)!==!0:!1}function a(e){return h(e)||o(e)}function s(e,t){return r(e)&&i(e,t)}var l=e.isContentEditableTrue,c=e.isContentEditableFalse,u=e.isBr,d=e.isText,f=e.matchNodeNames("script style textarea"),h=e.matchNodeNames("img input textarea hr iframe video audio object"),p=e.matchNodeNames("table"),m=n.isCaretContainer;return{isCaretCandidate:r,isInEditable:i,isAtomic:a,isEditableCaretCandidate:s}}),r(V,[],function(){function e(e){return e?{left:c(e.left),top:c(e.top),bottom:c(e.bottom),right:c(e.right),width:c(e.width),height:c(e.height)}:{left:0,top:0,bottom:0,right:0,width:0,height:0}}function t(t,n){return t=e(t),n?t.right=t.left:(t.left=t.left+t.width,t.right=t.left),t.width=0,t}function n(e,t){return e.left===t.left&&e.top===t.top&&e.bottom===t.bottom&&e.right===t.right}function r(e,t,n){return e>=0&&e<=Math.min(t.height,n.height)/2}function i(e,t){return e.bottomt.bottom?!1:r(t.top-e.bottom,e,t)}function o(e,t){return e.top>t.bottom?!0:e.bottomt.right}function l(e,t){return i(e,t)?-1:o(e,t)?1:a(e,t)?-1:s(e,t)?1:0}var c=Math.round;return{ +clone:e,collapse:t,isEqual:n,isAbove:i,isBelow:o,isLeft:a,isRight:s,compare:l}}),r(U,[],function(){function e(e){return"string"==typeof e&&e.charCodeAt(0)>=768&&t.test(e)}var t=new RegExp("[\u0300-\u036f\u0483-\u0487\u0488-\u0489\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e3-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2-\u09e3\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62-\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c00\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc-\u0ccd\u0cd5-\u0cd6\u0ce2-\u0ce3\u0d01\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62-\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1abe\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9\u1dc0-\u1df5\u1dfc-\u1dff\u200c-\u200d\u20d0-\u20dc\u20dd-\u20e0\u20e1\u20e2-\u20e4\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u302e-\u302f\u3099-\u309a\ua66f\ua670-\ua672\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\uff9e-\uff9f]");return{isExtendingChar:e}}),r($,[z,_,w,T,W,V,U],function(e,t,n,r,i,o,a){function s(e){return e&&/[\r\n\t ]/.test(e)}function l(e){var t=e.startContainer,n=e.startOffset,r;return s(e.toString())&&g(t.parentNode)&&(r=t.data,s(r[n-1])||s(r[n+1]))?!0:!1}function c(e){function t(e){var t=e.ownerDocument,n=t.createRange(),r=t.createTextNode("\xa0"),i=e.parentNode,a;return i.insertBefore(r,e),n.setStart(r,0),n.setEnd(r,1),a=o.clone(n.getBoundingClientRect()),i.removeChild(r),a}function n(e){var n,r;return r=e.getClientRects(),n=r.length>0?o.clone(r[0]):o.clone(e.getBoundingClientRect()),y(e)&&0===n.left?t(e):n}function r(e,t){return e=o.collapse(e,t),e.width=1,e.right=e.left+1,e}function i(e){0!==e.height&&(c.length>0&&o.isEqual(e,c[c.length-1])||c.push(e))}function s(e,t){var o=e.ownerDocument.createRange();return t0&&(o.setStart(e,t-1),o.setEnd(e,t),l(o)||i(r(n(o),!1))),void(t=t.data.length:n>=t.childNodes.length}function a(){var e;return e=t.ownerDocument.createRange(),e.setStart(t,n),e.setEnd(t,n),e}function s(){return r||(r=c(new u(t,n))),r}function l(){return s().length>0}function d(e){return e&&t===e.container()&&n===e.offset()}function f(e){return C(t,e?n-1:n)}return{container:e.constant(t),offset:e.constant(n),toRange:a,getClientRects:s,isVisible:l,isAtStart:i,isAtEnd:o,isEqual:d,getNode:f}}var d=t.isElement,f=i.isCaretCandidate,h=t.matchStyleValues("display","block table"),p=t.matchStyleValues("float","left right"),m=e.and(d,f,e.negate(p)),g=e.negate(t.matchStyleValues("white-space","pre pre-line pre-wrap")),v=t.isText,y=t.isBr,b=n.nodeIndex,C=r.getNode;return u.fromRangeStart=function(e){return new u(e.startContainer,e.startOffset)},u.fromRangeEnd=function(e){return new u(e.endContainer,e.endOffset)},u.after=function(e){return new u(e.parentNode,b(e)+1)},u.before=function(e){return new u(e.parentNode,b(e))},u}),r(q,[_,w,z,p,$],function(e,t,n,r,i){function o(e){var t=e.parentNode;return v(t)?o(t):t}function a(e){return e?r.reduce(e.childNodes,function(e,t){return v(t)&&"BR"!=t.nodeName?e=e.concat(a(t)):e.push(t),e},[]):[]}function s(e,t){for(;(e=e.previousSibling)&&g(e);)t+=e.data.length;return t}function l(e){return function(t){return e===t}}function c(t){var n,i,s;return n=a(o(t)),i=r.findIndex(n,l(t),t),n=n.slice(0,i+1),s=r.reduce(n,function(e,t,r){return g(t)&&g(n[r-1])&&e++,e},0),n=r.filter(n,e.matchNodeNames(t.nodeName)),i=r.findIndex(n,l(t),t),i-s}function u(e){var t;return t=g(e)?"text()":e.nodeName.toLowerCase(),t+"["+c(e)+"]"}function d(e,t,n){var r=[];for(t=t.parentNode;t!=e&&(!n||!n(t));t=t.parentNode)r.push(t);return r}function f(t,i){var o,a,l=[],c,f,h;return o=i.container(),a=i.offset(),g(o)?c=s(o,a):(f=o.childNodes,a>=f.length?(c="after",a=f.length-1):c="before",o=f[a]),l.push(u(o)),h=d(t,o),h=r.filter(h,n.negate(e.isBogus)),l=l.concat(r.map(h,function(e){return u(e)})),l.reverse().join("/")+","+c}function h(t,n,i){var o=a(t);return o=r.filter(o,function(e,t){return!g(e)||!g(o[t-1])}),o=r.filter(o,e.matchNodeNames(n)),o[i]}function p(e,t){for(var n=e,r=0,o;g(n);){if(o=n.data.length,t>=r&&r+o>=t){e=n,t-=r;break}if(!g(n.nextSibling)){e=n,t=o;break}r+=o,n=n.nextSibling}return t>e.data.length&&(t=e.data.length),new i(e,t)}function m(e,t){var n,o,a;return t?(n=t.split(","),t=n[0].split("/"),a=n.length>1?n[1]:"before",o=r.reduce(t,function(e,t){return(t=/([\w\-\(\)]+)\[([0-9]+)\]/.exec(t))?("text()"===t[1]&&(t[1]="#text"),h(e,t[1],parseInt(t[2],10))):null},e),o?g(o)?p(o,parseInt(a,10)):(a="after"===a?y(o)+1:y(o),new i(o.parentNode,a)):null):null}var g=e.isText,v=e.isBogus,y=t.nodeIndex;return{create:f,resolve:m}}),r(j,[h,m,k,q,$,_],function(e,t,n,r,i,o){function a(a){var l=a.dom;this.getBookmark=function(e,c){function u(e,n){var r=0;return t.each(l.select(e),function(e){return"all"!==e.getAttribute("data-mce-bogus")?e==n?!1:void r++:void 0}),r}function d(e){function t(t){var n,r,i,o=t?"start":"end";n=e[o+"Container"],r=e[o+"Offset"],1==n.nodeType&&"TR"==n.nodeName&&(i=n.childNodes,n=i[Math.min(t?r:r-1,i.length-1)],n&&(r=t?0:n.childNodes.length,e["set"+(t?"Start":"End")](n,r)))}return t(!0),t(),e}function f(e){function t(e,t){var r=e[t?"startContainer":"endContainer"],i=e[t?"startOffset":"endOffset"],o=[],a,s,u=0;if(3==r.nodeType){if(c)for(a=r.previousSibling;a&&3==a.nodeType;a=a.previousSibling)i+=a.nodeValue.length;o.push(i)}else s=r.childNodes,i>=s.length&&s.length&&(u=1,i=Math.max(0,s.length-1)),o.push(l.nodeIndex(s[i],c)+u);for(;r&&r!=n;r=r.parentNode)o.push(l.nodeIndex(r,c));return o}var n=l.getRoot(),r={};return r.start=t(e,!0),a.isCollapsed()||(r.end=t(e)),r}function h(e){function t(e){var t;if(n.isCaretContainer(e)){if(o.isText(e)&&n.isCaretContainerBlock(e)&&(e=e.parentNode),t=e.previousSibling,s(t))return t;if(t=e.nextSibling,s(t))return t}}return t(e.startContainer)||t(e.endContainer)}var p,m,g,v,y,b,C="",x;if(2==e)return b=a.getNode(),y=b?b.nodeName:null,p=a.getRng(),s(b)||"IMG"==y?{name:y,index:u(y,b)}:a.tridentSel?a.tridentSel.getBookmark(e):(b=h(p),b?(y=b.tagName,{name:y,index:u(y,b)}):f(p));if(3==e)return p=a.getRng(),{start:r.create(l.getRoot(),i.fromRangeStart(p)),end:r.create(l.getRoot(),i.fromRangeEnd(p))};if(e)return{rng:a.getRng()};if(p=a.getRng(),g=l.uniqueId(),v=a.isCollapsed(),x="overflow:hidden;line-height:0px",p.duplicate||p.item){if(p.item)return b=p.item(0),y=b.nodeName,{name:y,index:u(y,b)};m=p.duplicate();try{p.collapse(),p.pasteHTML(''+C+""),v||(m.collapse(!1),p.moveToElementText(m.parentElement()),0===p.compareEndPoints("StartToEnd",m)&&m.move("character",-1),m.pasteHTML(''+C+""))}catch(w){return null}}else{if(b=a.getNode(),y=b.nodeName,"IMG"==y)return{name:y,index:u(y,b)};m=d(p.cloneRange()),v||(m.collapse(!1),m.insertNode(l.create("span",{"data-mce-type":"bookmark",id:g+"_end",style:x},C))),p=d(p),p.collapse(!0),p.insertNode(l.create("span",{"data-mce-type":"bookmark",id:g+"_start",style:x},C))}return a.moveToBookmark({id:g,keep:1}),{id:g}},this.moveToBookmark=function(n){function i(e){var t=n[e?"start":"end"],r,i,o,a;if(t){for(o=t[0],i=d,r=t.length-1;r>=1;r--){if(a=i.childNodes,t[r]>a.length-1)return;i=a[t[r]]}3===i.nodeType&&(o=Math.min(t[0],i.nodeValue.length)),1===i.nodeType&&(o=Math.min(t[0],i.childNodes.length)),e?u.setStart(i,o):u.setEnd(i,o)}return!0}function o(r){var i=l.get(n.id+"_"+r),o,a,s,c,u=n.keep;if(i&&(o=i.parentNode,"start"==r?(u?(o=i.firstChild,a=1):a=l.nodeIndex(i),f=h=o,p=m=a):(u?(o=i.firstChild,a=1):a=l.nodeIndex(i),h=o,m=a),!u)){for(c=i.previousSibling,s=i.nextSibling,t.each(t.grep(i.childNodes),function(e){3==e.nodeType&&(e.nodeValue=e.nodeValue.replace(/\uFEFF/g,""))});i=l.get(n.id+"_"+r);)l.remove(i,1);c&&s&&c.nodeType==s.nodeType&&3==c.nodeType&&!e.opera&&(a=c.nodeValue.length,c.appendData(s.nodeValue),l.remove(s),"start"==r?(f=h=c,p=m=a):(h=c,m=a))}}function s(t){return!l.isBlock(t)||t.innerHTML||e.ie||(t.innerHTML='
    '),t}function c(){var e,t;return e=l.createRng(),t=r.resolve(l.getRoot(),n.start),e.setStart(t.container(),t.offset()),t=r.resolve(l.getRoot(),n.end),e.setEnd(t.container(),t.offset()),e}var u,d,f,h,p,m;if(n)if(t.isArray(n.start)){if(u=l.createRng(),d=l.getRoot(),a.tridentSel)return a.tridentSel.moveToBookmark(n);i(!0)&&i()&&a.setRng(u)}else"string"==typeof n.start?a.setRng(c(n)):n.id?(o("start"),o("end"),f&&(u=l.createRng(),u.setStart(s(f),p),u.setEnd(s(h),m),a.setRng(u))):n.name?a.select(l.select(n.name)[n.index]):n.rng&&a.setRng(n.rng)}}var s=o.isContentEditableFalse;return a.isBookmarkNode=function(e){return e&&"SPAN"===e.tagName&&"bookmark"===e.getAttribute("data-mce-type")},a}),r(Y,[y,O,F,T,j,_,h,m],function(e,n,r,i,o,a,s,l){function c(e,t,i,a){var s=this;s.dom=e,s.win=t,s.serializer=i,s.editor=a,s.bookmarkManager=new o(s),s.controlSelection=new r(s,a),s.win.getSelection||(s.tridentSel=new n(s))}var u=l.each,d=l.trim,f=s.ie;return c.prototype={setCursorLocation:function(e,t){var n=this,r=n.dom.createRng();e?(r.setStart(e,t),r.setEnd(e,t),n.setRng(r),n.collapse(!1)):(n._moveEndPoint(r,n.editor.getBody(),!0),n.setRng(r))},getContent:function(e){var n=this,r=n.getRng(),i=n.dom.create("body"),o=n.getSel(),a,s,l;return e=e||{},a=s="",e.get=!0,e.format=e.format||"html",e.selection=!0,n.editor.fire("BeforeGetContent",e),"text"==e.format?n.isCollapsed()?"":r.text||(o.toString?o.toString():""):(r.cloneContents?(l=r.cloneContents(),l&&i.appendChild(l)):r.item!==t||r.htmlText!==t?(i.innerHTML="
    "+(r.item?r.item(0).outerHTML:r.htmlText),i.removeChild(i.firstChild)):i.innerHTML=r.toString(),/^\s/.test(i.innerHTML)&&(a=" "),/\s+$/.test(i.innerHTML)&&(s=" "),e.getInner=!0,e.content=n.isCollapsed()?"":a+n.serializer.serialize(i,e)+s,n.editor.fire("GetContent",e),e.content)},setContent:function(e,t){var n=this,r=n.getRng(),i,o=n.win.document,a,s;if(t=t||{format:"html"},t.set=!0,t.selection=!0,t.content=e,t.no_events||n.editor.fire("BeforeSetContent",t),e=t.content,r.insertNode){e+='_',r.startContainer==o&&r.endContainer==o?o.body.innerHTML=e:(r.deleteContents(),0===o.body.childNodes.length?o.body.innerHTML=e:r.createContextualFragment?r.insertNode(r.createContextualFragment(e)):(a=o.createDocumentFragment(),s=o.createElement("div"),a.appendChild(s),s.outerHTML=e,r.insertNode(a))),i=n.dom.get("__caret"),r=o.createRange(),r.setStartBefore(i),r.setEndBefore(i),n.setRng(r),n.dom.remove("__caret");try{n.setRng(r)}catch(l){}}else r.item&&(o.execCommand("Delete",!1,null),r=n.getRng()),/^\s+/.test(e)?(r.pasteHTML('_'+e),n.dom.remove("__mce_tmp")):r.pasteHTML(e);t.no_events||n.editor.fire("SetContent",t)},getStart:function(e){var t=this,n=t.getRng(),r,i,o,a;if(n.duplicate||n.item){if(n.item)return n.item(0);for(o=n.duplicate(),o.collapse(1),r=o.parentElement(),r.ownerDocument!==t.dom.doc&&(r=t.dom.getRoot()),i=a=n.parentElement();a=a.parentNode;)if(a==r){r=i;break}return r}return r=n.startContainer,1==r.nodeType&&r.hasChildNodes()&&(e&&n.collapsed||(r=r.childNodes[Math.min(r.childNodes.length-1,n.startOffset)])),r&&3==r.nodeType?r.parentNode:r},getEnd:function(e){var t=this,n=t.getRng(),r,i;return n.duplicate||n.item?n.item?n.item(0):(n=n.duplicate(),n.collapse(0),r=n.parentElement(),r.ownerDocument!==t.dom.doc&&(r=t.dom.getRoot()),r&&"BODY"==r.nodeName?r.lastChild||r:r):(r=n.endContainer,i=n.endOffset,1==r.nodeType&&r.hasChildNodes()&&(e&&n.collapsed||(r=r.childNodes[i>0?i-1:i])),r&&3==r.nodeType?r.parentNode:r)},getBookmark:function(e,t){return this.bookmarkManager.getBookmark(e,t)},moveToBookmark:function(e){return this.bookmarkManager.moveToBookmark(e)},select:function(e,t){var n=this,r=n.dom,i=r.createRng(),o;if(n.lastFocusBookmark=null,e){if(!t&&n.controlSelection.controlSelect(e))return;o=r.nodeIndex(e),i.setStart(e.parentNode,o),i.setEnd(e.parentNode,o+1),t&&(n._moveEndPoint(i,e,!0),n._moveEndPoint(i,e)),n.setRng(i)}return e},isCollapsed:function(){var e=this,t=e.getRng(),n=e.getSel();return!t||t.item?!1:t.compareEndPoints?0===t.compareEndPoints("StartToEnd",t):!n||t.collapsed},collapse:function(e){var t=this,n=t.getRng(),r;n.item&&(r=n.item(0),n=t.win.document.body.createTextRange(),n.moveToElementText(r)),n.collapse(!!e),t.setRng(n)},getSel:function(){var e=this.win;return e.getSelection?e.getSelection():e.document.selection},getRng:function(e){function t(e,t,n){try{return t.compareBoundaryPoints(e,n)}catch(r){return-1}}var n=this,r,i,o,a,s,l;if(!n.win)return null;if(a=n.win.document,!e&&n.lastFocusBookmark){var c=n.lastFocusBookmark;return c.startContainer?(i=a.createRange(),i.setStart(c.startContainer,c.startOffset),i.setEnd(c.endContainer,c.endOffset)):i=c,i}if(e&&n.tridentSel)return n.tridentSel.getRangeAt(0);try{(r=n.getSel())&&(i=r.rangeCount>0?r.getRangeAt(0):r.createRange?r.createRange():a.createRange())}catch(u){}if(l=n.editor.fire("GetSelectionRange",{range:i}),l.range!==i)return l.range;if(f&&i&&i.setStart&&a.selection){try{s=a.selection.createRange()}catch(u){}s&&s.item&&(o=s.item(0),i=a.createRange(),i.setStartBefore(o),i.setEndAfter(o))}return i||(i=a.createRange?a.createRange():a.body.createTextRange()),i.setStart&&9===i.startContainer.nodeType&&i.collapsed&&(o=n.dom.getRoot(),i.setStart(o,0),i.setEnd(o,0)),n.selectedRange&&n.explicitRange&&(0===t(i.START_TO_START,i,n.selectedRange)&&0===t(i.END_TO_END,i,n.selectedRange)?i=n.explicitRange:(n.selectedRange=null,n.explicitRange=null)),i},setRng:function(e,t){var n=this,r,i,o;if(e)if(e.select){n.explicitRange=null;try{e.select()}catch(a){}}else if(n.tridentSel){if(e.cloneRange)try{n.tridentSel.addRange(e)}catch(a){}}else{if(r=n.getSel(),o=n.editor.fire("SetSelectionRange",{range:e}),e=o.range,r){n.explicitRange=e;try{r.removeAllRanges(),r.addRange(e)}catch(a){}t===!1&&r.extend&&(r.collapse(e.endContainer,e.endOffset),r.extend(e.startContainer,e.startOffset)),n.selectedRange=r.rangeCount>0?r.getRangeAt(0):null}e.collapsed||e.startContainer!=e.endContainer||!r.setBaseAndExtent||s.ie||e.endOffset-e.startOffset<2&&e.startContainer.hasChildNodes()&&(i=e.startContainer.childNodes[e.startOffset],i&&"IMG"==i.tagName&&n.getSel().setBaseAndExtent(i,0,i,1))}},setNode:function(e){var t=this;return t.setContent(t.dom.getOuterHTML(e)),e},getNode:function(){function e(e,t){for(var n=e;e&&3===e.nodeType&&0===e.length;)e=t?e.nextSibling:e.previousSibling;return e||n}var t=this,n=t.getRng(),r,i=n.startContainer,o=n.endContainer,a=n.startOffset,s=n.endOffset,l=t.dom.getRoot();return n?n.setStart?(r=n.commonAncestorContainer,!n.collapsed&&(i==o&&2>s-a&&i.hasChildNodes()&&(r=i.childNodes[a]),3===i.nodeType&&3===o.nodeType&&(i=i.length===a?e(i.nextSibling,!0):i.parentNode,o=0===s?e(o.previousSibling,!1):o.parentNode,i&&i===o))?i:r&&3==r.nodeType?r.parentNode:r):(r=n.item?n.item(0):n.parentElement(),r.ownerDocument!==t.win.document&&(r=l),r):l},getSelectedBlocks:function(t,n){var r=this,i=r.dom,o,a,s=[];if(a=i.getRoot(),t=i.getParent(t||r.getStart(),i.isBlock),n=i.getParent(n||r.getEnd(),i.isBlock),t&&t!=a&&s.push(t),t&&n&&t!=n){o=t;for(var l=new e(t,a);(o=l.next())&&o!=n;)i.isBlock(o)&&s.push(o)}return n&&t!=n&&n!=a&&s.push(n),s},isForward:function(){var e=this.dom,t=this.getSel(),n,r;return t&&t.anchorNode&&t.focusNode?(n=e.createRng(),n.setStart(t.anchorNode,t.anchorOffset),n.collapse(!0),r=e.createRng(),r.setStart(t.focusNode,t.focusOffset),r.collapse(!0),n.compareBoundaryPoints(n.START_TO_START,r)<=0):!0},normalize:function(){var e=this,t=e.getRng();return s.range&&new i(e.dom).normalize(t)&&e.setRng(t,e.isForward()),t},selectorChanged:function(e,t){var n=this,r;return n.selectorChangedData||(n.selectorChangedData={},r={},n.editor.on("NodeChange",function(e){var t=e.element,i=n.dom,o=i.getParents(t,null,i.getRoot()),a={};u(n.selectorChangedData,function(e,t){u(o,function(n){return i.is(n,t)?(r[t]||(u(e,function(e){e(!0,{node:n,selector:t,parents:o})}),r[t]=e),a[t]=e,!1):void 0})}),u(r,function(e,n){a[n]||(delete r[n],u(e,function(e){e(!1,{node:t,selector:n,parents:o})}))})})),n.selectorChangedData[e]||(n.selectorChangedData[e]=[]),n.selectorChangedData[e].push(t),n},getScrollContainer:function(){for(var e,t=this.dom.getRoot();t&&"BODY"!=t.nodeName;){if(t.scrollHeight>t.clientHeight){e=t;break}t=t.parentNode}return e},scrollIntoView:function(e,t){function n(e){for(var t=0,n=0,r=e;r&&r.nodeType;)t+=r.offsetLeft||0,n+=r.offsetTop||0,r=r.offsetParent;return{x:t,y:n}}var r,i,o=this,s=o.dom,l=s.getRoot(),c,u,d=0;if(a.isElement(e)){if(t===!1&&(d=e.offsetHeight),"BODY"!=l.nodeName){var f=o.getScrollContainer();if(f)return r=n(e).y-n(f).y+d,u=f.clientHeight,c=f.scrollTop,void((c>r||r+25>c+u)&&(f.scrollTop=c>r?r:r-u+25))}i=s.getViewPort(o.editor.getWin()),r=s.getPos(e).y+d,c=i.y,u=i.h,(rc+u)&&o.editor.getWin().scrollTo(0,c>r?r:r-u+25)}},placeCaretAt:function(e,t){this.setRng(i.getCaretRangeFromPoint(e,t,this.editor.getDoc()))},_moveEndPoint:function(t,n,r){var i=n,o=new e(n,i),a=this.dom.schema.getNonEmptyElements();do{if(3==n.nodeType&&0!==d(n.nodeValue).length)return void(r?t.setStart(n,0):t.setEnd(n,n.nodeValue.length));if(a[n.nodeName]&&!/^(TD|TH)$/.test(n.nodeName))return void(r?t.setStartBefore(n):"BR"==n.nodeName?t.setEndBefore(n):t.setEndAfter(n));if(s.ie&&s.ie<11&&this.dom.isBlock(n)&&this.dom.isEmpty(n))return void(r?t.setStart(n,0):t.setEnd(n,0))}while(n=r?o.next():o.prev());"BODY"==i.nodeName&&(r?t.setStart(i,0):t.setEnd(i,i.childNodes.length))},destroy:function(){this.win=null,this.controlSelection.destroy()}},c}),r(X,[j,m],function(e,t){function n(t){this.compare=function(n,i){function o(e){var n={};return r(t.getAttribs(e),function(r){var i=r.nodeName.toLowerCase();0!==i.indexOf("_")&&"style"!==i&&"data-mce-style"!==i&&(n[i]=t.getAttrib(e,i))}),n}function a(e,t){var n,r;for(r in e)if(e.hasOwnProperty(r)){if(n=t[r],"undefined"==typeof n)return!1;if(e[r]!=n)return!1;delete t[r]}for(r in t)if(t.hasOwnProperty(r))return!1;return!0}return n.nodeName!=i.nodeName?!1:a(o(n),o(i))&&a(t.parseStyle(t.getAttrib(n,"style")),t.parseStyle(t.getAttrib(i,"style")))?!e.isBookmarkNode(n)&&!e.isBookmarkNode(i):!1}}var r=t.each;return n}),r(K,[m],function(e){function t(e,t){function r(e){return e.replace(/%(\w+)/g,"")}var i,o,a=e.dom,s="",l,c;if(c=e.settings.preview_styles,c===!1)return"";if(c||(c="font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow"),"string"==typeof t){if(t=e.formatter.get(t),!t)return;t=t[0]}return i=t.block||t.inline||"span",o=a.create(i),n(t.styles,function(e,t){e=r(e),e&&a.setStyle(o,t,e)}),n(t.attributes,function(e,t){e=r(e),e&&a.setAttrib(o,t,e)}),n(t.classes,function(e){e=r(e),a.hasClass(o,e)||a.addClass(o,e)}),e.fire("PreviewFormats"),a.setStyles(o,{position:"absolute",left:-65535}),e.getBody().appendChild(o),l=a.getStyle(e.getBody(),"fontSize",!0),l=/px$/.test(l)?parseInt(l,10):0,n(c.split(" "),function(t){var n=a.getStyle(o,t,!0);if(!("background-color"==t&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(n)&&(n=a.getStyle(e.getBody(),t,!0),"#ffffff"==a.toHex(n).toLowerCase())||"color"==t&&"#000000"==a.toHex(n).toLowerCase())){if("font-size"==t&&/em|%$/.test(n)){if(0===l)return;n=parseFloat(n,10)/(/%$/.test(n)?100:1),n=n*l+"px"}"border"==t&&n&&(s+="padding:0 2px;"),s+=t+":"+n+";"}}),e.fire("AfterPreviewFormats"),a.remove(o),s}var n=e.each;return{getCssText:t}}),r(G,[y,T,j,X,m,K],function(e,t,n,r,i,o){return function(a){function s(e){return e.nodeType&&(e=e.nodeName),!!a.schema.getTextBlockElements()[e.toLowerCase()]}function l(e){return/^(TH|TD)$/.test(e.nodeName)}function c(e){return e&&/^(IMG)$/.test(e.nodeName)}function u(e,t){return q.getParents(e,t,q.getRoot())}function d(e){return 1===e.nodeType&&"_mce_caret"===e.id}function f(){m({valigntop:[{selector:"td,th",styles:{verticalAlign:"top"}}],valignmiddle:[{selector:"td,th",styles:{verticalAlign:"middle"}}],valignbottom:[{selector:"td,th",styles:{verticalAlign:"bottom"}}],alignleft:[{selector:"figure.image",collapsed:!1,classes:"align-left",ceFalseOverride:!0},{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"left"},defaultBlock:"div"},{selector:"img,table",collapsed:!1,styles:{"float":"left"}}],aligncenter:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"center"},defaultBlock:"div"},{selector:"img",collapsed:!1,styles:{display:"block",marginLeft:"auto",marginRight:"auto"}},{selector:"table",collapsed:!1,styles:{marginLeft:"auto",marginRight:"auto"}}],alignright:[{selector:"figure.image",collapsed:!1,classes:"align-right",ceFalseOverride:!0},{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"right"},defaultBlock:"div"},{selector:"img,table",collapsed:!1,styles:{"float":"right"}}],alignjustify:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"justify"},defaultBlock:"div"}],bold:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:!0},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:!0},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},links:!0,remove_similar:!0},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},links:!0,remove_similar:!0},fontname:{inline:"span",styles:{fontFamily:"%value"}},fontsize:{inline:"span",styles:{fontSize:"%value"}},fontsize_class:{inline:"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},code:{inline:"code"},link:{inline:"a",selector:"a",remove:"all",split:!0,deep:!0,onmatch:function(){return!0},onformat:function(e,t,n){le(n,function(t,n){q.setAttrib(e,n,t)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins",remove:"all",split:!0,expand:!1,block_expand:!0,deep:!0},{selector:"span",attributes:["style","class"],remove:"empty",split:!0,expand:!1,deep:!0},{selector:"*",attributes:["style","class"],split:!1,expand:!1,deep:!0}]}),le("p h1 h2 h3 h4 h5 h6 div address pre div dt dd samp".split(/\s/),function(e){m(e,{block:e,remove:"all"})}),m(a.settings.formats)}function h(){a.addShortcut("meta+b","bold_desc","Bold"),a.addShortcut("meta+i","italic_desc","Italic"),a.addShortcut("meta+u","underline_desc","Underline");for(var e=1;6>=e;e++)a.addShortcut("access+"+e,"",["FormatBlock",!1,"h"+e]);a.addShortcut("access+7","",["FormatBlock",!1,"p"]),a.addShortcut("access+8","",["FormatBlock",!1,"div"]),a.addShortcut("access+9","",["FormatBlock",!1,"address"])}function p(e){return e?$[e]:$}function m(e,t){e&&("string"!=typeof e?le(e,function(e,t){m(t,e)}):(t=t.length?t:[t],le(t,function(e){e.deep===re&&(e.deep=!e.selector),e.split===re&&(e.split=!e.selector||e.inline),e.remove===re&&e.selector&&!e.inline&&(e.remove="none"),e.selector&&e.inline&&(e.mixed=!0,e.block_expand=!0),"string"==typeof e.classes&&(e.classes=e.classes.split(/\s+/))}),$[e]=t))}function g(e){return e&&$[e]&&delete $[e],$}function v(e){var t;return a.dom.getParent(e,function(e){return t=a.dom.getStyle(e,"text-decoration"),t&&"none"!==t}),t}function y(e){var t;1===e.nodeType&&e.parentNode&&1===e.parentNode.nodeType&&(t=v(e.parentNode),a.dom.getStyle(e,"color")&&t?a.dom.setStyle(e,"text-decoration",t):a.dom.getStyle(e,"text-decoration")===t&&a.dom.setStyle(e,"text-decoration",null))}function b(t,n,r){function i(e,t){if(t=t||u,e){if(t.onformat&&t.onformat(e,t,n,r),le(t.styles,function(t,r){q.setStyle(e,r,D(t,n))}),t.styles){var i=q.getAttrib(e,"style");i&&e.setAttribute("data-mce-style",i)}le(t.attributes,function(t,r){q.setAttrib(e,r,D(t,n))}),le(t.classes,function(t){t=D(t,n),q.hasClass(e,t)||q.addClass(e,t)})}}function o(){function t(t,n){var i=new e(n);for(r=i.current();r;r=i.prev())if(r.childNodes.length>1||r==t||"BR"==r.tagName)return r}var n=a.selection.getRng(),i=n.startContainer,o=n.endContainer;if(i!=o&&0===n.endOffset){var s=t(i,o),l=3==s.nodeType?s.length:s.childNodes.length;n.setEnd(s,l)}return n}function l(e,r,o){var a=[],l,f,h=!0;l=u.inline||u.block,f=q.create(l),i(f),Y.walk(e,function(e){function r(e){var g,v,y,b,C;return C=h,g=e.nodeName.toLowerCase(),v=e.parentNode.nodeName.toLowerCase(),1===e.nodeType&&ie(e)&&(C=h,h="true"===ie(e),b=!0),R(g,"br")?(p=0,void(u.block&&q.remove(e))):u.wrapper&&w(e,t,n)?void(p=0):h&&!b&&u.block&&!u.wrapper&&s(g)&&X(v,l)?(e=q.rename(e,l),i(e),a.push(e),void(p=0)):u.selector&&(le(c,function(t){return"collapsed"in t&&t.collapsed!==m?void 0:q.is(e,t.selector)&&!d(e)?(i(e,t),y=!0,!1):void 0}),!u.inline||y)?void(p=0):void(!h||b||!X(l,g)||!X(v,l)||!o&&3===e.nodeType&&1===e.nodeValue.length&&65279===e.nodeValue.charCodeAt(0)||d(e)||u.inline&&K(e)?(p=0,le(ce(e.childNodes),r),b&&(h=C),p=0):(p||(p=q.clone(f,ee),e.parentNode.insertBefore(p,e),a.push(p)),p.appendChild(e)))}var p;le(e,r)}),u.links===!0&&le(a,function(e){function t(e){"A"===e.nodeName&&i(e,u),le(ce(e.childNodes),t)}t(e)}),le(a,function(e){function r(e){var t=0;return le(e.childNodes,function(e){M(e)||se(e)||t++}),t}function o(e){var t,n;return le(e.childNodes,function(e){return 1!=e.nodeType||se(e)||d(e)?void 0:(t=e,ee)}),t&&!se(t)&&T(t,u)&&(n=q.clone(t,ee),i(n),q.replace(n,e,te),q.remove(t,1)),n||e}var s;if(s=r(e),(a.length>1||!K(e))&&0===s)return void q.remove(e,1);if(u.inline||u.wrapper){if(u.exact||1!==s||(e=o(e)),le(c,function(t){le(q.select(t.inline,e),function(e){se(e)||O(t,n,e,t.exact?e:null)})}),w(e.parentNode,t,n))return q.remove(e,1),e=0,te;u.merge_with_parents&&q.getParent(e.parentNode,function(r){return w(r,t,n)?(q.remove(e,1),e=0,te):void 0}),e&&u.merge_siblings!==!1&&(e=z(F(e),e),e=z(e,F(e,te)))}})}var c=p(t),u=c[0],f,h,m=!r&&j.isCollapsed();if("false"!==ie(j.getNode())){if(u)if(r)r.nodeType?(h=q.createRng(),h.setStartBefore(r),h.setEndAfter(r),l(P(h,c),null,!0)):l(r,null,!0);else if(m&&u.inline&&!q.select("td.mce-item-selected,th.mce-item-selected").length)V("apply",t,n);else{var g=a.selection.getNode();G||!c[0].defaultBlock||q.getParent(g,q.isBlock)||b(c[0].defaultBlock),a.selection.setRng(o()),f=j.getBookmark(),l(P(j.getRng(te),c),f),u.styles&&(u.styles.color||u.styles.textDecoration)&&(ue(g,y,"childNodes"),y(g)),j.moveToBookmark(f),U(j.getRng(te)),a.nodeChanged()}}else{r=j.getNode();for(var v=0,C=c.length;C>v;v++)if(c[v].ceFalseOverride&&q.is(r,c[v].selector))return void i(r,c[v])}}function C(e,t,n,r){function i(e){var n,r,o,a,s;if(1===e.nodeType&&ie(e)&&(a=b,b="true"===ie(e),s=!0),n=ce(e.childNodes),b&&!s)for(r=0,o=h.length;o>r&&!O(h[r],t,e,e);r++);if(m.deep&&n.length){for(r=0,o=n.length;o>r;r++)i(n[r]);s&&(b=a)}}function o(n){var i;return le(u(n.parentNode).reverse(),function(n){var o;i||"_start"==n.id||"_end"==n.id||(o=w(n,e,t,r),o&&o.split!==!1&&(i=n))}),i}function s(e,n,r,i){var o,a,s,l,c,u;if(e){for(u=e.parentNode,o=n.parentNode;o&&o!=u;o=o.parentNode){for(a=q.clone(o,ee),c=0;cC&&(!h[C].ceFalseOverride||!O(h[C],t,n,n));C++);}}function x(e,t,n){var r=p(e);!N(e,t,n)||"toggle"in r[0]&&!r[0].toggle?b(e,t,n):C(e,t,n)}function w(e,t,n,r){function i(e,t,i){var o,a,s=t[i],l;if(t.onmatch)return t.onmatch(e,t,i);if(s)if(s.length===re){for(o in s)if(s.hasOwnProperty(o)){if(a="attributes"===i?q.getAttrib(e,o):A(e,o),r&&!a&&!t.exact)return;if((!r||t.exact)&&!R(a,B(D(s[o],n),o)))return}}else for(l=0;l=0;o--){if(a=t[o].selector,!a||t[o].defaultBlock)return te;for(i=r.length-1;i>=0;i--)if(q.is(r[i],a))return te}return ee}function S(e,t,n){var r;return ne||(ne={},r={},a.on("NodeChange",function(e){var t=u(e.element),n={};t=i.grep(t,function(e){return 1==e.nodeType&&!e.getAttribute("data-mce-bogus")}),le(ne,function(e,i){le(t,function(o){return w(o,i,{},e.similar)?(r[i]||(le(e,function(e){e(!0,{node:o,format:i,parents:t})}),r[i]=e),n[i]=e,!1):void 0})}),le(r,function(i,o){n[o]||(delete r[o],le(i,function(n){n(!1,{node:e.element,format:o,parents:t})}))})})),le(e.split(","),function(e){ne[e]||(ne[e]=[],ne[e].similar=n),ne[e].push(t)}),this}function k(e){return o.getCssText(a,e)}function T(e,t){return R(e,t.inline)?te:R(e,t.block)?te:t.selector?1==e.nodeType&&q.is(e,t.selector):void 0}function R(e,t){return e=e||"",t=t||"",e=""+(e.nodeName||e),t=""+(t.nodeName||t),e.toLowerCase()==t.toLowerCase()}function A(e,t){return B(q.getStyle(e,t),t)}function B(e,t){return("color"==t||"backgroundColor"==t)&&(e=q.toHex(e)),"fontWeight"==t&&700==e&&(e="bold"),"fontFamily"==t&&(e=e.replace(/[\'\"]/g,"").replace(/,\s+/g,",")),""+e}function D(e,t){return"string"!=typeof e?e=e(t):t&&(e=e.replace(/%(\w+)/g,function(e,n){return t[n]||e})),e}function M(e){return e&&3===e.nodeType&&/^([\t \r\n]+|)$/.test(e.nodeValue)}function L(e,t,n){var r=q.create(t,n);return e.parentNode.insertBefore(r,e),r.appendChild(e),r}function P(t,n,r){function i(e){function t(e){return"BR"==e.nodeName&&e.getAttribute("data-mce-bogus")&&!e.nextSibling}var r,i,o,a,s;if(r=i=e?g:y,a=e?"previousSibling":"nextSibling",s=q.getRoot(),3==r.nodeType&&!M(r)&&(e?v>0:bo?n:o,-1===n||r||n++):(n=a.indexOf(" ",t),o=a.indexOf("\xa0",t),n=-1!==n&&(-1===o||o>n)?n:o),n}var s,l,c,u;if(3===t.nodeType){if(c=o(t,n),-1!==c)return{container:t,offset:c};u=t}for(s=new e(t,q.getParent(t,K)||a.getBody());l=s[i?"prev":"next"]();)if(3===l.nodeType){if(u=l,c=o(l),-1!==c)return{container:l,offset:c}}else if(K(l))break;return u?(n=i?0:u.length,{container:u,offset:n}):void 0}function d(e,r){var i,o,a,s;for(3==e.nodeType&&0===e.nodeValue.length&&e[r]&&(e=e[r]),i=u(e),o=0;oh?h:v],3==g.nodeType&&(v=0)),1==y.nodeType&&y.hasChildNodes()&&(h=y.childNodes.length-1,y=y.childNodes[b>h?h:b-1],3==y.nodeType&&(b=y.nodeValue.length)),g=l(g),y=l(y),(se(g.parentNode)||se(g))&&(g=se(g)?g:g.parentNode,g=g.nextSibling||g,3==g.nodeType&&(v=0)),(se(y.parentNode)||se(y))&&(y=se(y)?y:y.parentNode,y=y.previousSibling||y,3==y.nodeType&&(b=y.length)),n[0].inline&&(t.collapsed&&(m=c(g,v,!0),m&&(g=m.container,v=m.offset),m=c(y,b),m&&(y=m.container,b=m.offset)),p=o(y,b),p.node)){for(;p.node&&0===p.offset&&p.node.previousSibling;)p=o(p.node.previousSibling);p.node&&p.offset>0&&3===p.node.nodeType&&" "===p.node.nodeValue.charAt(p.offset-1)&&p.offset>1&&(y=p.node,y.splitText(p.offset-1))}return(n[0].inline||n[0].block_expand)&&(n[0].inline&&3==g.nodeType&&0!==v||(g=i(!0)),n[0].inline&&3==y.nodeType&&b!==y.nodeValue.length||(y=i())),n[0].selector&&n[0].expand!==ee&&!n[0].inline&&(g=d(g,"previousSibling"),y=d(y,"nextSibling")),(n[0].block||n[0].selector)&&(g=f(g,"previousSibling"),y=f(y,"nextSibling"),n[0].block&&(K(g)||(g=i(!0)),K(y)||(y=i()))),1==g.nodeType&&(v=J(g),g=g.parentNode),1==y.nodeType&&(b=J(y)+1,y=y.parentNode),{startContainer:g,startOffset:v,endContainer:y,endOffset:b}}function H(e,t){return t.links&&"A"==e.tagName}function O(e,t,n,r){var i,o,a;if(!T(n,e)&&!H(n,e))return ee;if("all"!=e.remove)for(le(e.styles,function(i,o){i=B(D(i,t),o),"number"==typeof o&&(o=i,r=0),(e.remove_similar||!r||R(A(r,o),i))&&q.setStyle(n,o,""),a=1}),a&&""===q.getAttrib(n,"style")&&(n.removeAttribute("style"),n.removeAttribute("data-mce-style")),le(e.attributes,function(e,i){var o;if(e=D(e,t),"number"==typeof i&&(i=e,r=0),!r||R(q.getAttrib(r,i),e)){if("class"==i&&(e=q.getAttrib(n,i),e&&(o="",le(e.split(/\s+/),function(e){/mce\-\w+/.test(e)&&(o+=(o?" ":"")+e)}),o)))return void q.setAttrib(n,i,o);"class"==i&&n.removeAttribute("className"),Z.test(i)&&n.removeAttribute("data-mce-"+i),n.removeAttribute(i)}}),le(e.classes,function(e){e=D(e,t),(!r||q.hasClass(r,e))&&q.removeClass(n,e)}),o=q.getAttribs(n),i=0;io?o:i]),3===r.nodeType&&n&&i>=r.nodeValue.length&&(r=new e(r,a.getBody()).next()||r),3!==r.nodeType||n||0!==i||(r=new e(r,a.getBody()).prev()||r),r}function V(t,n,r,i){function o(e){var t=q.create("span",{id:g,"data-mce-bogus":!0,style:v?"color:red":""});return e&&t.appendChild(a.getDoc().createTextNode(Q)),t}function l(e,t){for(;e;){if(3===e.nodeType&&e.nodeValue!==Q||e.childNodes.length>1)return!1;t&&1===e.nodeType&&t.push(e),e=e.firstChild}return!0}function c(e){for(;e;){if(e.id===g)return e;e=e.parentNode}}function u(t){var n;if(t)for(n=new e(t,t),t=n.current();t;t=n.next())if(3===t.nodeType)return t}function d(e,t){var n,r;if(e)r=j.getRng(!0),l(e)?(t!==!1&&(r.setStartBefore(e),r.setEndBefore(e)),q.remove(e)):(n=u(e),n.nodeValue.charAt(0)===Q&&(n.deleteData(0,1),r.startContainer==n&&r.startOffset>0&&r.setStart(n,r.startOffset-1),r.endContainer==n&&r.endOffset>0&&r.setEnd(n,r.endOffset-1)),q.remove(e,1)),j.setRng(r);else if(e=c(j.getStart()),!e)for(;e=q.get(g);)d(e,!1)}function f(){var e,t,i,a,s,l,d;e=j.getRng(!0),a=e.startOffset,l=e.startContainer,d=l.nodeValue,t=c(j.getStart()),t&&(i=u(t)),d&&a>0&&a=0;h--)u.appendChild(q.clone(f[h],!1)),u=u.firstChild;u.appendChild(q.doc.createTextNode(Q)),u=u.firstChild;var g=q.getParent(d,s);g&&q.isEmpty(g)?d.parentNode.replaceChild(m,d):q.insertAfter(m,d),j.setCursorLocation(u,1),q.isEmpty(d)&&q.remove(d)}}function m(){var e;e=c(j.getStart()),e&&!q.isEmpty(e)&&ue(e,function(e){1!=e.nodeType||e.id===g||q.isEmpty(e)||q.setAttrib(e,"data-mce-bogus",null)},"childNodes")}var g="_mce_caret",v=a.settings.caret_debug;a._hasCaretEvents||(ae=function(){var e=[],t;if(l(c(j.getStart()),e))for(t=e.length;t--;)q.setAttrib(e[t],"data-mce-bogus","1")},oe=function(e){var t=e.keyCode;d(),8==t&&j.isCollapsed()&&j.getStart().innerHTML==Q&&d(c(j.getStart())),(37==t||39==t)&&d(c(j.getStart())),m()},a.on("SetContent",function(e){e.selection&&m()}),a._hasCaretEvents=!0),"apply"==t?f():h()}function U(t){var n=t.startContainer,r=t.startOffset,i,o,a,s,l;if((t.startContainer!=t.endContainer||!c(t.startContainer.childNodes[t.startOffset]))&&(3==n.nodeType&&r>=n.nodeValue.length&&(r=J(n),n=n.parentNode,i=!0),1==n.nodeType))for(s=n.childNodes,n=s[Math.min(r,s.length-1)],o=new e(n,q.getParent(n,q.isBlock)),(r>s.length-1||i)&&o.next(),a=o.current();a;a=o.next())if(3==a.nodeType&&!M(a))return l=q.create("a",{"data-mce-bogus":"all"},Q),a.parentNode.insertBefore(l,a),t.setStart(a,0),j.setRng(t),void q.remove(l)}var $={},q=a.dom,j=a.selection,Y=new t(q),X=a.schema.isValidChild,K=q.isBlock,G=a.settings.forced_root_block,J=q.nodeIndex,Q="\ufeff",Z=/^(src|href|style)$/,ee=!1,te=!0,ne,re,ie=q.getContentEditable,oe,ae,se=n.isBookmarkNode,le=i.each,ce=i.grep,ue=i.walk,de=i.extend;de(this,{get:p,register:m,unregister:g,apply:b,remove:C,toggle:x,match:N,matchAll:E,matchNode:w,canApply:_,formatChanged:S,getCssText:k}),f(),h(),a.on("BeforeGetContent",function(e){ae&&"raw"!=e.format&&ae()}),a.on("mouseup keydown",function(e){oe&&oe(e)})}}),r(J,[I,h],function(e,t){return function(e){function n(){return e.serializer.getTrimmedContent()}function r(t){e.setDirty(t)}function i(e){o.typing=!1,o.add({},e)}var o=this,a=0,s=[],l,c,u=0;return e.on("init",function(){o.add()}),e.on("BeforeExecCommand",function(e){var t=e.command;"Undo"!=t&&"Redo"!=t&&"mceRepaint"!=t&&o.beforeChange()}),e.on("ExecCommand",function(e){var t=e.command;"Undo"!=t&&"Redo"!=t&&"mceRepaint"!=t&&i(e)}),e.on("ObjectResizeStart Cut",function(){o.beforeChange()}),e.on("SaveContent ObjectResized blur",i),e.on("DragEnd",i),e.on("KeyUp",function(a){var l=a.keyCode;a.isDefaultPrevented()||((l>=33&&36>=l||l>=37&&40>=l||45==l||13==l||a.ctrlKey)&&(i(),e.nodeChanged()),(46==l||8==l||t.mac&&(91==l||93==l))&&e.nodeChanged(),c&&o.typing&&(e.isDirty()||(r(s[0]&&n()!=s[0].content),e.isDirty()&&e.fire("change",{level:s[0],lastLevel:null})),e.fire("TypingUndo"),c=!1,e.nodeChanged()))}),e.on("KeyDown",function(e){var t=e.keyCode;if(!e.isDefaultPrevented()){if(t>=33&&36>=t||t>=37&&40>=t||45==t)return void(o.typing&&i(e));var n=e.ctrlKey&&!e.altKey||e.metaKey;!(16>t||t>20)||224==t||91==t||o.typing||n||(o.beforeChange(),o.typing=!0,o.add({},e),c=!0)}}),e.on("MouseDown",function(e){o.typing&&i(e)}),e.addShortcut("meta+z","","Undo"),e.addShortcut("meta+y,meta+shift+z","","Redo"),e.on("AddUndo Undo Redo ClearUndos",function(t){t.isDefaultPrevented()||e.nodeChanged()}),o={data:s,typing:!1,beforeChange:function(){u||(l=e.selection.getBookmark(2,!0))},add:function(t,i){var o,c=e.settings,d;if(t=t||{},t.content=n(),u||e.removed)return null;if(d=s[a],e.fire("BeforeAddUndo",{level:t,lastLevel:d,originalEvent:i}).isDefaultPrevented())return null;if(d&&d.content==t.content)return null;if(s[a]&&(s[a].beforeBookmark=l),c.custom_undo_redo_levels&&s.length>c.custom_undo_redo_levels){for(o=0;o0&&(r(!0),e.fire("change",f)),t},undo:function(){var t;return o.typing&&(o.add(),o.typing=!1),a>0&&(t=s[--a],e.setContent(t.content,{format:"raw"}),e.selection.moveToBookmark(t.beforeBookmark),r(!0),e.fire("undo",{level:t})),t},redo:function(){var t;return a0||o.typing&&s[0]&&n()!=s[0].content},hasRedo:function(){return aP)&&(u=a.create("br"),t.parentNode.insertBefore(u,t)),l.setStartBefore(t),l.setEndBefore(t)):(l.setStartAfter(t),l.setEndAfter(t)):(l.setStart(t,0),l.setEnd(t,0));s.setRng(l),a.remove(u),s.scrollIntoView(t)}}function y(e){var t=l.forced_root_block;t&&t.toLowerCase()===e.tagName.toLowerCase()&&a.setAttribs(e,l.forced_root_block_attrs)}function b(e){e.innerHTML=r?"":'
    '}function C(e){var t=D,n,i,o,s=u.getTextInlineElements();if(e||"TABLE"==z?(n=a.create(e||V),y(n)):n=L.cloneNode(!1),o=n,l.keep_styles!==!1)do if(s[t.nodeName]){if("_mce_caret"==t.id)continue;i=t.cloneNode(!1),a.setAttrib(i,"id",""),n.hasChildNodes()?(i.appendChild(n.firstChild),n.appendChild(i)):(o=i,n.appendChild(i))}while(t=t.parentNode);return r||(o.innerHTML='
    '),n}function x(t){var n,r,i;if(3==D.nodeType&&(t?M>0:MD.childNodes.length-1,D=D.childNodes[Math.min(M,D.childNodes.length-1)]||D,M=U&&3==D.nodeType?D.nodeValue.length:0),B=S(D)){if(c.beforeChange(),!a.isBlock(B)&&B!=a.getRoot())return void((!V||H)&&E());if((V&&!H||!V&&H)&&(D=w(D,M)),L=a.getParent(D,a.isBlock),F=L?a.getParent(L.parentNode,a.isBlock):null,z=L?L.nodeName.toUpperCase():"",W=F?F.nodeName.toUpperCase():"","LI"!=W||o.ctrlKey||(L=F,z=W),/^(LI|DT|DD)$/.test(z)){if(!V&&H)return void E();if(a.isEmpty(L))return void N()}if("PRE"==z&&l.br_in_pre!==!1){if(!H)return void E()}else if(!V&&!H&&"LI"!=z||V&&H)return void E();V&&L===i.getBody()||(V=V||"P",x()?T():x(!0)?(O=L.parentNode.insertBefore(C(),L),m(O),v(L)):(A=R.cloneRange(),A.setEndAfter(L),I=A.extractContents(),_(I),O=I.firstChild,a.insertAfter(I,L),g(O),k(L),a.isEmpty(L)&&b(L),a.isEmpty(O)?(a.remove(O),T()):v(O)),a.setAttrib(O,"id",""),i.fire("NewBlock",{newBlock:O}),c.add())}}}var a=i.dom,s=i.selection,l=i.settings,c=i.undoManager,u=i.schema,d=u.getNonEmptyElements(),f=u.getMoveCaretBeforeOnEnterElements();i.on("keydown",function(e){13==e.keyCode&&o(e)!==!1&&e.preventDefault()})}}),r(Z,[],function(){return function(e){function t(){var t=i.getStart(),s=e.getBody(),l,c,u,d,f,h,p,m=-16777215,g,v,y,b,C;if(C=n.forced_root_block,t&&1===t.nodeType&&C){for(;t&&t!=s;){if(a[t.nodeName])return;t=t.parentNode}if(l=i.getRng(),l.setStart){c=l.startContainer,u=l.startOffset,d=l.endContainer,f=l.endOffset;try{v=e.getDoc().activeElement===s}catch(x){}}else l.item&&(t=l.item(0),l=e.getDoc().body.createTextRange(),l.moveToElementText(t)),v=l.parentElement().ownerDocument===e.getDoc(),y=l.duplicate(),y.collapse(!0),u=-1*y.move("character",m),y.collapsed||(y=l.duplicate(),y.collapse(!1),f=-1*y.move("character",m)-u);for(t=s.firstChild,b=s.nodeName.toLowerCase();t;)if((3===t.nodeType||1==t.nodeType&&!a[t.nodeName])&&o.isValidChild(b,C.toLowerCase())){if(3===t.nodeType&&0===t.nodeValue.length){p=t,t=t.nextSibling,r.remove(p);continue}h||(h=r.create(C,e.settings.forced_root_block_attrs),t.parentNode.insertBefore(h,t),g=!0),p=t,t=t.nextSibling,h.appendChild(p)}else h=null,t=t.nextSibling;if(g&&v){if(l.setStart)l.setStart(c,u),l.setEnd(d,f),i.setRng(l);else try{l=e.getDoc().body.createTextRange(),l.moveToElementText(s),l.collapse(!0),l.moveStart("character",u),f>0&&l.moveEnd("character",f),l.select()}catch(x){}e.nodeChanged()}}}var n=e.settings,r=e.dom,i=e.selection,o=e.schema,a=o.getBlockElements();n.forced_root_block&&e.on("NodeChange",t)}}),r(ee,[P,h,m,X,T,y],function(e,n,r,i,o,a){var s=r.each,l=r.extend,c=r.map,u=r.inArray,d=r.explode,f=n.ie,h=n.ie&&n.ie<11,p=!0,m=!1;return function(r){function g(e,t,n,i){var o,a,l=0;if(/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(e)||i&&i.skip_focus||r.focus(),i=r.fire("BeforeExecCommand",{command:e,ui:t,value:n}),i.isDefaultPrevented())return!1;if(a=e.toLowerCase(),o=M.exec[a])return o(a,t,n),r.fire("ExecCommand",{command:e,ui:t,value:n}),!0;if(s(r.plugins,function(i){return i.execCommand&&i.execCommand(e,t,n)?(r.fire("ExecCommand",{command:e,ui:t,value:n}),l=!0,!1):void 0}),l)return l;if(r.theme&&r.theme.execCommand&&r.theme.execCommand(e,t,n))return r.fire("ExecCommand",{command:e,ui:t,value:n}),!0;try{l=r.getDoc().execCommand(e,t,n)}catch(c){}return l?(r.fire("ExecCommand",{command:e,ui:t,value:n}),!0):!1}function v(e){var t;if(!r._isHidden()){if(e=e.toLowerCase(),t=M.state[e])return t(e);try{return r.getDoc().queryCommandState(e)}catch(n){}return!1}}function y(e){var t;if(!r._isHidden()){if(e=e.toLowerCase(),t=M.value[e])return t(e);try{return r.getDoc().queryCommandValue(e)}catch(n){}}}function b(e,t){t=t||"exec",s(e,function(e,n){s(n.toLowerCase().split(","),function(n){M[t][n]=e})})}function C(e,t,n){e=e.toLowerCase(),M.exec[e]=function(e,i,o,a){return t.call(n||r,i,o,a)}}function x(e){if(e=e.toLowerCase(),M.exec[e])return!0;try{return r.getDoc().queryCommandSupported(e)}catch(t){}return!1}function w(e,t,n){e=e.toLowerCase(),M.state[e]=function(){return t.call(n||r)}}function N(e,t,n){e=e.toLowerCase(),M.value[e]=function(){return t.call(n||r)}}function E(e){return e=e.toLowerCase(),!!M.exec[e]}function _(e,n,i){return n===t&&(n=m),i===t&&(i=null),r.getDoc().execCommand(e,n,i)}function S(e){return D.match(e)}function k(e,n){D.toggle(e,n?{value:n}:t),r.nodeChanged()}function T(e){P=B.getBookmark(e)}function R(){B.moveToBookmark(P)}var A,B,D,M={state:{},exec:{},value:{}},L=r.settings,P;r.on("PreInit",function(){A=r.dom,B=r.selection,L=r.settings,D=r.formatter}),l(this,{execCommand:g,queryCommandState:v,queryCommandValue:y,queryCommandSupported:x,addCommands:b,addCommand:C,addQueryStateHandler:w,addQueryValueHandler:N,hasCustomCommand:E}),b({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){r.undoManager.add()},"Cut,Copy,Paste":function(e){var t=r.getDoc(),i;try{_(e)}catch(o){i=p}if(i||!t.queryCommandSupported(e)){var a=r.translate("Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.");n.mac&&(a=a.replace(/Ctrl\+/g,"\u2318+")),r.notificationManager.open({text:a,type:"error"})}},unlink:function(){if(B.isCollapsed()){var e=B.getNode();return void("A"==e.tagName&&r.dom.remove(e,!0))}D.remove("link")},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull,JustifyNone":function(e){var t=e.substring(7);"full"==t&&(t="justify"),s("left,center,right,justify".split(","),function(e){t!=e&&D.remove("align"+e)}),"none"!=t&&k("align"+t)},"InsertUnorderedList,InsertOrderedList":function(e){var t,n;_(e),t=A.getParent(B.getNode(),"ol,ul"),t&&(n=t.parentNode,/^(H[1-6]|P|ADDRESS|PRE)$/.test(n.nodeName)&&(T(),A.split(n,t),R()))},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){k(e)},"ForeColor,HiliteColor,FontName":function(e,t,n){k(e,n)},FontSize:function(e,t,n){var r,i;n>=1&&7>=n&&(i=d(L.font_size_style_values),r=d(L.font_size_classes),n=r?r[n-1]||n:i[n-1]||n),k(e,n)},RemoveFormat:function(e){D.remove(e)},mceBlockQuote:function(){k("blockquote")},FormatBlock:function(e,t,n){return k(n||"p")},mceCleanup:function(){var e=B.getBookmark();r.setContent(r.getContent({cleanup:p}),{cleanup:p}),B.moveToBookmark(e)},mceRemoveNode:function(e,t,n){var i=n||B.getNode();i!=r.getBody()&&(T(),r.dom.remove(i,p),R())},mceSelectNodeDepth:function(e,t,n){var i=0;A.getParent(B.getNode(),function(e){return 1==e.nodeType&&i++==n?(B.select(e),m):void 0},r.getBody())},mceSelectNode:function(e,t,n){B.select(n)},mceInsertContent:function(t,n,o){function a(e){function t(e){return r[e]&&3==r[e].nodeType}var n,r,i;return n=B.getRng(!0),r=n.startContainer,i=n.startOffset,3==r.nodeType&&(i>0?e=e.replace(/^ /," "):t("previousSibling")||(e=e.replace(/^ /," ")),i|)$/," "):t("nextSibling")||(e=e.replace(/( | )(
    |)$/," "))),e}function l(){var e,t,n;e=B.getRng(!0),t=e.startContainer,n=e.startOffset,3==t.nodeType&&e.collapsed&&("\xa0"===t.data[n]?(t.deleteData(n,1),/[\u00a0| ]$/.test(o)||(o+=" ")):"\xa0"===t.data[n-1]&&(t.deleteData(n-1,1),/[\u00a0| ]$/.test(o)||(o=" "+o)))}function c(e){if(E)for(x=e.firstChild;x;x=x.walk(!0))S[x.name]&&x.attr("data-mce-new","true")}function u(){if(E){var e=r.getBody(),t=new i(A);s(A.select("*[data-mce-new]"),function(n){n.removeAttribute("data-mce-new");for(var r=n.parentNode;r&&r!=e;r=r.parentNode)t.compare(r,n)&&A.remove(n,!0)})}}function d(e){function t(e){for(var t=r.getBody();e&&e!==t;e=e.parentNode)if("false"===r.dom.getContentEditable(e))return e;return null}var n;if(e){if(B.scrollIntoView(e),n=t(e))return A.remove(e),void B.select(n);C=A.createRng(),x=e.previousSibling,x&&3==x.nodeType?(C.setStart(x,x.nodeValue.length),f||(w=e.nextSibling,w&&3==w.nodeType&&(x.appendData(w.data),w.parentNode.removeChild(w)))):(C.setStartBefore(e),C.setEndBefore(e)),A.remove(e),B.setRng(C)}}var h,p,m,g,v,y,b,C,x,w,N,E,_,S=r.schema.getTextInlineElements();"string"!=typeof o&&(E=o.merge,_=o.data,o=o.content),/^ | $/.test(o)&&(o=a(o)),h=r.parser,p=new e({validate:L.validate},r.schema),N='​',y={content:o,format:"html",selection:!0},r.fire("BeforeSetContent",y),o=y.content,-1==o.indexOf("{$caret}")&&(o+="{$caret}"),o=o.replace(/\{\$caret\}/,N),C=B.getRng();var k=C.startContainer||(C.parentElement?C.parentElement():null),T=r.getBody();k===T&&B.isCollapsed()&&A.isBlock(T.firstChild)&&A.isEmpty(T.firstChild)&&(C=A.createRng(),C.setStart(T.firstChild,0),C.setEnd(T.firstChild,0),B.setRng(C)),B.isCollapsed()||(r.getDoc().execCommand("Delete",!1,null),l()),m=B.getNode();var R={context:m.nodeName.toLowerCase(),data:_};if(v=h.parse(o,R),c(v),x=v.lastChild,"mce_marker"==x.attr("id"))for(b=x,x=x.prev;x;x=x.walk(!0))if(3==x.type||!A.isBlock(x.name)){r.schema.isValidChild(x.parent.name,"span")&&x.parent.insert(b,x,"br"===x.name);break}if(r._selectionOverrides.showBlockCaretContainer(m),R.invalid){for(B.setContent(N),m=B.getNode(),g=r.getBody(),9==m.nodeType?m=x=g:x=m;x!==g;)m=x,x=x.parentNode;o=m==g?g.innerHTML:A.getOuterHTML(m),o=p.serialize(h.parse(o.replace(//i,function(){return p.serialize(v)}))),m==g?A.setHTML(g,o):A.setOuterHTML(m,o)}else o=p.serialize(v),x=m.firstChild,w=m.lastChild,!x||x===w&&"BR"===x.nodeName?A.setHTML(m,o):B.setContent(o);u(),d(A.get("mce_marker")),r.fire("SetContent",y),r.addVisual()},mceInsertRawHTML:function(e,t,n){B.setContent("tiny_mce_marker"),r.setContent(r.getContent().replace(/tiny_mce_marker/g,function(){return n}))},mceToggleFormat:function(e,t,n){k(n)},mceSetContent:function(e,t,n){r.setContent(n)},"Indent,Outdent":function(e){var t,n,i;t=L.indentation,n=/[a-z%]+$/i.exec(t),t=parseInt(t,10),v("InsertUnorderedList")||v("InsertOrderedList")?_(e):(L.forced_root_block||A.getParent(B.getNode(),A.isBlock)||D.apply("div"),s(B.getSelectedBlocks(),function(o){if("false"!==A.getContentEditable(o)&&"LI"!=o.nodeName){var a=r.getParam("indent_use_margin",!1)?"margin":"padding";a+="rtl"==A.getStyle(o,"direction",!0)?"Right":"Left","outdent"==e?(i=Math.max(0,parseInt(o.style[a]||0,10)-t),A.setStyle(o,a,i?i+n:"")):(i=parseInt(o.style[a]||0,10)+t+n,A.setStyle(o,a,i))}}))},mceRepaint:function(){},InsertHorizontalRule:function(){r.execCommand("mceInsertContent",!1,"
    ")},mceToggleVisualAid:function(){r.hasVisual=!r.hasVisual,r.addVisual()},mceReplaceContent:function(e,t,n){r.execCommand("mceInsertContent",!1,n.replace(/\{\$selection\}/g,B.getContent({format:"text"})))},mceInsertLink:function(e,t,n){var r;"string"==typeof n&&(n={href:n}),r=A.getParent(B.getNode(),"a"),n.href=n.href.replace(" ","%20"),r&&n.href||D.remove("link"),n.href&&D.apply("link",n,r)},selectAll:function(){var e=A.getRoot(),t;B.getRng().setStart?(t=A.createRng(),t.setStart(e,0),t.setEnd(e,e.childNodes.length),B.setRng(t)):(t=B.getRng(),t.item||(t.moveToElementText(e),t.select()))},"delete":function(){_("Delete");var e=r.getBody();A.isEmpty(e)&&(r.setContent(""),e.firstChild&&A.isBlock(e.firstChild)?r.selection.setCursorLocation(e.firstChild,0):r.selection.setCursorLocation(e,0))},mceNewDocument:function(){r.setContent("")},InsertLineBreak:function(e,t,n){function i(){for(var e=new a(m,v),t,n=r.schema.getNonEmptyElements();t=e.next();)if(n[t.nodeName.toLowerCase()]||t.length>0)return!0}var s=n,l,c,u,d=B.getRng(!0);new o(A).normalize(d);var f=d.startOffset,m=d.startContainer;if(1==m.nodeType&&m.hasChildNodes()){var g=f>m.childNodes.length-1;m=m.childNodes[Math.min(f,m.childNodes.length-1)]||m,f=g&&3==m.nodeType?m.nodeValue.length:0}var v=A.getParent(m,A.isBlock),y=v?v.nodeName.toUpperCase():"",b=v?A.getParent(v.parentNode,A.isBlock):null,C=b?b.nodeName.toUpperCase():"",x=s&&s.ctrlKey;"LI"!=C||x||(v=b,y=C),m&&3==m.nodeType&&f>=m.nodeValue.length&&(h||i()||(l=A.create("br"),d.insertNode(l),d.setStartAfter(l),d.setEndAfter(l),c=!0)),l=A.create("br"),d.insertNode(l);var w=A.doc.documentMode;return h&&"PRE"==y&&(!w||8>w)&&l.parentNode.insertBefore(A.doc.createTextNode("\r"),l),u=A.create("span",{}," "),l.parentNode.insertBefore(u,l),B.scrollIntoView(u),A.remove(u),c?(d.setStartBefore(l),d.setEndBefore(l)):(d.setStartAfter(l),d.setEndAfter(l)),B.setRng(d),r.undoManager.add(),p}}),b({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(e){var t="align"+e.substring(7),n=B.isCollapsed()?[A.getParent(B.getNode(),A.isBlock)]:B.getSelectedBlocks(),r=c(n,function(e){return!!D.matchNode(e,t)});return-1!==u(r,p)},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){return S(e)},mceBlockQuote:function(){return S("blockquote")},Outdent:function(){var e;if(L.inline_styles){if((e=A.getParent(B.getStart(),A.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return p;if((e=A.getParent(B.getEnd(),A.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return p}return v("InsertUnorderedList")||v("InsertOrderedList")||!L.inline_styles&&!!A.getParent(B.getNode(),"BLOCKQUOTE")},"InsertUnorderedList,InsertOrderedList":function(e){var t=A.getParent(B.getNode(),"ul,ol");return t&&("insertunorderedlist"===e&&"UL"===t.tagName||"insertorderedlist"===e&&"OL"===t.tagName)}},"state"),b({"FontSize,FontName":function(e){var t=0,n;return(n=A.getParent(B.getNode(),"span"))&&(t="fontsize"==e?n.style.fontSize:n.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()),t}},"value"),b({Undo:function(){r.undoManager.undo()},Redo:function(){r.undoManager.redo()}})}}),r(te,[m],function(e){function t(e,o){var a=this,s,l;if(e=r(e),o=a.settings=o||{},s=o.base_uri,/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e))return void(a.source=e);var c=0===e.indexOf("//");0!==e.indexOf("/")||c||(e=(s?s.protocol||"http":"http")+"://mce_host"+e),/^[\w\-]*:?\/\//.test(e)||(l=o.base_uri?o.base_uri.path:new t(location.href).directory,""===o.base_uri.protocol?e="//mce_host"+a.toAbsPath(l,e):(e=/([^#?]*)([#?]?.*)/.exec(e),e=(s&&s.protocol||"http")+"://mce_host"+a.toAbsPath(l,e[1])+e[2])), +e=e.replace(/@@/g,"(mce_at)"),e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e),n(i,function(t,n){var r=e[n];r&&(r=r.replace(/\(mce_at\)/g,"@@")),a[t]=r}),s&&(a.protocol||(a.protocol=s.protocol),a.userInfo||(a.userInfo=s.userInfo),a.port||"mce_host"!==a.host||(a.port=s.port),a.host&&"mce_host"!==a.host||(a.host=s.host),a.source=""),c&&(a.protocol="")}var n=e.each,r=e.trim,i="source protocol authority userInfo user password host port relative path directory file query anchor".split(" "),o={ftp:21,http:80,https:443,mailto:25};return t.prototype={setPath:function(e){var t=this;e=/^(.*?)\/?(\w+)?$/.exec(e),t.path=e[0],t.directory=e[1],t.file=e[2],t.source="",t.getURI()},toRelative:function(e){var n=this,r;if("./"===e)return e;if(e=new t(e,{base_uri:n}),"mce_host"!=e.host&&n.host!=e.host&&e.host||n.port!=e.port||n.protocol!=e.protocol&&""!==e.protocol)return e.getURI();var i=n.getURI(),o=e.getURI();return i==o||"/"==i.charAt(i.length-1)&&i.substr(0,i.length-1)==o?i:(r=n.toRelPath(n.path,e.path),e.query&&(r+="?"+e.query),e.anchor&&(r+="#"+e.anchor),r)},toAbsolute:function(e,n){return e=new t(e,{base_uri:this}),e.getURI(n&&this.isSameOrigin(e))},isSameOrigin:function(e){if(this.host==e.host&&this.protocol==e.protocol){if(this.port==e.port)return!0;var t=o[this.protocol];if(t&&(this.port||t)==(e.port||t))return!0}return!1},toRelPath:function(e,t){var n,r=0,i="",o,a;if(e=e.substring(0,e.lastIndexOf("/")),e=e.split("/"),n=t.split("/"),e.length>=n.length)for(o=0,a=e.length;a>o;o++)if(o>=n.length||e[o]!=n[o]){r=o+1;break}if(e.lengtho;o++)if(o>=e.length||e[o]!=n[o]){r=o+1;break}if(1===r)return t;for(o=0,a=e.length-(r-1);a>o;o++)i+="../";for(o=r-1,a=n.length;a>o;o++)i+=o!=r-1?"/"+n[o]:n[o];return i},toAbsPath:function(e,t){var r,i=0,o=[],a,s;for(a=/\/$/.test(t)?"/":"",e=e.split("/"),t=t.split("/"),n(e,function(e){e&&o.push(e)}),e=o,r=t.length-1,o=[];r>=0;r--)0!==t[r].length&&"."!==t[r]&&(".."!==t[r]?i>0?i--:o.push(t[r]):i++);return r=e.length-i,s=0>=r?o.reverse().join("/"):e.slice(0,r).join("/")+"/"+o.reverse().join("/"),0!==s.indexOf("/")&&(s="/"+s),a&&s.lastIndexOf("/")!==s.length-1&&(s+=a),s},getURI:function(e){var t,n=this;return(!n.source||e)&&(t="",e||(t+=n.protocol?n.protocol+"://":"//",n.userInfo&&(t+=n.userInfo+"@"),n.host&&(t+=n.host),n.port&&(t+=":"+n.port)),n.path&&(t+=n.path),n.query&&(t+="?"+n.query),n.anchor&&(t+="#"+n.anchor),n.source=t),n.source}},t.parseDataUri=function(e){var t,n;return e=decodeURIComponent(e).split(","),n=/data:([^;]+)/.exec(e[0]),n&&(t=n[1]),{type:t,data:e[1]}},t}),r(ne,[m],function(e){function t(){}var n=e.each,r=e.extend,i,o;return t.extend=i=function(e){function t(){var e,t,n,r=this;if(!o&&(r.init&&r.init.apply(r,arguments),t=r.Mixins))for(e=t.length;e--;)n=t[e],n.init&&n.init.apply(r,arguments)}function a(){return this}function s(e,t){return function(){var n=this,r=n._super,i;return n._super=c[e],i=t.apply(n,arguments),n._super=r,i}}var l=this,c=l.prototype,u,d,f;o=!0,u=new l,o=!1,e.Mixins&&(n(e.Mixins,function(t){t=t;for(var n in t)"init"!==n&&(e[n]=t[n])}),c.Mixins&&(e.Mixins=c.Mixins.concat(e.Mixins))),e.Methods&&n(e.Methods.split(","),function(t){e[t]=a}),e.Properties&&n(e.Properties.split(","),function(t){var n="_"+t;e[t]=function(e){var t=this,r;return e!==r?(t[n]=e,t):t[n]}}),e.Statics&&n(e.Statics,function(e,n){t[n]=e}),e.Defaults&&c.Defaults&&(e.Defaults=r({},c.Defaults,e.Defaults));for(d in e)f=e[d],"function"==typeof f&&c[d]?u[d]=s(d,f):u[d]=f;return t.prototype=u,t.constructor=t,t.extend=i,t},t}),r(re,[m],function(e){function t(t){function n(){return!1}function r(){return!0}function i(e,i){var o,s,l,c;if(e=e.toLowerCase(),i=i||{},i.type=e,i.target||(i.target=u),i.preventDefault||(i.preventDefault=function(){i.isDefaultPrevented=r},i.stopPropagation=function(){i.isPropagationStopped=r},i.stopImmediatePropagation=function(){i.isImmediatePropagationStopped=r},i.isDefaultPrevented=n,i.isPropagationStopped=n,i.isImmediatePropagationStopped=n),t.beforeFire&&t.beforeFire(i),o=d[e])for(s=0,l=o.length;l>s;s++){if(c=o[s],c.once&&a(e,c.func),i.isImmediatePropagationStopped())return i.stopPropagation(),i;if(c.func.call(u,i)===!1)return i.preventDefault(),i}return i}function o(t,r,i,o){var a,s,l;if(r===!1&&(r=n),r)for(r={func:r},o&&e.extend(r,o),s=t.toLowerCase().split(" "),l=s.length;l--;)t=s[l],a=d[t],a||(a=d[t]=[],f(t,!0)),i?a.unshift(r):a.push(r);return c}function a(e,t){var n,r,i,o,a;if(e)for(o=e.toLowerCase().split(" "),n=o.length;n--;){if(e=o[n],r=d[e],!e){for(i in d)f(i,!1),delete d[i];return c}if(r){if(t)for(a=r.length;a--;)r[a].func===t&&(r=r.slice(0,a).concat(r.slice(a+1)),d[e]=r);else r.length=0;r.length||(f(e,!1),delete d[e])}}else{for(e in d)f(e,!1);d={}}return c}function s(e,t,n){return o(e,t,n,{once:!0})}function l(e){return e=e.toLowerCase(),!(!d[e]||0===d[e].length)}var c=this,u,d={},f;t=t||{},u=t.scope||c,f=t.toggleEvent||n,c.fire=i,c.on=o,c.off=a,c.once=s,c.has=l}var n=e.makeMap("focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange mouseout mouseenter mouseleave wheel keydown keypress keyup input contextmenu dragstart dragend dragover draggesture dragdrop drop drag submit compositionstart compositionend compositionupdate touchstart touchend"," ");return t.isNative=function(e){return!!n[e.toLowerCase()]},t}),r(ie,[],function(){function e(e){this.create=e.create}return e.create=function(t,n){return new e({create:function(e,r){function i(t){e.set(r,t.value)}function o(e){t.set(n,e.value)}var a;return e.on("change:"+r,o),t.on("change:"+n,i),a=e._bindings,a||(a=e._bindings=[],e.on("destroy",function(){for(var e=a.length;e--;)a[e]()})),a.push(function(){t.off("change:"+n,i)}),t.get(n)}})},e}),r(oe,[re],function(e){function t(t){return t._eventDispatcher||(t._eventDispatcher=new e({scope:t,toggleEvent:function(n,r){e.isNative(n)&&t.toggleNativeEvent&&t.toggleNativeEvent(n,r)}})),t._eventDispatcher}return{fire:function(e,n,r){var i=this;if(i.removed&&"remove"!==e)return n;if(n=t(i).fire(e,n,r),r!==!1&&i.parent)for(var o=i.parent();o&&!n.isPropagationStopped();)o.fire(e,n,!1),o=o.parent();return n},on:function(e,n,r){return t(this).on(e,n,r)},off:function(e,n){return t(this).off(e,n)},once:function(e,n){return t(this).once(e,n)},hasEventListeners:function(e){return t(this).has(e)}}}),r(ae,[ie,oe,ne,m],function(e,t,n,r){function i(e){return e.nodeType>0}function o(e,t){var n,a;if(e===t)return!0;if(null===e||null===t)return e===t;if("object"!=typeof e||"object"!=typeof t)return e===t;if(r.isArray(t)){if(e.length!==t.length)return!1;for(n=e.length;n--;)if(!o(e[n],t[n]))return!1}if(i(e)||i(t))return e===t;a={};for(n in t){if(!o(e[n],t[n]))return!1;a[n]=!0}for(n in e)if(!a[n]&&!o(e[n],t[n]))return!1;return!0}return n.extend({Mixins:[t],init:function(t){var n,r;t=t||{};for(n in t)r=t[n],r instanceof e&&(t[n]=r.create(this,n));this.data=t},set:function(t,n){var r,i,a=this.data[t];if(n instanceof e&&(n=n.create(this,t)),"object"==typeof t){for(r in t)this.set(r,t[r]);return this}return o(a,n)||(this.data[t]=n,i={target:this,name:t,value:n,oldValue:a},this.fire("change:"+t,i),this.fire("change",i)),this},get:function(e){return this.data[e]},has:function(e){return e in this.data},bind:function(t){return e.create(this,t)},destroy:function(){this.fire("destroy")}})}),r(se,[ne],function(e){function t(e){for(var t=[],n=e.length,r;n--;)r=e[n],r.__checked||(t.push(r),r.__checked=1);for(n=t.length;n--;)delete t[n].__checked;return t}var n=/^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@?([\w\\]+)([\^\$\*!~]?=)([\w\\]+)\])?(?:\:(.+))?/i,r=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,i=/^\s*|\s*$/g,o,a=e.extend({init:function(e){function t(e){return e?(e=e.toLowerCase(),function(t){return"*"===e||t.type===e}):void 0}function o(e){return e?function(t){return t._name===e}:void 0}function a(e){return e?(e=e.split("."),function(t){for(var n=e.length;n--;)if(!t.classes.contains(e[n]))return!1;return!0}):void 0}function s(e,t,n){return e?function(r){var i=r[e]?r[e]():"";return t?"="===t?i===n:"*="===t?i.indexOf(n)>=0:"~="===t?(" "+i+" ").indexOf(" "+n+" ")>=0:"!="===t?i!=n:"^="===t?0===i.indexOf(n):"$="===t?i.substr(i.length-n.length)===n:!1:!!n}:void 0}function l(e){var t;return e?(e=/(?:not\((.+)\))|(.+)/i.exec(e),e[1]?(t=u(e[1],[]),function(e){return!d(e,t)}):(e=e[2],function(t,n,r){return"first"===e?0===n:"last"===e?n===r-1:"even"===e?n%2===0:"odd"===e?n%2===1:t[e]?t[e]():!1})):void 0}function c(e,r,c){function u(e){e&&r.push(e)}var d;return d=n.exec(e.replace(i,"")),u(t(d[1])),u(o(d[2])),u(a(d[3])),u(s(d[4],d[5],d[6])),u(l(d[7])),r.pseudo=!!d[7],r.direct=c,r}function u(e,t){var n=[],i,o,a;do if(r.exec(""),o=r.exec(e),o&&(e=o[3],n.push(o[1]),o[2])){i=o[3];break}while(o);for(i&&u(i,t),e=[],a=0;a"!=n[a]&&e.push(c(n[a],[],">"===n[a-1]));return t.push(e),t}var d=this.match;this._selectors=u(e,[])},match:function(e,t){var n,r,i,o,a,s,l,c,u,d,f,h,p;for(t=t||this._selectors,n=0,r=t.length;r>n;n++){for(a=t[n],o=a.length,p=e,h=0,i=o-1;i>=0;i--)for(c=a[i];p;){if(c.pseudo)for(f=p.parent().items(),u=d=f.length;u--&&f[u]!==p;);for(s=0,l=c.length;l>s;s++)if(!c[s](p,u,d)){s=l+1;break}if(s===l){h++;break}if(i===o-1)break;p=p.parent()}if(h===o)return!0}return!1},find:function(e){function n(e,t,i){var o,a,s,l,c,u=t[i];for(o=0,a=e.length;a>o;o++){for(c=e[o],s=0,l=u.length;l>s;s++)if(!u[s](c,o,a)){s=l+1;break}if(s===l)i==t.length-1?r.push(c):c.items&&n(c.items(),t,i+1);else if(u.direct)return;c.items&&n(c.items(),t,i)}}var r=[],i,s,l=this._selectors;if(e.items){for(i=0,s=l.length;s>i;i++)n(e.items(),l[i],0);s>1&&(r=t(r))}return o||(o=a.Collection),new o(r)}});return a}),r(le,[m,se,ne],function(e,t,n){var r,i,o=Array.prototype.push,a=Array.prototype.slice;return i={length:0,init:function(e){e&&this.add(e)},add:function(t){var n=this;return e.isArray(t)?o.apply(n,t):t instanceof r?n.add(t.toArray()):o.call(n,t),n},set:function(e){var t=this,n=t.length,r;for(t.length=0,t.add(e),r=t.length;n>r;r++)delete t[r];return t},filter:function(e){var n=this,i,o,a=[],s,l;for("string"==typeof e?(e=new t(e),l=function(t){return e.match(t)}):l=e,i=0,o=n.length;o>i;i++)s=n[i],l(s)&&a.push(s);return new r(a)},slice:function(){return new r(a.apply(this,arguments))},eq:function(e){return-1===e?this.slice(e):this.slice(e,+e+1)},each:function(t){return e.each(this,t),this},toArray:function(){return e.toArray(this)},indexOf:function(e){for(var t=this,n=t.length;n--&&t[n]!==e;);return n},reverse:function(){return new r(e.toArray(this).reverse())},hasClass:function(e){return this[0]?this[0].classes.contains(e):!1},prop:function(e,t){var n=this,r,i;return t!==r?(n.each(function(n){n[e]&&n[e](t)}),n):(i=n[0],i&&i[e]?i[e]():void 0)},exec:function(t){var n=this,r=e.toArray(arguments).slice(1);return n.each(function(e){e[t]&&e[t].apply(e,r)}),n},remove:function(){for(var e=this.length;e--;)this[e].remove();return this},addClass:function(e){return this.each(function(t){t.classes.add(e)})},removeClass:function(e){return this.each(function(t){t.classes.remove(e)})}},e.each("fire on off show hide append prepend before after reflow".split(" "),function(t){i[t]=function(){var n=e.toArray(arguments);return this.each(function(e){t in e&&e[t].apply(e,n)}),this}}),e.each("text name disabled active selected checked visible parent value data".split(" "),function(e){i[e]=function(t){return this.prop(e,t)}}),r=n.extend(i),t.Collection=r,r}),r(ce,[m,w],function(e,t){var n=0;return{id:function(){return"mceu_"+n++},createFragment:function(e){return t.DOM.createFragment(e)},getWindowSize:function(){return t.DOM.getViewPort()},getSize:function(e){var t,n;if(e.getBoundingClientRect){var r=e.getBoundingClientRect();t=Math.max(r.width||r.right-r.left,e.offsetWidth),n=Math.max(r.height||r.bottom-r.bottom,e.offsetHeight)}else t=e.offsetWidth,n=e.offsetHeight;return{width:t,height:n}},getPos:function(e,n){return t.DOM.getPos(e,n)},getViewPort:function(e){return t.DOM.getViewPort(e)},get:function(e){return document.getElementById(e)},addClass:function(e,n){return t.DOM.addClass(e,n)},removeClass:function(e,n){return t.DOM.removeClass(e,n)},hasClass:function(e,n){return t.DOM.hasClass(e,n)},toggleClass:function(e,n,r){return t.DOM.toggleClass(e,n,r)},css:function(e,n,r){return t.DOM.setStyle(e,n,r)},getRuntimeStyle:function(e,n){return t.DOM.getStyle(e,n,!0)},on:function(e,n,r,i){return t.DOM.bind(e,n,r,i)},off:function(e,n,r){return t.DOM.unbind(e,n,r)},fire:function(e,n,r){return t.DOM.fire(e,n,r)},innerHtml:function(e,n){t.DOM.setHTML(e,n)}}}),r(ue,[],function(){return{parseBox:function(e){var t,n=10;if(e)return"number"==typeof e?(e=e||0,{top:e,left:e,bottom:e,right:e}):(e=e.split(" "),t=e.length,1===t?e[1]=e[2]=e[3]=e[0]:2===t?(e[2]=e[0],e[3]=e[1]):3===t&&(e[3]=e[1]),{top:parseInt(e[0],n)||0,right:parseInt(e[1],n)||0,bottom:parseInt(e[2],n)||0,left:parseInt(e[3],n)||0})},measureBox:function(e,t){function n(t){var n=document.defaultView;return n?(t=t.replace(/[A-Z]/g,function(e){return"-"+e}),n.getComputedStyle(e,null).getPropertyValue(t)):e.currentStyle[t]}function r(e){var t=parseFloat(n(e),10);return isNaN(t)?0:t}return{top:r(t+"TopWidth"),right:r(t+"RightWidth"),bottom:r(t+"BottomWidth"),left:r(t+"LeftWidth")}}}}),r(de,[m],function(e){function t(){}function n(e){this.cls=[],this.cls._map={},this.onchange=e||t,this.prefix=""}return e.extend(n.prototype,{add:function(e){return e&&!this.contains(e)&&(this.cls._map[e]=!0,this.cls.push(e),this._change()),this},remove:function(e){if(this.contains(e)){for(var t=0;t0&&(e+=" "),e+=this.prefix+this.cls[t];return e},n}),r(fe,[u],function(e){var t={},n;return{add:function(r){var i=r.parent();if(i){if(!i._layout||i._layout.isNative())return;t[i._id]||(t[i._id]=i),n||(n=!0,e.requestAnimationFrame(function(){var e,r;n=!1;for(e in t)r=t[e],r.state.get("rendered")&&r.reflow();t={}},document.body))}},remove:function(e){t[e._id]&&delete t[e._id]}}}),r(he,[ne,m,re,ae,le,ce,g,ue,de,fe],function(e,t,n,r,i,o,a,s,l,c){function u(e){return e._eventDispatcher||(e._eventDispatcher=new n({scope:e,toggleEvent:function(t,r){r&&n.isNative(t)&&(e._nativeEvents||(e._nativeEvents={}),e._nativeEvents[t]=!0,e.state.get("rendered")&&d(e))}})),e._eventDispatcher}function d(e){function t(t){var n=e.getParentCtrl(t.target);n&&n.fire(t.type,t)}function n(){var e=c._lastHoverCtrl;e&&(e.fire("mouseleave",{target:e.getEl()}),e.parents().each(function(e){e.fire("mouseleave",{target:e.getEl()})}),c._lastHoverCtrl=null)}function r(t){var n=e.getParentCtrl(t.target),r=c._lastHoverCtrl,i=0,o,a,s;if(n!==r){if(c._lastHoverCtrl=n,a=n.parents().toArray().reverse(),a.push(n),r){for(s=r.parents().toArray().reverse(),s.push(r),i=0;i=i;o--)r=s[o],r.fire("mouseleave",{target:r.getEl()})}for(o=i;oo;o++)c=l[o]._eventsRoot;for(c||(c=l[l.length-1]||e),e._eventsRoot=c,s=o,o=0;s>o;o++)l[o]._eventsRoot=c;var p=c._delegates;p||(p=c._delegates={});for(d in u){if(!u)return!1;"wheel"!==d||h?("mouseenter"===d||"mouseleave"===d?c._hasMouseEnter||(a(c.getEl()).on("mouseleave",n).on("mouseover",r),c._hasMouseEnter=1):p[d]||(a(c.getEl()).on(d,t),p[d]=!0),u[d]=!1):f?a(e.getEl()).on("mousewheel",i):a(e.getEl()).on("DOMMouseScroll",i)}}}var f="onmousewheel"in document,h=!1,p="mce-",m,g=0,v={Statics:{classPrefix:p},isRtl:function(){return m.rtl},classPrefix:p,init:function(e){function n(e){var t;for(e=e.split(" "),t=0;tn.maxW?n.maxW:i,n.w=i,n.innerW=i-o),i=e.h,i!==s&&(i=in.maxH?n.maxH:i,n.h=i,n.innerH=i-a),i=e.innerW,i!==s&&(i=in.maxW-o?n.maxW-o:i,n.innerW=i,n.w=i+o),i=e.innerH,i!==s&&(i=in.maxH-a?n.maxH-a:i,n.innerH=i,n.h=i+a),e.contentW!==s&&(n.contentW=e.contentW),e.contentH!==s&&(n.contentH=e.contentH),r=t._lastLayoutRect,(r.x!==n.x||r.y!==n.y||r.w!==n.w||r.h!==n.h)&&(l=m.repaintControls,l&&l.map&&!l.map[t._id]&&(l.push(t),l.map[t._id]=!0),r.x=n.x,r.y=n.y,r.w=n.w,r.h=n.h),t):n},repaint:function(){var e=this,t,n,r,i,o,a,s,l,c,u;c=document.createRange?function(e){return e}:Math.round,t=e.getEl().style,i=e._layoutRect,l=e._lastRepaintRect||{},o=e.borderBox,a=o.left+o.right,s=o.top+o.bottom,i.x!==l.x&&(t.left=c(i.x)+"px",l.x=i.x),i.y!==l.y&&(t.top=c(i.y)+"px",l.y=i.y),i.w!==l.w&&(u=c(i.w-a),t.width=(u>=0?u:0)+"px",l.w=i.w),i.h!==l.h&&(u=c(i.h-s),t.height=(u>=0?u:0)+"px",l.h=i.h),e._hasBody&&i.innerW!==l.innerW&&(u=c(i.innerW),r=e.getEl("body"),r&&(n=r.style,n.width=(u>=0?u:0)+"px"),l.innerW=i.innerW),e._hasBody&&i.innerH!==l.innerH&&(u=c(i.innerH),r=r||e.getEl("body"),r&&(n=n||r.style,n.height=(u>=0?u:0)+"px"),l.innerH=i.innerH),e._lastRepaintRect=l,e.fire("repaint",{},!1)},on:function(e,t){function n(e){var t,n;return"string"!=typeof e?e:function(i){return t||r.parentsAndSelf().each(function(r){var i=r.settings.callbacks;return i&&(t=i[e])?(n=r,!1):void 0}),t?t.call(n,i):(i.action=e,void this.fire("execute",i))}}var r=this;return u(r).on(e,n(t)),r},off:function(e,t){return u(this).off(e,t),this},fire:function(e,t,n){var r=this;if(t=t||{},t.control||(t.control=r),t=u(r).fire(e,t),n!==!1&&r.parent)for(var i=r.parent();i&&!t.isPropagationStopped();)i.fire(e,t,!1),i=i.parent();return t},hasEventListeners:function(e){return u(this).has(e)},parents:function(e){var t=this,n,r=new i;for(n=t.parent();n;n=n.parent())r.add(n);return e&&(r=r.filter(e)),r},parentsAndSelf:function(e){return new i(this).add(this.parents(e))},next:function(){var e=this.parent().items();return e[e.indexOf(this)+1]},prev:function(){var e=this.parent().items();return e[e.indexOf(this)-1]},innerHtml:function(e){return this.$el.html(e),this},getEl:function(e){var t=e?this._id+"-"+e:this._id;return this._elmCache[t]||(this._elmCache[t]=a("#"+t)[0]),this._elmCache[t]},show:function(){return this.visible(!0)},hide:function(){return this.visible(!1)},focus:function(){try{this.getEl().focus()}catch(e){}return this},blur:function(){return this.getEl().blur(),this},aria:function(e,t){var n=this,r=n.getEl(n.ariaTarget);return"undefined"==typeof t?n._aria[e]:(n._aria[e]=t,n.state.get("rendered")&&r.setAttribute("role"==e?e:"aria-"+e,t),n)},encode:function(e,t){return t!==!1&&(e=this.translate(e)),(e||"").replace(/[&<>"]/g,function(e){return"&#"+e.charCodeAt(0)+";"})},translate:function(e){return m.translate?m.translate(e):e},before:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t),!0),t},after:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t)),t},remove:function(){var e=this,t=e.getEl(),n=e.parent(),r,i;if(e.items){var o=e.items().toArray();for(i=o.length;i--;)o[i].remove()}n&&n.items&&(r=[],n.items().each(function(t){t!==e&&r.push(t)}),n.items().set(r),n._lastRect=null),e._eventsRoot&&e._eventsRoot==e&&a(t).off();var s=e.getRoot().controlIdLookup;return s&&delete s[e._id],t&&t.parentNode&&t.parentNode.removeChild(t),e.state.set("rendered",!1),e.state.destroy(),e.fire("remove"),e},renderBefore:function(e){return a(e).before(this.renderHtml()),this.postRender(),this},renderTo:function(e){return a(e||this.getContainerElm()).append(this.renderHtml()),this.postRender(),this},preRender:function(){},render:function(){},renderHtml:function(){return'
    '},postRender:function(){var e=this,t=e.settings,n,r,i,o,s;e.$el=a(e.getEl()),e.state.set("rendered",!0);for(o in t)0===o.indexOf("on")&&e.on(o.substr(2),t[o]);if(e._eventsRoot){for(i=e.parent();!s&&i;i=i.parent())s=i._eventsRoot;if(s)for(o in s._nativeEvents)e._nativeEvents[o]=!0}d(e),t.style&&(n=e.getEl(),n&&(n.setAttribute("style",t.style),n.style.cssText=t.style)),e.settings.border&&(r=e.borderBox,e.$el.css({"border-top-width":r.top,"border-right-width":r.right,"border-bottom-width":r.bottom,"border-left-width":r.left}));var l=e.getRoot();l.controlIdLookup||(l.controlIdLookup={}),l.controlIdLookup[e._id]=e;for(var u in e._aria)e.aria(u,e._aria[u]);e.state.get("visible")===!1&&(e.getEl().style.display="none"),e.bindStates(),e.state.on("change:visible",function(t){var n=t.value,r;e.state.get("rendered")&&(e.getEl().style.display=n===!1?"none":"",e.getEl().getBoundingClientRect()),r=e.parent(),r&&(r._lastRect=null),e.fire(n?"show":"hide"),c.add(e)}),e.fire("postrender",{},!1)},bindStates:function(){},scrollIntoView:function(e){function t(e,t){var n,r,i=e;for(n=r=0;i&&i!=t&&i.nodeType;)n+=i.offsetLeft||0,r+=i.offsetTop||0,i=i.offsetParent;return{x:n,y:r}}var n=this.getEl(),r=n.parentNode,i,o,a,s,l,c,u=t(n,r);return i=u.x,o=u.y,a=n.offsetWidth,s=n.offsetHeight,l=r.clientWidth,c=r.clientHeight,"end"==e?(i-=l-a,o-=c-s):"center"==e&&(i-=l/2-a/2,o-=c/2-s/2),r.scrollLeft=i,r.scrollTop=o,this},getRoot:function(){for(var e=this,t,n=[];e;){if(e.rootControl){t=e.rootControl;break}n.push(e),t=e,e=e.parent()}t||(t=this);for(var r=n.length;r--;)n[r].rootControl=t;return t},reflow:function(){c.remove(this);var e=this.parent();return e._layout&&!e._layout.isNative()&&e.reflow(),this}};return t.each("text title visible disabled active value".split(" "),function(e){v[e]=function(t){return 0===arguments.length?this.state.get(e):("undefined"!=typeof t&&this.state.set(e,t),this)}}),m=e.extend(v)}),r(pe,[],function(){var e={},t;return{add:function(t,n){e[t.toLowerCase()]=n},has:function(t){return!!e[t.toLowerCase()]},create:function(n,r){var i,o,a;if(!t){a=tinymce.ui;for(o in a)e[o.toLowerCase()]=a[o];t=!0}if("string"==typeof n?(r=r||{},r.type=n):(r=n,n=r.type),n=n.toLowerCase(),i=e[n],!i)throw new Error("Could not find control by type: "+n);return i=new i(r),i.type=n,i}}}),r(me,[],function(){return function(e){function t(e){return e&&1===e.nodeType}function n(e){return e=e||C,t(e)?e.getAttribute("role"):null}function r(e){for(var t,r=e||C;r=r.parentNode;)if(t=n(r))return t}function i(e){var n=C;return t(n)?n.getAttribute("aria-"+e):void 0}function o(e){var t=e.tagName.toUpperCase();return"INPUT"==t||"TEXTAREA"==t}function a(e){return o(e)&&!e.hidden?!0:/^(button|menuitem|checkbox|tab|menuitemcheckbox|option|gridcell)$/.test(n(e))?!0:!1}function s(e){function t(e){if(1==e.nodeType&&"none"!=e.style.display){a(e)&&n.push(e);for(var r=0;re?e=t.length-1:e>=t.length&&(e=0),t[e]&&t[e].focus(),e}function d(e,t){var n=-1,r=l();t=t||s(r.getEl());for(var i=0;i=0&&(n=t.getEl(),n&&n.parentNode.removeChild(n),n=e.getEl(),n&&n.parentNode.removeChild(n)),t.parent(this)},create:function(t){var n=this,i,a=[];return o.isArray(t)||(t=[t]),o.each(t,function(t){t&&(t instanceof e||("string"==typeof t&&(t={type:t}),i=o.extend({},n.settings.defaults,t),t.type=i.type=i.type||t.type||n.settings.defaultType||(i.defaults?i.defaults.type:null),t=r.create(i)),a.push(t))}),a},renderNew:function(){var e=this;return e.items().each(function(t,n){var r;t.parent(e),t.state.get("rendered")||(r=e.getEl("body"),r.hasChildNodes()&&n<=r.childNodes.length-1?a(r.childNodes[n]).before(t.renderHtml()):a(r).append(t.renderHtml()),t.postRender(),l.add(t))}),e._layout.applyClasses(e.items().filter(":visible")),e._lastRect=null,e},append:function(e){return this.add(e).renderNew()},prepend:function(e){var t=this;return t.items().set(t.create(e).concat(t.items().toArray())),t.renderNew()},insert:function(e,t,n){var r=this,i,o,a;return e=r.create(e),i=r.items(),!n&&t=0&&t
    '+(e.settings.html||"")+t.renderHtml(e)+"
    "},postRender:function(){var e=this,t;return e.items().exec("postRender"),e._super(),e._layout.postRender(e),e.state.set("rendered",!0),e.settings.style&&e.$el.css(e.settings.style),e.settings.border&&(t=e.borderBox,e.$el.css({"border-top-width":t.top,"border-right-width":t.right,"border-bottom-width":t.bottom,"border-left-width":t.left})),e.parent()||(e.keyboardNav=new i({root:e})),e},initLayoutRect:function(){var e=this,t=e._super();return e._layout.recalc(e),t},recalc:function(){var e=this,t=e._layoutRect,n=e._lastRect;return n&&n.w==t.w&&n.h==t.h?void 0:(e._layout.recalc(e),t=e.layoutRect(),e._lastRect={x:t.x,y:t.y,w:t.w,h:t.h},!0)},reflow:function(){var t;if(l.remove(this),this.visible()){for(e.repaintControls=[],e.repaintControls.map={},this.recalc(),t=e.repaintControls.length;t--;)e.repaintControls[t].repaint();"flow"!==this.settings.layout&&"stack"!==this.settings.layout&&this.repaint(),e.repaintControls=[]}return this}})}),r(ve,[g],function(e){function t(e){var t,n,r,i,o,a,s,l,c=Math.max;return t=e.documentElement,n=e.body,r=c(t.scrollWidth,n.scrollWidth),i=c(t.clientWidth,n.clientWidth),o=c(t.offsetWidth,n.offsetWidth),a=c(t.scrollHeight,n.scrollHeight),s=c(t.clientHeight,n.clientHeight),l=c(t.offsetHeight,n.offsetHeight),{width:o>r?i:r,height:l>a?s:a}}function n(e){var t,n;if(e.changedTouches)for(t="screenX screenY pageX pageY clientX clientY".split(" "),n=0;n").css({position:"absolute",top:0,left:0,width:c.width,height:c.height,zIndex:2147483647,opacity:1e-4,cursor:m}).appendTo(s.body),e(s).on("mousemove touchmove",d).on("mouseup touchend",u),i.start(r)},d=function(e){return n(e),e.button!==l?u(e):(e.deltaX=e.screenX-f,e.deltaY=e.screenY-h,e.preventDefault(),void i.drag(e))},u=function(t){n(t),e(s).off("mousemove touchmove",d).off("mouseup touchend",u),a.remove(),i.stop&&i.stop(t)},this.destroy=function(){e(o()).off()},e(o()).on("mousedown touchstart",c)}}),r(ye,[g,ve],function(e,t){return{init:function(){var e=this;e.on("repaint",e.renderScroll)},renderScroll:function(){function n(){function t(t,a,s,l,c,u){var d,f,h,p,m,g,v,y,b;if(f=i.getEl("scroll"+t)){if(y=a.toLowerCase(),b=s.toLowerCase(),e(i.getEl("absend")).css(y,i.layoutRect()[l]-1),!c)return void e(f).css("display","none");e(f).css("display","block"),d=i.getEl("body"),h=i.getEl("scroll"+t+"t"),p=d["client"+s]-2*o,p-=n&&r?f["client"+u]:0, +m=d["scroll"+s],g=p/m,v={},v[y]=d["offset"+a]+o,v[b]=p,e(f).css(v),v={},v[y]=d["scroll"+a]*g,v[b]=p*g,e(h).css(v)}}var n,r,a;a=i.getEl("body"),n=a.scrollWidth>a.clientWidth,r=a.scrollHeight>a.clientHeight,t("h","Left","Width","contentW",n,"Height"),t("v","Top","Height","contentH",r,"Width")}function r(){function n(n,r,a,s,l){var c,u=i._id+"-scroll"+n,d=i.classPrefix;e(i.getEl()).append('
    '),i.draghelper=new t(u+"t",{start:function(){c=i.getEl("body")["scroll"+r],e("#"+u).addClass(d+"active")},drag:function(e){var t,u,d,f,h=i.layoutRect();u=h.contentW>h.innerW,d=h.contentH>h.innerH,f=i.getEl("body")["client"+a]-2*o,f-=u&&d?i.getEl("scroll"+n)["client"+l]:0,t=f/i.getEl("body")["scroll"+a],i.getEl("body")["scroll"+r]=c+e["delta"+s]/t},stop:function(){e("#"+u).removeClass(d+"active")}})}i.classes.add("scroll"),n("v","Top","Height","Y","Width"),n("h","Left","Width","X","Height")}var i=this,o=2;i.settings.autoScroll&&(i._hasScroll||(i._hasScroll=!0,r(),i.on("wheel",function(e){var t=i.getEl("body");t.scrollLeft+=10*(e.deltaX||0),t.scrollTop+=10*e.deltaY,n()}),e(i.getEl("body")).on("scroll",n)),n())}}}),r(be,[ge,ye],function(e,t){return e.extend({Defaults:{layout:"fit",containerCls:"panel"},Mixins:[t],renderHtml:function(){var e=this,t=e._layout,n=e.settings.html;return e.preRender(),t.preRender(e),"undefined"==typeof n?n='
    '+t.renderHtml(e)+"
    ":("function"==typeof n&&(n=n.call(e)),e._hasBody=!1),'
    '+(e._preBodyHtml||"")+n+"
    "}})}),r(Ce,[ce],function(e){function t(t,n,r){var i,o,a,s,l,c,u,d,f,h;return f=e.getViewPort(),o=e.getPos(n),a=o.x,s=o.y,t.state.get("fixed")&&"static"==e.getRuntimeStyle(document.body,"position")&&(a-=f.x,s-=f.y),i=t.getEl(),h=e.getSize(i),l=h.width,c=h.height,h=e.getSize(n),u=h.width,d=h.height,r=(r||"").split(""),"b"===r[0]&&(s+=d),"r"===r[1]&&(a+=u),"c"===r[0]&&(s+=Math.round(d/2)),"c"===r[1]&&(a+=Math.round(u/2)),"b"===r[3]&&(s-=c),"r"===r[4]&&(a-=l),"c"===r[3]&&(s-=Math.round(c/2)),"c"===r[4]&&(a-=Math.round(l/2)),{x:a,y:s,w:l,h:c}}return{testMoveRel:function(n,r){for(var i=e.getViewPort(),o=0;o0&&a.x+a.w0&&a.y+a.hi.x&&a.x+a.wi.y&&a.y+a.he?0:e+n>t?(e=t-n,0>e?0:e):e}var i=this;if(i.settings.constrainToViewport){var o=e.getViewPort(window),a=i.layoutRect();t=r(t,o.w+o.x,a.w),n=r(n,o.h+o.y,a.h)}return i.state.get("rendered")?i.layoutRect({x:t,y:n}).repaint():(i.settings.x=t,i.settings.y=n),i.fire("move",{x:t,y:n}),i}}}),r(xe,[ce],function(e){return{resizeToContent:function(){this._layoutRect.autoResize=!0,this._lastRect=null,this.reflow()},resizeTo:function(t,n){if(1>=t||1>=n){var r=e.getWindowSize();t=1>=t?t*r.w:t,n=1>=n?n*r.h:n}return this._layoutRect.autoResize=!1,this.layoutRect({minW:t,minH:n,w:t,h:n}).reflow()},resizeBy:function(e,t){var n=this,r=n.layoutRect();return n.resizeTo(r.w+e,r.h+t)}}}),r(we,[be,Ce,xe,ce,g,u],function(e,t,n,r,i,o){function a(e,t){for(;e;){if(e==t)return!0;e=e.parent()}}function s(e){for(var t=v.length;t--;){var n=v[t],r=n.getParentCtrl(e.target);if(n.settings.autohide){if(r&&(a(r,n)||n.parent()===r))continue;e=n.fire("autohide",{target:e.target}),e.isDefaultPrevented()||n.hide()}}}function l(){p||(p=function(e){2!=e.button&&s(e)},i(document).on("click touchstart",p))}function c(){m||(m=function(){var e;for(e=v.length;e--;)d(v[e])},i(window).on("scroll",m))}function u(){if(!g){var e=document.documentElement,t=e.clientWidth,n=e.clientHeight;g=function(){document.all&&t==e.clientWidth&&n==e.clientHeight||(t=e.clientWidth,n=e.clientHeight,C.hideAll())},i(window).on("resize",g)}}function d(e){function t(t,n){for(var r,i=0;in&&(e.fixed(!1).layoutRect({y:e._autoFixY}).repaint(),t(!1,e._autoFixY-n)):(e._autoFixY=e.layoutRect().y,e._autoFixY
    ').appendTo(t.getContainerElm())),o.setTimeout(function(){n.addClass(r+"in"),i(t.getEl()).addClass(r+"in")}),b=!0),f(!0,t)}}),t.on("show",function(){t.parents().each(function(e){return e.state.get("fixed")?(t.fixed(!0),!1):void 0})}),e.popover&&(t._preBodyHtml='
    ',t.classes.add("popover").add("bottom").add(t.isRtl()?"end":"start"))},fixed:function(e){var t=this;if(t.state.get("fixed")!=e){if(t.state.get("rendered")){var n=r.getViewPort();e?t.layoutRect().y-=n.y:t.layoutRect().y+=n.y}t.classes.toggle("fixed",e),t.state.set("fixed",e)}return t},show:function(){var e=this,t,n=e._super();for(t=v.length;t--&&v[t]!==e;);return-1===t&&v.push(e),n},hide:function(){return h(this),f(!1,this),this._super()},hideAll:function(){C.hideAll()},close:function(){var e=this;return e.fire("close").isDefaultPrevented()||(e.remove(),f(!1,e)),e},remove:function(){h(this),this._super()},postRender:function(){var e=this;return e.settings.bodyRole&&this.getEl("body").setAttribute("role",e.settings.bodyRole),e._super()}});return C.hideAll=function(){for(var e=v.length;e--;){var t=v[e];t&&t.settings.autohide&&(t.hide(),v.splice(e,1))}},C}),r(Ne,[we,be,ce,g,ve,ue,h,u],function(e,t,n,r,i,o,a,s){function l(e){var t="width=device-width,initial-scale=1.0,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0",n=r("meta[name=viewport]")[0],i;a.overrideViewPort!==!1&&(n||(n=document.createElement("meta"),n.setAttribute("name","viewport"),document.getElementsByTagName("head")[0].appendChild(n)),i=n.getAttribute("content"),i&&"undefined"!=typeof f&&(f=i),n.setAttribute("content",e?t:f))}function c(e){for(var t=0;tr.w&&(o=r.x-Math.max(0,i/2),e.layoutRect({w:i,x:o}),a=!0)),t&&(t.layoutRect({w:e.layoutRect().innerW}).recalc(),i=t.layoutRect().minW+r.deltaW,i>r.w&&(o=r.x-Math.max(0,i-r.w),e.layoutRect({w:i,x:o}),a=!0)),a&&e.recalc()},initLayoutRect:function(){var e=this,t=e._super(),r=0,i;if(e.settings.title&&!e._fullscreen){i=e.getEl("head");var o=n.getSize(i);t.headerW=o.width,t.headerH=o.height,r+=t.headerH}e.statusbar&&(r+=e.statusbar.layoutRect().h),t.deltaH+=r,t.minH+=r,t.h+=r;var a=n.getWindowSize();return t.x=e.settings.x||Math.max(0,a.w/2-t.w/2),t.y=e.settings.y||Math.max(0,a.h/2-t.h/2),t},renderHtml:function(){var e=this,t=e._layout,n=e._id,r=e.classPrefix,i=e.settings,o="",a="",s=i.html;return e.preRender(),t.preRender(e),i.title&&(o='
    '+e.encode(i.title)+'
    '),i.url&&(s=''),"undefined"==typeof s&&(s=t.renderHtml(e)),e.statusbar&&(a=e.statusbar.renderHtml()),'
    '+o+'
    '+s+"
    "+a+"
    "},fullscreen:function(e){var t=this,i=document.documentElement,a,l=t.classPrefix,c;if(e!=t._fullscreen)if(r(window).on("resize",function(){var e;if(t._fullscreen)if(a)t._timer||(t._timer=s.setTimeout(function(){var e=n.getWindowSize();t.moveTo(0,0).resizeTo(e.w,e.h),t._timer=0},50));else{e=(new Date).getTime();var r=n.getWindowSize();t.moveTo(0,0).resizeTo(r.w,r.h),(new Date).getTime()-e>50&&(a=!0)}}),c=t.layoutRect(),t._fullscreen=e,e){t._initial={x:c.x,y:c.y,w:c.w,h:c.h},t.borderBox=o.parseBox("0"),t.getEl("head").style.display="none",c.deltaH-=c.headerH+2,r([i,document.body]).addClass(l+"fullscreen"),t.classes.add("fullscreen");var u=n.getWindowSize();t.moveTo(0,0).resizeTo(u.w,u.h)}else t.borderBox=o.parseBox(t.settings.border),t.getEl("head").style.display="",c.deltaH+=c.headerH,r([i,document.body]).removeClass(l+"fullscreen"),t.classes.remove("fullscreen"),t.moveTo(t._initial.x,t._initial.y).resizeTo(t._initial.w,t._initial.h);return t.reflow()},postRender:function(){var e=this,t;setTimeout(function(){e.classes.add("in")},0),e._super(),e.statusbar&&e.statusbar.postRender(),e.focus(),this.dragHelper=new i(e._id+"-dragh",{start:function(){t={x:e.layoutRect().x,y:e.layoutRect().y}},drag:function(n){e.moveTo(t.x+n.deltaX,t.y+n.deltaY)}}),e.on("submit",function(t){t.isDefaultPrevented()||e.close()}),d.push(e),l(!0)},submit:function(){return this.fire("submit",{data:this.toJSON()})},remove:function(){var e=this,t;for(e.dragHelper.destroy(),e._super(),e.statusbar&&this.statusbar.remove(),t=d.length;t--;)d[t]===e&&d.splice(t,1);l(d.length>0),c(e.classPrefix)},getContentWindow:function(){var e=this.getEl().getElementsByTagName("iframe")[0];return e?e.contentWindow:null}});return a.desktop||u(),h}),r(Ee,[Ne],function(e){var t=e.extend({init:function(e){e={border:1,padding:20,layout:"flex",pack:"center",align:"center",containerCls:"panel",autoScroll:!0,buttons:{type:"button",text:"Ok",action:"ok"},items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200}},this._super(e)},Statics:{OK:1,OK_CANCEL:2,YES_NO:3,YES_NO_CANCEL:4,msgBox:function(n){function r(e,t,n){return{type:"button",text:e,subtype:n?"primary":"",onClick:function(e){e.control.parents()[1].close(),o(t)}}}var i,o=n.callback||function(){};switch(n.buttons){case t.OK_CANCEL:i=[r("Ok",!0,!0),r("Cancel",!1)];break;case t.YES_NO:case t.YES_NO_CANCEL:i=[r("Yes",1,!0),r("No",0)],n.buttons==t.YES_NO_CANCEL&&i.push(r("Cancel",-1));break;default:i=[r("Ok",!0,!0)]}return new e({padding:20,x:n.x,y:n.y,minWidth:300,minHeight:100,layout:"flex",pack:"center",align:"center",buttons:i,title:n.title,role:"alertdialog",items:{type:"label",multiline:!0,maxWidth:500,maxHeight:200,text:n.text},onPostRender:function(){this.aria("describedby",this.items()[0]._id)},onClose:n.onClose,onCancel:function(){o(!1)}}).renderTo(document.body).reflow()},alert:function(e,n){return"string"==typeof e&&(e={text:e}),e.callback=n,t.msgBox(e)},confirm:function(e,n){return"string"==typeof e&&(e={text:e}),e.callback=n,e.buttons=t.OK_CANCEL,t.msgBox(e)}}});return t}),r(_e,[Ne,Ee],function(e,t){return function(n){function r(){return o.length?o[o.length-1]:void 0}var i=this,o=[];i.windows=o,n.on("remove",function(){for(var e=o.length;e--;)o[e].close()}),i.open=function(t,r){var i;return n.editorManager.setActive(n),t.title=t.title||" ",t.url=t.url||t.file,t.url&&(t.width=parseInt(t.width||320,10),t.height=parseInt(t.height||240,10)),t.body&&(t.items={defaults:t.defaults,type:t.bodyType||"form",items:t.body}),t.url||t.buttons||(t.buttons=[{text:"Ok",subtype:"primary",onclick:function(){i.find("form")[0].submit()}},{text:"Cancel",onclick:function(){i.close()}}]),i=new e(t),o.push(i),i.on("close",function(){for(var e=o.length;e--;)o[e]===i&&o.splice(e,1);o.length||n.focus()}),t.data&&i.on("postRender",function(){this.find("*").each(function(e){var n=e.name();n in t.data&&e.value(t.data[n])})}),i.features=t||{},i.params=r||{},1===o.length&&n.nodeChanged(),i.renderTo().reflow()},i.alert=function(e,r,i){t.alert(e,function(){r?r.call(i||this):n.focus()})},i.confirm=function(e,n,r){t.confirm(e,function(e){n.call(r||this,e)})},i.close=function(){r()&&r().close()},i.getParams=function(){return r()?r().params:null},i.setParams=function(e){r()&&(r().params=e)},i.getWindows=function(){return o}}}),r(Se,[he,Ce],function(e,t){return e.extend({Mixins:[t],Defaults:{classes:"widget tooltip tooltip-n"},renderHtml:function(){var e=this,t=e.classPrefix;return'"},bindStates:function(){var e=this;return e.state.on("change:text",function(t){e.getEl().lastChild.innerHTML=e.encode(t.value)}),e._super()},repaint:function(){var e=this,t,n;t=e.getEl().style,n=e._layoutRect,t.left=n.x+"px",t.top=n.y+"px",t.zIndex=131070}})}),r(ke,[he,Se],function(e,t){var n,r=e.extend({init:function(e){var t=this;t._super(e),e=t.settings,t.canFocus=!0,e.tooltip&&r.tooltips!==!1&&(t.on("mouseenter",function(n){var r=t.tooltip().moveTo(-65535);if(n.control==t){var i=r.text(e.tooltip).show().testMoveRel(t.getEl(),["bc-tc","bc-tl","bc-tr"]);r.classes.toggle("tooltip-n","bc-tc"==i),r.classes.toggle("tooltip-nw","bc-tl"==i),r.classes.toggle("tooltip-ne","bc-tr"==i),r.moveRel(t.getEl(),i)}else r.hide()}),t.on("mouseleave mousedown click",function(){t.tooltip().hide()})),t.aria("label",e.ariaLabel||e.tooltip)},tooltip:function(){return n||(n=new t({type:"tooltip"}),n.renderTo()),n},postRender:function(){var e=this,t=e.settings;e._super(),e.parent()||!t.width&&!t.height||(e.initLayoutRect(),e.repaint()),t.autofocus&&e.focus()},bindStates:function(){function e(e){n.aria("disabled",e),n.classes.toggle("disabled",e)}function t(e){n.aria("pressed",e),n.classes.toggle("active",e)}var n=this;return n.state.on("change:disabled",function(t){e(t.value)}),n.state.on("change:active",function(e){t(e.value)}),n.state.get("disabled")&&e(!0),n.state.get("active")&&t(!0),n._super()},remove:function(){this._super(),n&&(n.remove(),n=null)}});return r}),r(Te,[ke],function(e){return e.extend({Defaults:{value:0},init:function(e){var t=this;t._super(e),t.classes.add("progress"),t.settings.filter||(t.settings.filter=function(e){return Math.round(e)})},renderHtml:function(){var e=this,t=e._id,n=this.classPrefix;return'
    0%
    '},postRender:function(){var e=this;return e._super(),e.value(e.settings.value),e},bindStates:function(){function e(e){e=t.settings.filter(e),t.getEl().lastChild.innerHTML=e+"%",t.getEl().firstChild.firstChild.style.width=e+"%"}var t=this;return t.state.on("change:value",function(t){e(t.value)}),e(t.state.get("value")),t._super()}})}),r(Re,[he,Ce,Te],function(e,t,n){return e.extend({Mixins:[t],Defaults:{classes:"widget notification"},init:function(e){var t=this;t._super(e),e.text&&t.text(e.text),e.icon&&(t.icon=e.icon),e.color&&(t.color=e.color),e.type&&t.classes.add("notification-"+e.type),e.timeout&&(e.timeout<0||e.timeout>0)&&!e.closeButton?t.closeButton=!1:(t.classes.add("has-close"),t.closeButton=!0),e.progressBar&&(t.progressBar=new n),t.on("click",function(e){-1!=e.target.className.indexOf(t.classPrefix+"close")&&t.close()})},renderHtml:function(){var e=this,t=e.classPrefix,n="",r="",i="",o="";return e.icon&&(n=''),e.color&&(o=' style="background-color: '+e.color+'"'),e.closeButton&&(r=''),e.progressBar&&(i=e.progressBar.renderHtml()),'"},bindStates:function(){var e=this;return e.state.on("change:text",function(t){e.getEl().childNodes[1].innerHTML=t.value}),e.progressBar&&e.progressBar.bindStates(),e._super()},close:function(){var e=this;return e.fire("close").isDefaultPrevented()||e.remove(),e},repaint:function(){var e=this,t,n;t=e.getEl().style,n=e._layoutRect,t.left=n.x+"px",t.top=n.y+"px",t.zIndex=131070}})}),r(Ae,[Re,u],function(e,t){return function(n){function r(){return l.length?l[l.length-1]:void 0}function i(){t.requestAnimationFrame(function(){o(),a()})}function o(){for(var e=0;e0){var e=l.slice(0,1)[0],t=n.inline?n.getElement():n.getContentAreaContainer();if(e.moveRel(t,"tc-tc"),l.length>1)for(var r=1;r0&&(r.timer=setTimeout(function(){r.close()},t.timeout)),r.on("close",function(){var e=l.length;for(r.timer&&n.getWin().clearTimeout(r.timer);e--;)l[e]===r&&l.splice(e,1);a()}),r.renderTo(),a(),r},s.close=function(){r()&&r().close()},s.getNotifications=function(){return l}}}),r(Be,[w],function(e){function t(t,n,r){for(var i=[];n&&n!=t;n=n.parentNode)i.push(e.nodeIndex(n,r));return i}function n(e,t){var n,r,i;for(r=e,n=t.length-1;n>=0;n--){if(i=r.childNodes,t[n]>i.length-1)return null;r=i[t[n]]}return r}return{create:t,resolve:n}}),r(De,[I,T,y,Be,A,C,h,m,u,k],function(e,t,n,r,i,o,a,s,l,c){return function(u){function d(e,t){try{u.getDoc().execCommand(e,!1,t)}catch(n){}}function f(){var e=u.getDoc().documentMode;return e?e:6}function h(e){return e.isDefaultPrevented()}function p(e){var t,n;e.dataTransfer&&(u.selection.isCollapsed()&&"IMG"==e.target.tagName&&Q.select(e.target),t=u.selection.getContent(),t.length>0&&(n=oe+escape(u.id)+","+escape(t),e.dataTransfer.setData(ae,n)))}function m(e){var t;return e.dataTransfer&&(t=e.dataTransfer.getData(ae),t&&t.indexOf(oe)>=0)?(t=t.substr(oe.length).split(","),{id:unescape(t[0]),html:unescape(t[1])}):null}function g(e){u.queryCommandSupported("mceInsertClipboardContent")?u.execCommand("mceInsertClipboardContent",!1,{content:e}):u.execCommand("mceInsertContent",!1,e)}function v(){function i(e){var t=C.schema.getBlockElements(),n=u.getBody();if("BR"!=e.nodeName)return!1;for(e=e;e!=n&&!t[e.nodeName];e=e.parentNode)if(e.nextSibling)return!1;return!0}function o(e,t){var n;for(n=e.nextSibling;n&&n!=t;n=n.nextSibling)if((3!=n.nodeType||0!==X.trim(n.data).length)&&n!==t)return!1;return n===t}function a(e,t,r){var o,a,s;for(s=C.schema.getNonEmptyElements(),o=new n(r||e,e);a=o[t?"next":"prev"]();){if(s[a.nodeName]&&!i(a))return a;if(3==a.nodeType&&a.data.length>0)return a}}function c(e){var n,r,i,o,s;if(!e.collapsed&&(n=C.getParent(t.getNode(e.startContainer,e.startOffset),C.isBlock),r=C.getParent(t.getNode(e.endContainer,e.endOffset),C.isBlock),s=u.schema.getTextBlockElements(),n!=r&&s[n.nodeName]&&s[r.nodeName]&&"false"!==C.getContentEditable(n)&&"false"!==C.getContentEditable(r)))return e.deleteContents(),i=a(n,!1),o=a(r,!0),C.isEmpty(r)||X(n).append(r.childNodes),X(r).remove(),i?1==i.nodeType?"BR"==i.nodeName?(e.setStartBefore(i),e.setEndBefore(i)):(e.setStartAfter(i),e.setEndAfter(i)):(e.setStart(i,i.data.length),e.setEnd(i,i.data.length)):o&&(1==o.nodeType?(e.setStartBefore(o),e.setEndBefore(o)):(e.setStart(o,0),e.setEnd(o,0))),x.setRng(e),!0}function d(e,n){var r,i,s,l,c,d;if(!e.collapsed)return e;if(c=e.startContainer,d=e.startOffset,3==c.nodeType)if(n){if(d0)return e;if(r=t.getNode(e.startContainer,e.startOffset),s=C.getParent(r,C.isBlock),i=a(u.getBody(),n,r),l=C.getParent(i,C.isBlock),!r||!i)return e;if(l&&s!=l)if(n){if(!o(s,l))return e;1==r.nodeType?"BR"==r.nodeName?e.setStartBefore(r):e.setStartAfter(r):e.setStart(r,r.data.length),1==i.nodeType?e.setEnd(i,0):e.setEndBefore(i)}else{if(!o(l,s))return e;1==i.nodeType?"BR"==i.nodeName?e.setStartBefore(i):e.setStartAfter(i):e.setStart(i,i.data.length),1==r.nodeType?e.setEnd(r,0):e.setEndBefore(r)}return e}function f(e){var t=x.getRng();return t=d(t,e),c(t)?!0:void 0}function v(e,t){function n(e,n){return m=X(n).parents().filter(function(e,t){return!!u.schema.getTextInlineElements()[t.nodeName]}),l=e.cloneNode(!1),m=s.map(m,function(e){return e=e.cloneNode(!1),l.hasChildNodes()?(e.appendChild(l.firstChild),l.appendChild(e)):l.appendChild(e),l.appendChild(e),e}),m.length?(p=C.create("br"),m[0].appendChild(p),C.replace(l,e),t.setStartBefore(p),t.setEndBefore(p),u.selection.setRng(t),p):null}function i(e){return e&&u.schema.getTextBlockElements()[e.tagName]}var o,a,l,c,d,f,h,p,m;if(t.collapsed&&(f=t.startContainer,h=t.startOffset,a=C.getParent(f,C.isBlock),i(a)))if(1==f.nodeType){if(f=f.childNodes[h],f&&"BR"!=f.tagName)return;if(d=e?a.nextSibling:a.previousSibling,C.isEmpty(a)&&i(d)&&C.isEmpty(d)&&n(a,f))return C.remove(d),!0}else if(3==f.nodeType){if(o=r.create(a,f),c=a.cloneNode(!0),f=r.resolve(c,o),e){if(h>=f.data.length)return;f.deleteData(h,1)}else{if(0>=h)return;f.deleteData(h-1,1)}if(C.isEmpty(c))return n(a,f)}}function y(e){var t,n,r;f(e)||(s.each(u.getBody().getElementsByTagName("*"),function(e){"SPAN"==e.tagName&&e.setAttribute("mce-data-marked",1),!e.hasAttribute("data-mce-style")&&e.hasAttribute("style")&&u.dom.setAttrib(e,"style",u.dom.getAttrib(e,"style"))}),t=new w(function(){}),t.observe(u.getDoc(),{childList:!0,attributes:!0,subtree:!0,attributeFilter:["style"]}),u.getDoc().execCommand(e?"ForwardDelete":"Delete",!1,null),n=u.selection.getRng(),r=n.startContainer.parentNode,s.each(t.takeRecords(),function(e){if(C.isChildOf(e.target,u.getBody())){if("style"==e.attributeName){var t=e.target.getAttribute("data-mce-style");t?e.target.setAttribute("style",t):e.target.removeAttribute("style")}s.each(e.addedNodes,function(e){if("SPAN"==e.nodeName&&!e.getAttribute("mce-data-marked")){var t,i;e==r&&(t=n.startOffset,i=e.firstChild),C.remove(e,!0),i&&(n.setStart(i,t),n.setEnd(i,t),u.selection.setRng(n))}})}}),t.disconnect(),s.each(u.dom.select("span[mce-data-marked]"),function(e){e.removeAttribute("mce-data-marked")}))}var b=u.getDoc(),C=u.dom,x=u.selection,w=window.MutationObserver,N,E;w||(N=!0,w=function(){function e(e){var t=e.relatedNode||e.target;n.push({target:t,addedNodes:[t]})}function t(e){var t=e.relatedNode||e.target;n.push({target:t,attributeName:e.attrName})}var n=[],r;this.observe=function(n){r=n,r.addEventListener("DOMSubtreeModified",e,!1),r.addEventListener("DOMNodeInsertedIntoDocument",e,!1),r.addEventListener("DOMNodeInserted",e,!1),r.addEventListener("DOMAttrModified",t,!1)},this.disconnect=function(){r.removeEventListener("DOMSubtreeModified",e,!1),r.removeEventListener("DOMNodeInsertedIntoDocument",e,!1),r.removeEventListener("DOMNodeInserted",e,!1),r.removeEventListener("DOMAttrModified",t,!1)},this.takeRecords=function(){return n}}),u.on("keydown",function(e){var t=e.keyCode==G,n=e.ctrlKey||e.metaKey;if(!h(e)&&(t||e.keyCode==K)){var r=u.selection.getRng(),i=r.startContainer,o=r.startOffset;if(t&&e.shiftKey)return;if(v(t,r))return void e.preventDefault();if(!n&&r.collapsed&&3==i.nodeType&&(t?o0))return;e.preventDefault(),n&&u.selection.getSel().modify("extend",t?"forward":"backward",e.metaKey?"lineboundary":"word"),y(t)}}),u.on("keypress",function(t){if(!h(t)&&!x.isCollapsed()&&t.charCode>31&&!e.metaKeyPressed(t)){var n,r,i,o,a,s;n=u.selection.getRng(),s=String.fromCharCode(t.charCode),t.preventDefault(),r=X(n.startContainer).parents().filter(function(e,t){return!!u.schema.getTextInlineElements()[t.nodeName]}),y(!0),r=r.filter(function(e,t){return!X.contains(u.getBody(),t)}),r.length?(i=C.createFragment(),r.each(function(e,t){t=t.cloneNode(!1),i.hasChildNodes()?(t.appendChild(i.firstChild),i.appendChild(t)):(a=t,i.appendChild(t)),i.appendChild(t)}),a.appendChild(u.getDoc().createTextNode(s)),o=C.getParent(n.startContainer,C.isBlock),C.isEmpty(o)?X(o).empty().append(i):n.insertNode(i),n.setStart(a.firstChild,1),n.setEnd(a.firstChild,1),u.selection.setRng(n)):u.selection.setContent(s)}}),u.addCommand("Delete",function(){y()}),u.addCommand("ForwardDelete",function(){y(!0)}),N||(u.on("dragstart",function(e){E=x.getRng(),p(e)}),u.on("drop",function(e){if(!h(e)){var n=m(e);n&&(e.preventDefault(),l.setEditorTimeout(u,function(){var r=t.getCaretRangeFromPoint(e.x,e.y,b);E&&(x.setRng(E),E=null),y(),x.setRng(r),g(n.html)}))}}),u.on("cut",function(e){h(e)||!e.clipboardData||u.selection.isCollapsed()||(e.preventDefault(),e.clipboardData.clearData(),e.clipboardData.setData("text/html",u.selection.getContent()),e.clipboardData.setData("text/plain",u.selection.getContent({format:"text"})),l.setEditorTimeout(u,function(){y(!0)}))}))}function y(){function e(e){var t=J.create("body"),n=e.cloneContents();return t.appendChild(n),Q.serializer.serialize(t,{format:"html"})}function n(n){if(!n.setStart){if(n.item)return!1;var r=n.duplicate();return r.moveToElementText(u.getBody()),t.compareRanges(n,r)}var i=e(n),o=J.createRng();o.selectNode(u.getBody());var a=e(o);return i===a}u.on("keydown",function(e){var t=e.keyCode,r,i;if(!h(e)&&(t==G||t==K)){if(r=u.selection.isCollapsed(),i=u.getBody(),r&&!J.isEmpty(i))return;if(!r&&!n(u.selection.getRng()))return;e.preventDefault(),u.setContent(""),i.firstChild&&J.isBlock(i.firstChild)?u.selection.setCursorLocation(i.firstChild,0):u.selection.setCursorLocation(i,0),u.nodeChanged()}})}function b(){u.shortcuts.add("meta+a",null,"SelectAll")}function C(){u.settings.content_editable||J.bind(u.getDoc(),"mousedown mouseup",function(e){var t;if(e.target==u.getDoc().documentElement)if(t=Q.getRng(),u.getBody().focus(),"mousedown"==e.type){if(c.isCaretContainer(t.startContainer))return;Q.placeCaretAt(e.clientX,e.clientY)}else Q.setRng(t)})}function x(){u.on("keydown",function(e){if(!h(e)&&e.keyCode===K){if(!u.getBody().getElementsByTagName("hr").length)return;if(Q.isCollapsed()&&0===Q.getRng(!0).startOffset){var t=Q.getNode(),n=t.previousSibling;if("HR"==t.nodeName)return J.remove(t),void e.preventDefault();n&&n.nodeName&&"hr"===n.nodeName.toLowerCase()&&(J.remove(n),e.preventDefault())}}})}function w(){window.Range.prototype.getClientRects||u.on("mousedown",function(e){if(!h(e)&&"HTML"===e.target.nodeName){var t=u.getBody();t.blur(),l.setEditorTimeout(u,function(){t.focus()})}})}function N(){u.on("click",function(e){var t=e.target;/^(IMG|HR)$/.test(t.nodeName)&&"false"!==J.getContentEditableParent(t)&&(e.preventDefault(),Q.getSel().setBaseAndExtent(t,0,t,1),u.nodeChanged()),"A"==t.nodeName&&J.hasClass(t,"mce-item-anchor")&&(e.preventDefault(),Q.select(t))})}function E(){function e(){var e=J.getAttribs(Q.getStart().cloneNode(!1));return function(){var t=Q.getStart();t!==u.getBody()&&(J.setAttrib(t,"style",null),Y(e,function(e){t.setAttributeNode(e.cloneNode(!0))}))}}function t(){return!Q.isCollapsed()&&J.getParent(Q.getStart(),J.isBlock)!=J.getParent(Q.getEnd(),J.isBlock)}u.on("keypress",function(n){var r;return h(n)||8!=n.keyCode&&46!=n.keyCode||!t()?void 0:(r=e(),u.getDoc().execCommand("delete",!1,null),r(),n.preventDefault(),!1)}),J.bind(u.getDoc(),"cut",function(n){var r;!h(n)&&t()&&(r=e(),l.setEditorTimeout(u,function(){r()}))})}function _(){document.body.setAttribute("role","application")}function S(){u.on("keydown",function(e){if(!h(e)&&e.keyCode===K&&Q.isCollapsed()&&0===Q.getRng(!0).startOffset){var t=Q.getNode().previousSibling;if(t&&t.nodeName&&"table"===t.nodeName.toLowerCase())return e.preventDefault(),!1}})}function k(){f()>7||(d("RespectVisibilityInDesign",!0),u.contentStyles.push(".mceHideBrInPre pre br {display: none}"),J.addClass(u.getBody(),"mceHideBrInPre"),ee.addNodeFilter("pre",function(e){for(var t=e.length,n,r,o,a;t--;)for(n=e[t].getAll("br"),r=n.length;r--;)o=n[r],a=o.prev,a&&3===a.type&&"\n"!=a.value.charAt(a.value-1)?a.value+="\n":o.parent.insert(new i("#text",3),o,!0).value="\n"}),te.addNodeFilter("pre",function(e){for(var t=e.length,n,r,i,o;t--;)for(n=e[t].getAll("br"),r=n.length;r--;)i=n[r],o=i.prev,o&&3==o.type&&(o.value=o.value.replace(/\r?\n$/,""))}))}function T(){J.bind(u.getBody(),"mouseup",function(){var e,t=Q.getNode();"IMG"==t.nodeName&&((e=J.getStyle(t,"width"))&&(J.setAttrib(t,"width",e.replace(/[^0-9%]+/g,"")),J.setStyle(t,"width","")),(e=J.getStyle(t,"height"))&&(J.setAttrib(t,"height",e.replace(/[^0-9%]+/g,"")),J.setStyle(t,"height","")))})}function R(){u.on("keydown",function(t){var n,r,i,o,a;if(!h(t)&&t.keyCode==e.BACKSPACE&&(n=Q.getRng(),r=n.startContainer,i=n.startOffset,o=J.getRoot(),a=r,n.collapsed&&0===i)){for(;a&&a.parentNode&&a.parentNode.firstChild==a&&a.parentNode!=o;)a=a.parentNode;"BLOCKQUOTE"===a.tagName&&(u.formatter.toggle("blockquote",null,a),n=J.createRng(),n.setStart(r,0),n.setEnd(r,0),Q.setRng(n))}})}function A(){function e(){u._refreshContentEditable(),d("StyleWithCSS",!1),d("enableInlineTableEditing",!1),Z.object_resizing||d("enableObjectResizing",!1)}Z.readonly||u.on("BeforeExecCommand MouseDown",e)}function B(){function e(){Y(J.select("a"),function(e){var t=e.parentNode,n=J.getRoot();if(t.lastChild===e){for(;t&&!J.isBlock(t);){if(t.parentNode.lastChild!==t||t===n)return;t=t.parentNode}J.add(t,"br",{"data-mce-bogus":1})}})}u.on("SetContent ExecCommand",function(t){("setcontent"==t.type||"mceInsertLink"===t.command)&&e()})}function D(){Z.forced_root_block&&u.on("init",function(){d("DefaultParagraphSeparator",Z.forced_root_block)})}function M(){u.on("keydown",function(e){var t;h(e)||e.keyCode!=K||(t=u.getDoc().selection.createRange(),t&&t.item&&(e.preventDefault(),u.undoManager.beforeChange(),J.remove(t.item(0)),u.undoManager.add()))})}function L(){var e;f()>=10&&(e="",Y("p div h1 h2 h3 h4 h5 h6".split(" "),function(t,n){e+=(n>0?",":"")+t+":empty"}),u.contentStyles.push(e+"{padding-right: 1px !important}"))}function P(){f()<9&&(ee.addNodeFilter("noscript",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.firstChild,r&&n.attr("data-mce-innertext",r.value)}),te.addNodeFilter("noscript",function(e){for(var t=e.length,n,r,a;t--;)n=e[t],r=e[t].firstChild,r?r.value=o.decode(r.value):(a=n.attributes.map["data-mce-innertext"],a&&(n.attr("data-mce-innertext",null), +r=new i("#text",3),r.value=a,r.raw=!0,n.append(r)))}))}function H(){function e(e,t){var n=i.createTextRange();try{n.moveToPoint(e,t)}catch(r){n=null}return n}function t(t){var r;t.button?(r=e(t.x,t.y),r&&(r.compareEndPoints("StartToStart",a)>0?r.setEndPoint("StartToStart",a):r.setEndPoint("EndToEnd",a),r.select())):n()}function n(){var e=r.selection.createRange();a&&!e.item&&0===e.compareEndPoints("StartToEnd",e)&&a.select(),J.unbind(r,"mouseup",n),J.unbind(r,"mousemove",t),a=o=0}var r=J.doc,i=r.body,o,a,s;r.documentElement.unselectable=!0,J.bind(r,"mousedown contextmenu",function(i){if("HTML"===i.target.nodeName){if(o&&n(),s=r.documentElement,s.scrollHeight>s.clientHeight)return;o=1,a=e(i.x,i.y),a&&(J.bind(r,"mouseup",n),J.bind(r,"mousemove",t),J.getRoot().focus(),a.select())}})}function O(){u.on("keyup focusin mouseup",function(t){65==t.keyCode&&e.metaKeyPressed(t)||Q.normalize()},!0)}function I(){u.contentStyles.push("img:-moz-broken {-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}")}function F(){u.inline||u.on("keydown",function(){document.activeElement==document.body&&u.getWin().focus()})}function z(){u.inline||(u.contentStyles.push("body {min-height: 150px}"),u.on("click",function(e){var t;if("HTML"==e.target.nodeName){if(a.ie>11)return void u.getBody().focus();t=u.selection.getRng(),u.getBody().focus(),u.selection.setRng(t),u.selection.normalize(),u.nodeChanged()}}))}function W(){a.mac&&u.on("keydown",function(t){!e.metaKeyPressed(t)||t.shiftKey||37!=t.keyCode&&39!=t.keyCode||(t.preventDefault(),u.selection.getSel().modify("move",37==t.keyCode?"backward":"forward","lineboundary"))})}function V(){d("AutoUrlDetect",!1)}function U(){u.on("click",function(e){var t=e.target;do if("A"===t.tagName)return void e.preventDefault();while(t=t.parentNode)}),u.contentStyles.push(".mce-content-body {-webkit-touch-callout: none}")}function $(){u.on("init",function(){u.dom.bind(u.getBody(),"submit",function(e){e.preventDefault()})})}function q(){ee.addNodeFilter("br",function(e){for(var t=e.length;t--;)"Apple-interchange-newline"==e[t].attr("class")&&e[t].remove()})}function j(){u.on("dragstart",function(e){p(e)}),u.on("drop",function(e){if(!h(e)){var n=m(e);if(n&&n.id!=u.id){e.preventDefault();var r=t.getCaretRangeFromPoint(e.x,e.y,u.getDoc());Q.setRng(r),g(n.html)}}})}var Y=s.each,X=u.$,K=e.BACKSPACE,G=e.DELETE,J=u.dom,Q=u.selection,Z=u.settings,ee=u.parser,te=u.serializer,ne=a.gecko,re=a.ie,ie=a.webkit,oe="data:text/mce-internal,",ae=re?"Text":"URL";R(),y(),O(),ie&&(v(),C(),N(),D(),$(),S(),q(),a.iOS?(F(),z(),U()):b()),re&&a.ie<11&&(x(),_(),k(),T(),M(),L(),P(),H()),a.ie>=11&&(z(),S()),a.ie&&(b(),V(),j()),ne&&(x(),w(),E(),A(),B(),I(),W(),S())}}),r(Me,[oe,w,m],function(e,t,n){function r(e,t){return"selectionchange"==t?e.getDoc():!e.inline&&/^mouse|click|contextmenu|drop|dragover|dragend/.test(t)?e.getDoc().documentElement:e.settings.event_root?(e.eventRoot||(e.eventRoot=o.select(e.settings.event_root)[0]),e.eventRoot):e.getBody()}function i(e,t){function n(e){return!e.hidden&&!e.readonly}var i=r(e,t),s;if(e.delegates||(e.delegates={}),!e.delegates[t])if(e.settings.event_root){if(a||(a={},e.editorManager.on("removeEditor",function(){var t;if(!e.editorManager.activeEditor&&a){for(t in a)e.dom.unbind(r(e,t));a=null}})),a[t])return;s=function(r){for(var i=r.target,a=e.editorManager.editors,s=a.length;s--;){var l=a[s].getBody();(l===i||o.isChildOf(i,l))&&n(a[s])&&a[s].fire(t,r)}},a[t]=s,o.bind(i,t,s)}else s=function(r){n(e)&&e.fire(t,r)},o.bind(i,t,s),e.delegates[t]=s}var o=t.DOM,a,s={bindPendingEventDelegates:function(){var e=this;n.each(e._pendingNativeEvents,function(t){i(e,t)})},toggleNativeEvent:function(e,t){var n=this;"focus"!=e&&"blur"!=e&&(t?n.initialized?i(n,e):n._pendingNativeEvents?n._pendingNativeEvents.push(e):n._pendingNativeEvents=[e]:n.initialized&&(n.dom.unbind(r(n,e),e,n.delegates[e]),delete n.delegates[e]))},unbindAllNativeEvents:function(){var e=this,t;if(e.delegates){for(t in e.delegates)e.dom.unbind(r(e,t),t,e.delegates[t]);delete e.delegates}e.inline||(e.getBody().onload=null,e.dom.unbind(e.getWin()),e.dom.unbind(e.getDoc())),e.dom.unbind(e.getBody()),e.dom.unbind(e.getContainer())}};return s=n.extend({},e,s)}),r(Le,[],function(){function e(e,t,n){try{e.getDoc().execCommand(t,!1,n)}catch(r){}}function t(t,n){var r=t.readonly?"readonly":"design";n!=r&&("readonly"==n?(t.selection.controlSelection.hideResizeRect(),t.readonly=!0,t.getBody().contentEditable=!1):(t.readonly=!1,t.getBody().contentEditable=!0,e(t,"StyleWithCSS",!1),e(t,"enableInlineTableEditing",!1),e(t,"enableObjectResizing",!1),t.focus(),t.nodeChanged()),t.fire("SwitchMode",{mode:n}))}return{setMode:t}}),r(Pe,[m,h],function(e,t){var n=e.each,r=e.explode,i={f9:120,f10:121,f11:122},o=e.makeMap("alt,ctrl,shift,meta,access");return function(a){function s(e,s,l,c){var u,d,f;f={func:l,scope:c||a,desc:a.translate(s)},n(r(e,"+"),function(e){e in o?f[e]=!0:/^[0-9]{2,}$/.test(e)?f.keyCode=parseInt(e,10):(f.charCode=e.charCodeAt(0),f.keyCode=i[e]||e.toUpperCase().charCodeAt(0))}),u=[f.keyCode];for(d in o)f[d]?u.push(d):f[d]=!1;return f.id=u.join(","),f.access&&(f.alt=!0,t.mac?f.ctrl=!0:f.shift=!0),f.meta&&(t.mac?f.meta=!0:(f.ctrl=!0,f.meta=!1)),f}var l=this,c={};a.on("keyup keypress keydown",function(e){(e.altKey||e.ctrlKey||e.metaKey)&&!e.isDefaultPrevented()&&n(c,function(t){return t.ctrl==e.ctrlKey&&t.meta==e.metaKey&&t.alt==e.altKey&&t.shift==e.shiftKey&&(e.keyCode==t.keyCode||e.charCode&&e.charCode==t.charCode)?(e.preventDefault(),"keydown"==e.type&&t.func.call(t.scope),!0):void 0})}),l.add=function(t,i,o,l){var u;return u=o,"string"==typeof o?o=function(){a.execCommand(u,!1,null)}:e.isArray(u)&&(o=function(){a.execCommand(u[0],u[1],u[2])}),n(r(t.toLowerCase()),function(e){var t=s(e,i,o,l);c[t.id]=t}),!0},l.remove=function(e){var t=s(e);return c[t.id]?(delete c[t.id],!0):!1}}}),r(He,[c,m,z],function(e,t,n){return function(r){function i(e){var t,n;return n={"image/jpeg":"jpg","image/jpg":"jpg","image/gif":"gif","image/png":"png"},t=n[e.blob().type.toLowerCase()]||"dat",e.id()+"."+t}function o(e,t){return e?e.replace(/\/$/,"")+"/"+t.replace(/^\//,""):t}function a(e){return{id:e.id,blob:e.blob,base64:e.base64,filename:n.constant(i(e))}}function s(e,t,n,a){var s,l,c;s=new XMLHttpRequest,s.open("POST",r.url),s.withCredentials=r.credentials,c=a(),s.upload.onprogress=function(e){var t=Math.round(e.loaded/e.total*100);c.progressBar.value(t)},s.onload=function(){var e;return c.close(),200!=s.status?void n("HTTP Error: "+s.status):(e=JSON.parse(s.responseText),e&&"string"==typeof e.location?void t(o(r.basePath,e.location)):void n("Invalid JSON: "+s.responseText))},l=new FormData,l.append("file",e.blob(),i(e)),s.send(l)}function l(){return new e(function(e){e([])})}function c(e){return e.then(function(e){return e})["catch"](function(e){return e})}function u(e,t,n){var r=e(n),i=c(r);return delete p[t],p[t]=i,i}function d(e,n){return t.map(e,function(e){var t=e.id();return p[t]?p[t]:u(n,t,e)})}function f(t,n){function i(t){return new e(function(e){var i=r.handler;i(a(t),function(n){e({url:n,blobInfo:t,status:!0})},function(n){e({url:"",blobInfo:t,status:!1,error:n})},n)})}var o=d(t,i);return e.all(o)}function h(e,t){return r.url||r.handler!==s?f(e,t):l()}var p={};return r=t.extend({credentials:!1,handler:s},r),{upload:h}}}),r(Oe,[c],function(e){function t(t){return new e(function(e){var n=new XMLHttpRequest;n.open("GET",t,!0),n.responseType="blob",n.onload=function(){200==this.status&&e(this.response)},n.send()})}function n(e){var t,n;return e=decodeURIComponent(e).split(","),n=/data:([^;]+)/.exec(e[0]),n&&(t=n[1]),{type:t,data:e[1]}}function r(t){return new e(function(e){var r,i,o;t=n(t);try{r=atob(t.data)}catch(a){return void e(new Blob([]))}for(i=new Uint8Array(r.length),o=0;o0}function s(e){return 0>e}function l(e,n,r,i,o){var l=new t(e,i);if(s(n)){if(C(e)&&(e=l.prev(!0),r(e)))return e;for(;e=l.prev(o);)if(r(e))return e}if(a(n)){if(C(e)&&(e=l.next(!0),r(e)))return e;for(;e=l.next(o);)if(r(e))return e}return null}function c(e,t){for(e=e.parentNode;e&&e!=t;e=e.parentNode)if(b(e))return e;return t}function u(e,t){for(;e&&e!=t;){if(x(e))return e;e=e.parentNode}return null}function d(e,t,n){return u(e.container(),n)==u(t.container(),n)}function f(e,t,n){return c(e.container(),n)==c(t.container(),n)}function h(e,t){var n,r;return t?(n=t.container(),r=t.offset(),E(n)?n.childNodes[r+e]:null):null}function p(e,t){var n=t.ownerDocument.createRange();return e?(n.setStartBefore(t),n.setEndBefore(t)):(n.setStartAfter(t),n.setEndAfter(t)),n}function m(e,t,n){return u(t,e)==u(n,e)}function g(e,t,n){var r,i;for(i=e?"previousSibling":"nextSibling";n&&n!=t;){if(r=n[i],w(r)&&(r=r[i]),C(r)){if(m(t,r,n))return r;break}if(_(r))break;n=n.parentNode}return null}function v(e,t,r){var o,a,s,l,c=N(g,!0,t),u=N(g,!1,t);if(a=r.startContainer,s=r.startOffset,i.isCaretContainerBlock(a)){if(E(a)||(a=a.parentNode),l=a.getAttribute("data-mce-caret"),"before"==l&&(o=a.nextSibling,C(o)))return S(o);if("after"==l&&(o=a.previousSibling,C(o)))return k(o)}if(!r.collapsed)return r;if(n.isText(a)){if(w(a)){if(1===e){if(o=u(a))return S(o);if(o=c(a))return k(o)}if(-1===e){if(o=c(a))return k(o);if(o=u(a))return S(o)}return r}if(i.endsWithCaretContainer(a)&&s>=a.data.length-1)return 1===e&&(o=u(a))?S(o):r;if(i.startsWithCaretContainer(a)&&1>=s)return-1===e&&(o=c(a))?k(o):r;if(s===a.data.length)return o=u(a),o?S(o):r;if(0===s)return o=c(a),o?k(o):r}return r}function y(e,t){return C(h(e,t))}var b=n.isContentEditableTrue,C=n.isContentEditableFalse,x=n.matchStyleValues("display","block table table-cell table-caption"),w=i.isCaretContainer,N=e.curry,E=n.isElement,_=o.isCaretCandidate,S=N(p,!0),k=N(p,!1);return{isForwards:a,isBackwards:s,findNode:l,getEditingHost:c,getParentBlock:u,isInSameBlock:d,isInSameEditingHost:f,isBeforeContentEditableFalse:N(y,0),isAfterContentEditableFalse:N(y,-1),normalizeRange:v}}),r(Ve,[_,W,$,We,p,z],function(e,t,n,r,i,o){function a(e,t){for(var n=[];e&&e!=t;)n.push(e),e=e.parentNode;return n}function s(e,t){return e.hasChildNodes()&&t0)return n(y,--b);if(h(e)&&b0&&(x=s(y,b-1),m(x)))return!g(x)&&(w=r.findNode(x,e,v,x))?d(w)?n(w,w.data.length):n.after(w):d(x)?n(x,x.data.length):n.before(x);if(h(e)&&b0&&(n&&(l*=-1),r.left+=l,r.right+=l),r}function l(){var n,r,o,a,s;for(n=i("*[contentEditable=false]",t),a=0;a
    ').css(l).appendTo(t),o&&m.addClass("mce-visual-caret-before"),d(),c=a.ownerDocument.createRange(),f=g.firstChild,c.setStart(f,0),c.setEnd(f,1),c):(g=e.insertInline(a,o),c=a.ownerDocument.createRange(),s(g.nextSibling)?(c.setStart(g,0),c.setEnd(g,0)):(c.setStart(g,1),c.setEnd(g,1)),c)}function u(){l(),g&&(e.remove(g),g=null),m&&(m.remove(),m=null),clearInterval(p)}function d(){p=a.setInterval(function(){i("div.mce-visual-caret",t).toggleClass("mce-visual-caret-hidden")},500)}function f(){a.clearInterval(p)}function h(){return".mce-visual-caret {position: absolute;background-color: black;background-color: currentcolor;}.mce-visual-caret-hidden {display: none;}*[data-mce-caret] {position: absolute;left: -1000px;right: auto;top: 0;margin: 0;padding: 0;}"}var p,m,g;return{show:c,hide:u,getCss:h,destroy:f}}}),r($e,[p,_,V],function(e,t,n){function r(i){function o(t){return e.map(t,function(e){return e=n.clone(e),e.node=i,e})}if(e.isArray(i))return e.reduce(i,function(e,t){return e.concat(r(t))},[]);if(t.isElement(i))return o(i.getClientRects());if(t.isText(i)){var a=i.ownerDocument.createRange();return a.setStart(i,0),a.setEnd(i,i.data.length),o(a.getClientRects())}}return{getClientRects:r}}),r(qe,[z,p,$e,W,We,Ve,$,V],function(e,t,n,r,i,o,a,s){function l(e,t,n,o){for(;o=i.findNode(o,e,r.isEditableCaretCandidate,t);)if(n(o))return}function c(e,r,i,o,a,s){function c(o){var s,l,c;for(c=n.getClientRects(o),-1==e&&(c=c.reverse()),s=0;s0&&r(l,t.last(f))&&u++,l.line=u,a(l))return!0;f.push(l)}}var u=0,d,f=[],h;return(h=t.last(s.getClientRects()))?(d=s.getNode(),c(d),l(e,o,c,d),f):f}function u(e,t){return t.line>e}function d(e,t){return t.line===e}function f(e,n,r,i){function l(n){return 1==e?t.last(n.getClientRects()):t.last(n.getClientRects())}var c=new o(n),u,d,f,h,p=[],m=0,g,v;1==e?(u=c.next,d=s.isBelow,f=s.isAbove,h=a.after(i)):(u=c.prev,d=s.isAbove,f=s.isBelow,h=a.before(i)),v=l(h);do if(h.isVisible()&&(g=l(h),!f(g,v))){if(p.length>0&&d(g,t.last(p))&&m++,g=s.clone(g),g.position=h,g.line=m,r(g))return p;p.push(g)}while(h=u(h));return p}var h=e.curry,p=h(c,-1,s.isAbove,s.isBelow),m=h(c,1,s.isBelow,s.isAbove);return{upUntil:p,downUntil:m,positionsUntil:f,isAboveLine:h(u),isLine:h(d)}}),r(je,[z,p,_,$e,V,We,W],function(e,t,n,r,i,o,a){function s(e,t){return Math.abs(e.left-t)}function l(e,t){return Math.abs(e.right-t)}function c(e,n){function r(e,t){return e>=t.left&&e<=t.right}return t.reduce(e,function(e,t){var i,o;return i=Math.min(s(e,n),l(e,n)),o=Math.min(s(t,n),l(t,n)),r(n,t)?t:r(n,e)?e:o==i&&m(t.node)?t:i>o?t:e})}function u(e,t,n,r){for(;r=g(r,e,a.isEditableCaretCandidate,t);)if(n(r))return}function d(e,n){function o(e,i){var o;return o=t.filter(r.getClientRects(i),function(t){return!e(t,n)}),a=a.concat(o),0===o.length}var a=[];return a.push(n),u(-1,e,v(o,i.isAbove),n.node),u(1,e,v(o,i.isBelow),n.node),a}function f(e){return t.filter(t.toArray(e.getElementsByTagName("*")),m)}function h(e,t){return{node:e.node,before:s(e,t)=e.top&&i<=e.bottom}),a=c(o,n),a&&(a=c(d(e,a),n),a&&m(a.node))?h(a,n):null}var m=n.isContentEditableFalse,g=o.findNode,v=e.curry;return{findClosestClientRect:c,findLineNodeRects:d,closestCaret:p}}),r(Ye,[_],function(e){function t(e){function t(e){return n(e)}function r(t){c(e.getBody()).css("cursor",t)}function i(t){return t==h.element||e.dom.isChildOf(t,h.element)?!1:n(t)?!1:!0}function o(t){var n,i,o,a,s=0,l=0,u,d,p,m;0===t.button&&(n=t.screenX-h.screenX,i=t.screenY-h.screenY,u=Math.max(Math.abs(n),Math.abs(i)),!h.dragging&&u>10&&(h.dragging=!0,r("default"),h.clone=h.element.cloneNode(!0),o=f.getPos(h.element),h.relX=h.clientX-o.x,h.relY=h.clientY-o.y,h.width=h.element.offsetWidth,h.height=h.element.offsetHeight,c(h.clone).css({width:h.width,height:h.height}).removeAttr("data-mce-selected"),h.ghost=c("
    ").css({position:"absolute",opacity:.5,overflow:"hidden",width:h.width,height:h.height}).attr({"data-mce-bogus":"all",unselectable:"on",contenteditable:"false"}).addClass("mce-drag-container mce-reset").append(h.clone).appendTo(e.getBody())[0],a=e.dom.getViewPort(e.getWin()),h.maxX=a.w,h.maxY=a.h),h.dragging&&(e.selection.placeCaretAt(t.clientX,t.clientY),d=h.clientX+n-h.relX,p=h.clientY+i+5,d+h.width>h.maxX&&(s=d+h.width-h.maxX),p+h.height>h.maxY&&(l=p+h.height-h.maxY),m="BODY"!=e.getBody().nodeName?e.getBody().getBoundingClientRect():{left:0,top:0},c(h.ghost).css({left:d-m.left,top:p-m.top,width:h.width-s,height:h.height-l})))}function a(){h.dragging&&(e.selection.setRng(e.selection.getSel().getRangeAt(0)),i(e.selection.getNode())&&e.undoManager.transact(function(){e.insertContent(f.getOuterHTML(h.element)),c(h.element).remove()})),l()}function s(n){if(l(),t(n.target)){if(e.fire("dragstart",{target:n.target}).isDefaultPrevented())return;e.on("mousemove",o),e.on("mouseup",a),u!=d&&(f.bind(u,"mousemove",o),f.bind(u,"mouseup",a)),h={screenX:n.screenX,screenY:n.screenY,clientX:n.clientX,clientY:n.clientY,element:n.target}}}function l(){c(h.ghost).remove(),r(null),e.off("mousemove",o),e.off("mouseup",l),u!=d&&(f.unbind(u,"mousemove",o),f.unbind(u,"mouseup",l)),h={}}var c=e.$,u=document,d=e.getDoc(),f=e.dom,h={};e.on("mousedown",s)}var n=e.isContentEditableFalse;return{init:t}}),r(Xe,[h,Ve,$,k,We,Ue,qe,je,_,T,I,z,p,u,Ye],function(e,t,n,r,i,o,a,s,l,c,u,d,f,h,p){function m(e,t){for(;t=e(t);)if(t.isVisible())return t;return t}function g(c){function d(e){return c.dom.isBlock(e)}function g(e){c.selection.setRng(e)}function E(){return c.selection.getRng()}function _(e,t){c.selection.scrollIntoView(e,t)}function S(e,t,n){var r;return r=c.fire("ShowCaret",{target:t,direction:e,before:n}),r.isDefaultPrevented()?null:(_(t,-1===e),Q.show(n,t))}function k(e){var t;return t=c.fire("ObjectSelected",{target:e}),t.isDefaultPrevented()?null:(Q.hide(),T(e))}function T(e){var t=e.ownerDocument.createRange();return t.selectNode(e),t}function R(e,t){var n=i.isInSameBlock(e,t);return!n&&l.isBr(e.getNode())?!0:n}function A(e,t){return t=i.normalizeRange(e,X,t),-1==e?n.fromRangeStart(t):n.fromRangeEnd(t)}function B(e){return r.isCaretContainerBlock(e.startContainer)}function D(e,t,n,r){var i,o,a,s;return!r.collapsed&&(i=N(r),b(i))?S(e,i,-1==e):(s=B(r),o=A(e,r),n(o)?k(o.getNode(-1==e)):(o=t(o))?n(o)?S(e,o.getNode(-1==e),1==e):(a=t(o),n(a)&&R(o,a)?S(e,a.getNode(-1==e),1==e):s?F(o.toRange()):null):s?r:null)}function M(e,t,n){var r,i,o,l,c,u,d,h,p;if(p=N(n),r=A(e,n),i=t(X,a.isAboveLine(1),r),o=f.filter(i,a.isLine(1)),c=f.last(r.getClientRects()),w(r)&&(p=r.getNode()),x(r)&&(p=r.getNode(!0)),!c)return null;if(u=c.left,l=s.findClosestClientRect(o,u),l&&b(l.node))return d=Math.abs(u-l.left),h=Math.abs(u-l.right),S(e,l.node,h>d);if(p){var m=a.positionsUntil(e,X,a.isAboveLine(1),p);if(l=s.findClosestClientRect(f.filter(m,a.isLine(1)),u))return F(l.position.toRange());if(l=f.last(f.filter(m,a.isLine(0))))return F(l.position.toRange())}}function L(t,r){function i(){var t=c.dom.create(c.settings.forced_root_block);return(!e.ie||e.ie>=11)&&(t.innerHTML='
    '),t}var o,a,s;if(r.collapsed&&c.settings.forced_root_block){if(o=c.dom.getParent(r.startContainer,"PRE"),!o)return;a=1==t?G(n.fromRangeStart(r)):J(n.fromRangeStart(r)),a||(s=i(),1==t?c.$(o).after(s):c.$(o).before(s),c.selection.select(s,!0),c.selection.collapse())}}function P(e,t,n,r){var i;return(i=D(e,t,n,r))?i:(i=L(e,r),i?i:null)}function H(e,t,n){var r;return(r=M(e,t,n))?r:(r=L(e,n),r?r:null)}function O(){return te("*[data-mce-caret]")[0]}function I(e){e=te(e),e.attr("data-mce-caret")&&(Q.hide(),e.removeAttr("data-mce-caret"),e.removeAttr("data-mce-bogus"),e.removeAttr("style"),g(E()),_(e[0]))}function F(e){var t;return e&&e.collapsed?(e=i.normalizeRange(1,X,e),t=n.fromRangeStart(e),b(t.getNode())?S(1,t.getNode(),!t.isAtEnd()):b(t.getNode(!0))?S(1,t.getNode(!0),!1):(Q.hide(),e)):e}function z(e){var t,i,o,a;return b(e)?(b(e.previousSibling)&&(o=e.previousSibling),i=J(n.before(e)),i||(t=G(n.after(e))),t&&C(t.getNode())&&(a=t.getNode()),r.remove(e.previousSibling),r.remove(e.nextSibling),c.dom.remove(e),j(),c.dom.isEmpty(c.getBody())?(c.setContent(""),void c.focus()):o?n.after(o).toRange():a?n.before(a).toRange():i?i.toRange():t?t.toRange():null):null}function W(e,t,n){var r,i;return!n.collapsed&&(r=N(n),b(r))?F(z(r)):(i=A(e,n),t(i)?F(z(i.getNode(-1==e))):void 0)}function V(){function e(e){var t=e(E());return t?(g(t),!0):!1}function t(e){for(var t=c.getBody();e&&e!=t;){if(y(e)||b(e))return e;e=e.parentNode}return null}function r(){var e,r=t(c.selection.getNode());y(r)&&d(r)&&c.dom.isEmpty(r)&&(e=c.dom.create("br",{"data-mce-bogus":"1"}),c.$(r).empty().append(e),c.selection.setRng(n.before(e).toRange()))}function i(e){var t=O();if(t)return"compositionstart"==e.type?(e.preventDefault(),e.stopPropagation(),void I(t)):void(" "!=t.innerHTML&&I(t))}function o(e){var t;switch(e.keyCode){case u.DELETE:t=r();break;case u.BACKSPACE:t=r()}t&&e.preventDefault()}var l=v(P,1,G,w),f=v(P,-1,J,x),m=v(W,1,w),C=v(W,-1,x),N=v(H,-1,a.upUntil),_=v(H,1,a.downUntil);c.on("mouseup",function(){var e=E();e.collapsed&&g(F(e))}),c.on("mousedown",function(e){var n;if(n=t(e.target))b(n)?(e.preventDefault(),q(k(n),!1)):c.selection.placeCaretAt(e.clientX,e.clientY);else{j(),Q.hide();var r=s.closestCaret(X,e.clientX,e.clientY);r&&(e.preventDefault(),c.getBody().focus(),g(S(1,r.node,r.before)))}}),c.on("keydown",function(t){var n;if(!u.modifierPressed(t)){switch(t.keyCode){case u.RIGHT:n=e(l);break;case u.DOWN:n=e(_);break;case u.LEFT:n=e(f);break;case u.UP:n=e(N);break;case u.DELETE:n=e(m);break;case u.BACKSPACE:n=e(C);break;default:n=b(c.selection.getNode())}n&&t.preventDefault()}}),c.on("keyup compositionstart",function(e){i(e),o(e)},!0),c.on("cut",function(){var e=c.selection.getNode();b(e)&&h.setEditorTimeout(c,function(){g(F(z(e)))})}),c.on("getSelectionRange",function(e){var t=e.range;if(ee){if(!ee.parentNode)return void(ee=null);t=t.cloneRange(),t.selectNode(ee),e.range=t}}),c.on("setSelectionRange",function(e){var t;t=q(e.range),t&&(e.range=t)}),c.on("focus",function(){h.setEditorTimeout(c,function(){c.selection.setRng(F(c.selection.getRng()))})}),p.init(c)}function U(){var e=c.contentStyles,t=".mce-content-body";e.push(Q.getCss()),e.push(t+" .mce-offscreen-selection {position: absolute;left: -9999999999px;width: 100pxheight: 100px}"+t+" *[contentEditable=false] {cursor: default;}"+t+" *[contentEditable=true] {cursor: text;}")}function $(e){return r.isCaretContainer(e.startContainer)||r.isCaretContainer(e.endContainer)}function q(e,t){var n,r=c.$,i=c.dom,o,a,s,l,u,d,f;if(!e)return j(),null;if(e.collapsed){if(j(),!$(e)){if(f=A(1,e),b(f.getNode()))return S(1,f.getNode(),!f.isAtEnd());if(b(f.getNode(!0)))return S(1,f.getNode(!0),!1)}return null}return s=e.startContainer,l=e.startOffset,u=e.endOffset,3==s.nodeType&&0==l&&b(s.parentNode)&&(s=s.parentNode,l=i.nodeIndex(s),s=s.parentNode),1!=s.nodeType?(j(),null):(u==l+1&&(n=s.childNodes[l]),b(n)?t!==!1&&(d=c.fire("ObjectSelected",{target:n}),d.isDefaultPrevented())?(j(),null):(o=r("#"+Z),0===o.length&&(o=r('
    ').attr("id",Z),o.appendTo(c.getBody())),o.empty().append("\xa0").append(n.cloneNode(!0)).append("\xa0").css({top:i.getPos(n,c.getBody()).y}),e=c.dom.createRng(),e.setStart(o[0].firstChild,1),e.setEnd(o[0].lastChild,0),c.getBody().focus(),o[0].focus(),a=c.selection.getSel(),a.removeAllRanges(),a.addRange(e),c.$("*[data-mce-selected]").removeAttr("data-mce-selected"),n.setAttribute("data-mce-selected",1),ee=n,e):(j(),null))}function j(){ee&&(ee.removeAttribute("data-mce-selected"),c.$("#"+Z).remove(),ee=null)}function Y(){Q.destroy(),ee=null}var X=c.getBody(),K=new t(X),G=v(m,K.next),J=v(m,K.prev),Q=new o(c.getBody(),d),Z="sel-"+c.dom.uniqueId(),ee,te=c.$;return e.ceFalse&&(V(),U()),{showBlockCaretContainer:I,destroy:Y}}var v=d.curry,y=l.isContentEditableTrue,b=l.isContentEditableFalse,C=l.isElement,x=i.isAfterContentEditableFalse,w=i.isBeforeContentEditableFalse,N=c.getSelectedNode;return g}),r(Ke,[w,g,E,R,A,H,P,Y,G,J,Q,Z,ee,te,N,d,_e,Ae,B,M,De,h,m,u,Me,Le,Pe,ze,Xe],function(e,n,r,i,o,a,s,l,c,u,d,f,h,p,m,g,v,y,b,C,x,w,N,E,_,S,k,T,R){function A(e,t,i){var o=this,a,s;a=o.documentBaseUrl=i.documentBaseURL,s=i.baseURI,o.settings=t=L({id:e,theme:"modern",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:a,add_form_submit_trigger:!0,submit_patch:!0,add_unload_trigger:!0,convert_urls:!0,relative_urls:!0,remove_script_host:!0,object_resizing:!0,doctype:"",visual:!0,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",forced_root_block:"p",hidden_input:!0,padd_empty_editor:!0,render_ui:!0,indentation:"30px",inline_styles:!0,convert_fonts_to_spans:!0,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",validate:!0,entity_encoding:"named",url_converter:o.convertURL,url_converter_scope:o,ie7_compat:!0},t),r.language=t.language||"en",r.languageLoad=t.language_load,r.baseURL=i.baseURL,o.id=t.id=e,o.setDirty(!1),o.plugins={},o.documentBaseURI=new p(t.document_base_url||a,{base_uri:s}),o.baseURI=s,o.contentCSS=[],o.contentStyles=[],o.shortcuts=new k(o),o.loadedCSS={},o.editorCommands=new h(o),t.target&&(o.targetElm=t.target),o.suffix=i.suffix,o.editorManager=i,o.inline=t.inline,t.cache_suffix&&(w.cacheSuffix=t.cache_suffix.replace(/^[\?\&]+/,"")),t.override_viewport===!1&&(w.overrideViewPort=!1),i.fire("SetupEditor",o),o.execCallback("setup",o),o.$=n.overrideDefaults(function(){return{context:o.inline?o.getBody():o.getDoc(),element:o.getBody()}})}var B=e.DOM,D=r.ThemeManager,M=r.PluginManager,L=N.extend,P=N.each,H=N.explode,O=N.inArray,I=N.trim,F=N.resolve,z=g.Event,W=w.gecko,V=w.ie;return A.prototype={render:function(){function e(){B.unbind(window,"ready",e),n.render()}function t(){var e=m.ScriptLoader;if(r.language&&"en"!=r.language&&!r.language_url&&(r.language_url=n.editorManager.baseURL+"/langs/"+r.language+".js"),r.language_url&&e.add(r.language_url),r.theme&&"function"!=typeof r.theme&&"-"!=r.theme.charAt(0)&&!D.urls[r.theme]){var t=r.theme_url;t=t?n.documentBaseURI.toAbsolute(t):"themes/"+r.theme+"/theme"+o+".js",D.load(r.theme,t)}N.isArray(r.plugins)&&(r.plugins=r.plugins.join(" ")),P(r.external_plugins,function(e,t){M.load(t,e),r.plugins+=" "+t}),P(r.plugins.split(/[ ,]/),function(e){if(e=I(e),e&&!M.urls[e])if("-"==e.charAt(0)){e=e.substr(1,e.length);var t=M.dependencies(e);P(t,function(e){var t={prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"};e=M.createUrl(t,e),M.load(e.resource,e)})}else M.load(e,{prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"})}),e.loadQueue(function(){n.removed||n.init()})}var n=this,r=n.settings,i=n.id,o=n.suffix;if(!z.domLoaded)return void B.bind(window,"ready",e);if(n.getElement()&&w.contentEditable){r.inline?n.inline=!0:(n.orgVisibility=n.getElement().style.visibility,n.getElement().style.visibility="hidden");var a=n.getElement().form||B.getParent(i,"form");a&&(n.formElement=a,r.hidden_input&&!/TEXTAREA|INPUT/i.test(n.getElement().nodeName)&&(B.insertAfter(B.create("input",{type:"hidden",name:i}),i),n.hasHiddenInput=!0),n.formEventDelegate=function(e){n.fire(e.type,e)},B.bind(a,"submit reset",n.formEventDelegate),n.on("reset",function(){n.setContent(n.startContent,{format:"raw"})}),!r.submit_patch||a.submit.nodeType||a.submit.length||a._mceOldSubmit||(a._mceOldSubmit=a.submit,a.submit=function(){return n.editorManager.triggerSave(), +n.setDirty(!1),a._mceOldSubmit(a)})),n.windowManager=new v(n),n.notificationManager=new y(n),"xml"==r.encoding&&n.on("GetContent",function(e){e.save&&(e.content=B.encode(e.content))}),r.add_form_submit_trigger&&n.on("submit",function(){n.initialized&&n.save()}),r.add_unload_trigger&&(n._beforeUnload=function(){!n.initialized||n.destroyed||n.isHidden()||n.save({format:"raw",no_events:!0,set_dirty:!1})},n.editorManager.on("BeforeUnload",n._beforeUnload)),t()}},init:function(){function e(n){var r=M.get(n),i,o;if(i=M.urls[n]||t.documentBaseUrl.replace(/\/$/,""),n=I(n),r&&-1===O(m,n)){if(P(M.dependencies(n),function(t){e(t)}),t.plugins[n])return;o=new r(t,i,t.$),t.plugins[n]=o,o.init&&(o.init(t,i),m.push(n))}}var t=this,n=t.settings,r=t.getElement(),i,o,a,s,l,c,u,d,f,h,p,m=[];if(this.editorManager.i18n.setCode(n.language),t.rtl=n.rtl_ui||this.editorManager.i18n.rtl,t.editorManager.add(t),n.aria_label=n.aria_label||B.getAttrib(r,"aria-label",t.getLang("aria.rich_text_area")),n.theme&&("function"!=typeof n.theme?(n.theme=n.theme.replace(/-/,""),c=D.get(n.theme),t.theme=new c(t,D.urls[n.theme]),t.theme.init&&t.theme.init(t,D.urls[n.theme]||t.documentBaseUrl.replace(/\/$/,""),t.$)):t.theme=n.theme),P(n.plugins.replace(/\-/g,"").split(/[ ,]/),e),n.render_ui&&t.theme&&(t.orgDisplay=r.style.display,"function"!=typeof n.theme?(i=n.width||r.style.width||r.offsetWidth,o=n.height||r.style.height||r.offsetHeight,a=n.min_height||100,h=/^[0-9\.]+(|px)$/i,h.test(""+i)&&(i=Math.max(parseInt(i,10),100)),h.test(""+o)&&(o=Math.max(parseInt(o,10),a)),l=t.theme.renderUI({targetNode:r,width:i,height:o,deltaWidth:n.delta_width,deltaHeight:n.delta_height}),n.content_editable||(o=(l.iframeHeight||o)+("number"==typeof o?l.deltaHeight||0:""),a>o&&(o=a))):(l=n.theme(t,r),l.editorContainer.nodeType&&(l.editorContainer=l.editorContainer.id=l.editorContainer.id||t.id+"_parent"),l.iframeContainer.nodeType&&(l.iframeContainer=l.iframeContainer.id=l.iframeContainer.id||t.id+"_iframecontainer"),o=l.iframeHeight||r.offsetHeight),t.editorContainer=l.editorContainer),n.content_css&&P(H(n.content_css),function(e){t.contentCSS.push(t.documentBaseURI.toAbsolute(e))}),n.content_style&&t.contentStyles.push(n.content_style),n.content_editable)return r=s=l=null,t.initContentBody();for(t.iframeHTML=n.doctype+"",n.document_base_url!=t.documentBaseUrl&&(t.iframeHTML+=''),!w.caretAfter&&n.ie7_compat&&(t.iframeHTML+=''),t.iframeHTML+='',p=0;p',t.loadedCSS[g]=!0}d=n.body_id||"tinymce",-1!=d.indexOf("=")&&(d=t.getParam("body_id","","hash"),d=d[t.id]||d),f=n.body_class||"",-1!=f.indexOf("=")&&(f=t.getParam("body_class","","hash"),f=f[t.id]||""),n.content_security_policy&&(t.iframeHTML+=''),t.iframeHTML+='
    ';var v='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinymce.get("'+t.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody(true);})()';document.domain!=location.hostname&&w.ie&&w.ie<12&&(u=v);var y=B.create("iframe",{id:t.id+"_ifr",frameBorder:"0",allowTransparency:"true",title:t.editorManager.translate("Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help"),style:{width:"100%",height:o,display:"block"}});if(y.onload=function(){y.onload=null,t.fire("load")},B.setAttrib(y,"src",u||'javascript:""'),t.contentAreaContainer=l.iframeContainer,t.iframeElement=y,s=B.add(l.iframeContainer,y),V)try{t.getDoc()}catch(b){s.src=u=v}l.editorContainer&&(B.get(l.editorContainer).style.display=t.orgDisplay,t.hidden=B.isHidden(l.editorContainer)),t.getElement().style.display="none",B.setAttrib(t.id,"aria-hidden",!0),u||t.initContentBody(),r=s=l=null},initContentBody:function(t){var n=this,r=n.settings,s=n.getElement(),h=n.getDoc(),p,m;r.inline||(n.getElement().style.visibility=n.orgVisibility),t||r.content_editable||(h.open(),h.write(n.iframeHTML),h.close()),r.content_editable&&(n.on("remove",function(){var e=this.getBody();B.removeClass(e,"mce-content-body"),B.removeClass(e,"mce-edit-focus"),B.setAttrib(e,"contentEditable",null)}),B.addClass(s,"mce-content-body"),n.contentDocument=h=r.content_document||document,n.contentWindow=r.content_window||window,n.bodyElement=s,r.content_document=r.content_window=null,r.root_name=s.nodeName.toLowerCase()),p=n.getBody(),p.disabled=!0,n.readonly=r.readonly,n.readonly||(n.inline&&"static"==B.getStyle(p,"position",!0)&&(p.style.position="relative"),p.contentEditable=n.getParam("content_editable_state",!0)),p.disabled=!1,n.editorUpload=new T(n),n.schema=new b(r),n.dom=new e(h,{keep_values:!0,url_converter:n.convertURL,url_converter_scope:n,hex_colors:r.force_hex_style_colors,class_filter:r.class_filter,update_styles:!0,root_element:n.inline?n.getBody():null,collect:r.content_editable,schema:n.schema,onSetAttrib:function(e){n.fire("SetAttrib",e)}}),n.parser=new C(r,n.schema),n.parser.addAttributeFilter("src,href,style,tabindex",function(e,t){for(var r=e.length,i,o=n.dom,a,s;r--;)if(i=e[r],a=i.attr(t),s="data-mce-"+t,!i.attributes.map[s]){if(0===a.indexOf("data:")||0===a.indexOf("blob:"))continue;"style"===t?(a=o.serializeStyle(o.parseStyle(a),i.name),a.length||(a=null),i.attr(s,a),i.attr(t,a)):"tabindex"===t?(i.attr(s,a),i.attr(t,null)):i.attr(s,n.convertURL(a,t,i.name))}}),n.parser.addNodeFilter("script",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.attr("type")||"no/type",0!==r.indexOf("mce-")&&n.attr("type","mce-"+r)}),n.parser.addNodeFilter("#cdata",function(e){for(var t=e.length,n;t--;)n=e[t],n.type=8,n.name="#comment",n.value="[CDATA["+n.value+"]]"}),n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(e){for(var t=e.length,r,i=n.schema.getNonEmptyElements();t--;)r=e[t],r.isEmpty(i)&&(r.append(new o("br",1)).shortEnded=!0)}),n.serializer=new a(r,n),n.selection=new l(n.dom,n.getWin(),n.serializer,n),n.formatter=new c(n),n.undoManager=new u(n),n.forceBlocks=new f(n),n.enterKey=new d(n),n._nodeChangeDispatcher=new i(n),n._selectionOverrides=new R(n),n.fire("PreInit"),r.browser_spellcheck||r.gecko_spellcheck||(h.body.spellcheck=!1,B.setAttrib(p,"spellcheck","false")),n.fire("PostRender"),n.quirks=new x(n),r.directionality&&(p.dir=r.directionality),r.nowrap&&(p.style.whiteSpace="nowrap"),r.protect&&n.on("BeforeSetContent",function(e){P(r.protect,function(t){e.content=e.content.replace(t,function(e){return""})})}),n.on("SetContent",function(){n.addVisual(n.getBody())}),r.padd_empty_editor&&n.on("PostProcess",function(e){e.content=e.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
    [\r\n]*)$/,"")}),n.load({initial:!0,format:"html"}),n.startContent=n.getContent({format:"raw"}),n.initialized=!0,n.bindPendingEventDelegates(),n.fire("init"),n.focus(!0),n.nodeChanged({initial:!0}),n.execCallback("init_instance_callback",n),n.contentStyles.length>0&&(m="",P(n.contentStyles,function(e){m+=e+"\r\n"}),n.dom.addStyle(m)),P(n.contentCSS,function(e){n.loadedCSS[e]||(n.dom.loadCSS(e),n.loadedCSS[e]=!0)}),r.auto_focus&&E.setEditorTimeout(n,function(){var e;e=r.auto_focus===!0?n:n.editorManager.get(r.auto_focus),e.destroyed||e.focus()},100),s=h=p=null},focus:function(e){function t(e){return n.dom.getParent(e,function(e){return"true"===n.dom.getContentEditable(e)})}var n=this,r=n.selection,i=n.settings.content_editable,o,a,s=n.getDoc(),l=n.getBody(),c;if(!e){if(o=r.getRng(),o.item&&(a=o.item(0)),n._refreshContentEditable(),c=t(r.getNode()),n.$.contains(l,c))return c.focus(),r.normalize(),void n.editorManager.setActive(n);if(i||(w.opera||n.getBody().focus(),n.getWin().focus()),W||i){if(l.setActive)try{l.setActive()}catch(u){l.focus()}else l.focus();i&&r.normalize()}a&&a.ownerDocument==s&&(o=s.body.createControlRange(),o.addElement(a),o.select())}n.editorManager.setActive(n)},execCallback:function(e){var t=this,n=t.settings[e],r;if(n)return t.callbackLookup&&(r=t.callbackLookup[e])&&(n=r.func,r=r.scope),"string"==typeof n&&(r=n.replace(/\.\w+$/,""),r=r?F(r):0,n=F(n),t.callbackLookup=t.callbackLookup||{},t.callbackLookup[e]={func:n,scope:r}),n.apply(r||t,Array.prototype.slice.call(arguments,1))},translate:function(e){var t=this.settings.language||"en",n=this.editorManager.i18n;return e?n.data[t+"."+e]||e.replace(/\{\#([^\}]+)\}/g,function(e,r){return n.data[t+"."+r]||"{#"+r+"}"}):""},getLang:function(e,n){return this.editorManager.i18n.data[(this.settings.language||"en")+"."+e]||(n!==t?n:"{#"+e+"}")},getParam:function(e,t,n){var r=e in this.settings?this.settings[e]:t,i;return"hash"===n?(i={},"string"==typeof r?P(r.indexOf("=")>0?r.split(/[;,](?![^=;,]*(?:[;,]|$))/):r.split(","),function(e){e=e.split("="),e.length>1?i[I(e[0])]=I(e[1]):i[I(e[0])]=I(e)}):i=r,i):r},nodeChanged:function(e){this._nodeChangeDispatcher.nodeChanged(e)},addButton:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),t.text||t.icon||(t.icon=e),n.buttons=n.buttons||{},t.tooltip=t.tooltip||t.title,n.buttons[e]=t},addMenuItem:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),n.menuItems=n.menuItems||{},n.menuItems[e]=t},addContextToolbar:function(e,t){var n=this,r;n.contextToolbars=n.contextToolbars||[],"string"==typeof e&&(r=e,e=function(e){return n.dom.is(e,r)}),n.contextToolbars.push({predicate:e,items:t})},addCommand:function(e,t,n){this.editorCommands.addCommand(e,t,n)},addQueryStateHandler:function(e,t,n){this.editorCommands.addQueryStateHandler(e,t,n)},addQueryValueHandler:function(e,t,n){this.editorCommands.addQueryValueHandler(e,t,n)},addShortcut:function(e,t,n,r){this.shortcuts.add(e,t,n,r)},execCommand:function(e,t,n,r){return this.editorCommands.execCommand(e,t,n,r)},queryCommandState:function(e){return this.editorCommands.queryCommandState(e)},queryCommandValue:function(e){return this.editorCommands.queryCommandValue(e)},queryCommandSupported:function(e){return this.editorCommands.queryCommandSupported(e)},show:function(){var e=this;e.hidden&&(e.hidden=!1,e.inline?e.getBody().contentEditable=!0:(B.show(e.getContainer()),B.hide(e.id)),e.load(),e.fire("show"))},hide:function(){var e=this,t=e.getDoc();e.hidden||(V&&t&&!e.inline&&t.execCommand("SelectAll"),e.save(),e.inline?(e.getBody().contentEditable=!1,e==e.editorManager.focusedEditor&&(e.editorManager.focusedEditor=null)):(B.hide(e.getContainer()),B.setStyle(e.id,"display",e.orgDisplay)),e.hidden=!0,e.fire("hide"))},isHidden:function(){return!!this.hidden},setProgressState:function(e,t){this.fire("ProgressState",{state:e,time:t})},load:function(e){var n=this,r=n.getElement(),i;return r?(e=e||{},e.load=!0,i=n.setContent(r.value!==t?r.value:r.innerHTML,e),e.element=r,e.no_events||n.fire("LoadContent",e),e.element=r=null,i):void 0},save:function(e){var t=this,n=t.getElement(),r,i;if(n&&t.initialized)return e=e||{},e.save=!0,e.element=n,r=e.content=t.getContent(e),e.no_events||t.fire("SaveContent",e),"raw"==e.format&&t.fire("RawSaveContent",e),r=e.content,/TEXTAREA|INPUT/i.test(n.nodeName)?n.value=r:(t.inline||(n.innerHTML=r),(i=B.getParent(t.id,"form"))&&P(i.elements,function(e){return e.name==t.id?(e.value=r,!1):void 0})),e.element=n=null,e.set_dirty!==!1&&t.setDirty(!1),r},setContent:function(e,t){var n=this,r=n.getBody(),i,o;return t=t||{},t.format=t.format||"html",t.set=!0,t.content=e,t.no_events||n.fire("BeforeSetContent",t),e=t.content,0===e.length||/^\s+$/.test(e)?(o=V&&11>V?"":'
    ',"TABLE"==r.nodeName?e=""+o+"":/^(UL|OL)$/.test(r.nodeName)&&(e="
  • "+o+"
  • "),i=n.settings.forced_root_block,i&&n.schema.isValidChild(r.nodeName.toLowerCase(),i.toLowerCase())?(e=o,e=n.dom.createHTML(i,n.settings.forced_root_block_attrs,e)):V||e||(e='
    '),n.dom.setHTML(r,e),n.fire("SetContent",t)):("raw"!==t.format&&(e=new s({validate:n.validate},n.schema).serialize(n.parser.parse(e,{isRootContent:!0}))),t.content=I(e),n.dom.setHTML(r,t.content),t.no_events||n.fire("SetContent",t)),t.content},getContent:function(e){var t=this,n,r=t.getBody();return e=e||{},e.format=e.format||"html",e.get=!0,e.getInner=!0,e.no_events||t.fire("BeforeGetContent",e),n="raw"==e.format?t.serializer.getTrimmedContent():"text"==e.format?r.innerText||r.textContent:t.serializer.serialize(r,e),"text"!=e.format?e.content=I(n):e.content=n,e.no_events||t.fire("GetContent",e),e.content},insertContent:function(e,t){t&&(e=L({content:e},t)),this.execCommand("mceInsertContent",!1,e)},isDirty:function(){return!this.isNotDirty},setDirty:function(e){var t=!this.isNotDirty;this.isNotDirty=!e,e&&e!=t&&this.fire("dirty")},setMode:function(e){S.setMode(this,e)},getContainer:function(){var e=this;return e.container||(e.container=B.get(e.editorContainer||e.id+"_parent")),e.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return this.targetElm||(this.targetElm=B.get(this.id)),this.targetElm},getWin:function(){var e=this,t;return e.contentWindow||(t=e.iframeElement,t&&(e.contentWindow=t.contentWindow)),e.contentWindow},getDoc:function(){var e=this,t;return e.contentDocument||(t=e.getWin(),t&&(e.contentDocument=t.document)),e.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(e,t,n){var r=this,i=r.settings;return i.urlconverter_callback?r.execCallback("urlconverter_callback",e,n,!0,t):!i.convert_urls||n&&"LINK"==n.nodeName||0===e.indexOf("file:")||0===e.length?e:i.relative_urls?r.documentBaseURI.toRelative(e):e=r.documentBaseURI.toAbsolute(e,i.remove_script_host)},addVisual:function(e){var n=this,r=n.settings,i=n.dom,o;e=e||n.getBody(),n.hasVisual===t&&(n.hasVisual=r.visual),P(i.select("table,a",e),function(e){var t;switch(e.nodeName){case"TABLE":return o=r.visual_table_class||"mce-item-table",t=i.getAttrib(e,"border"),void(t&&"0"!=t||!n.hasVisual?i.removeClass(e,o):i.addClass(e,o));case"A":return void(i.getAttrib(e,"href",!1)||(t=i.getAttrib(e,"name")||e.id,o=r.visual_anchor_class||"mce-item-anchor",t&&n.hasVisual?i.addClass(e,o):i.removeClass(e,o)))}}),n.fire("VisualAid",{element:e,hasVisual:n.hasVisual})},remove:function(){var e=this;e.removed||(e.save(),e.removed=1,e.unbindAllNativeEvents(),e.hasHiddenInput&&B.remove(e.getElement().nextSibling),e.inline||(V&&10>V&&e.getDoc().execCommand("SelectAll",!1,null),B.setStyle(e.id,"display",e.orgDisplay),e.getBody().onload=null),e.fire("remove"),e.editorManager.remove(e),B.remove(e.getContainer()),e._selectionOverrides.destroy(),e.editorUpload.destroy(),e.destroy())},destroy:function(e){var t=this,n;if(!t.destroyed){if(!e&&!t.removed)return void t.remove();e||(t.editorManager.off("beforeunload",t._beforeUnload),t.theme&&t.theme.destroy&&t.theme.destroy(),t.selection.destroy(),t.dom.destroy()),n=t.formElement,n&&(n._mceOldSubmit&&(n.submit=n._mceOldSubmit,n._mceOldSubmit=null),B.unbind(n,"submit reset",t.formEventDelegate)),t.contentAreaContainer=t.formElement=t.container=t.editorContainer=null,t.bodyElement=t.contentDocument=t.contentWindow=null,t.iframeElement=t.targetElm=null,t.selection&&(t.selection=t.selection.win=t.selection.dom=t.selection.dom.doc=null),t.destroyed=1}},uploadImages:function(e){return this.editorUpload.uploadImages(e)},_scanForImages:function(){return this.editorUpload.scanForImages()},_refreshContentEditable:function(){var e=this,t,n;e._isHidden()&&(t=e.getBody(),n=t.parentNode,n.removeChild(t),n.appendChild(t),t.focus())},_isHidden:function(){var e;return W?(e=this.selection.getSel(),!e||!e.rangeCount||0===e.rangeCount):0}},L(A.prototype,_),A}),r(Ge,[],function(){var e={},t="en";return{setCode:function(e){e&&(t=e,this.rtl=this.data[e]?"rtl"===this.data[e]._dir:!1)},getCode:function(){return t},rtl:!1,add:function(t,n){var r=e[t];r||(e[t]=r={});for(var i in n)r[i]=n[i];this.setCode(t)},translate:function(n){var r;if(r=e[t],r||(r={}),"undefined"==typeof n)return n;if("string"!=typeof n&&n.raw)return n.raw;if(n.push){var i=n.slice(1);n=(r[n[0]]||n[0]).replace(/\{([0-9]+)\}/g,function(e,t){return i[t]})}return(r[n]||n).replace(/{context:\w+}$/,"")},data:e}}),r(Je,[w,u,h],function(e,t,n){function r(e){function l(){try{return document.activeElement}catch(e){return document.body}}function c(e,t){if(t&&t.startContainer){if(!e.isChildOf(t.startContainer,e.getRoot())||!e.isChildOf(t.endContainer,e.getRoot()))return;return{startContainer:t.startContainer,startOffset:t.startOffset,endContainer:t.endContainer,endOffset:t.endOffset}}return t}function u(e,t){var n;return t.startContainer?(n=e.getDoc().createRange(),n.setStart(t.startContainer,t.startOffset),n.setEnd(t.endContainer,t.endOffset)):n=t,n}function d(e){return!!s.getParent(e,r.isEditorUIElement)}function f(r){var f=r.editor;f.on("init",function(){(f.inline||n.ie)&&("onbeforedeactivate"in document&&n.ie<9?f.dom.bind(f.getBody(),"beforedeactivate",function(e){if(e.target==f.getBody())try{f.lastRng=f.selection.getRng()}catch(t){}}):f.on("nodechange mouseup keyup",function(e){var t=l();"nodechange"==e.type&&e.selectionChange||(t&&t.id==f.id+"_ifr"&&(t=f.getBody()),f.dom.isChildOf(t,f.getBody())&&(f.lastRng=f.selection.getRng()))}),n.webkit&&!i&&(i=function(){var t=e.activeEditor;if(t&&t.selection){var n=t.selection.getRng();n&&!n.collapsed&&(f.lastRng=n)}},s.bind(document,"selectionchange",i)))}),f.on("setcontent",function(){f.lastRng=null}),f.on("mousedown",function(){f.selection.lastFocusBookmark=null}),f.on("focusin",function(){var t=e.focusedEditor,n;f.selection.lastFocusBookmark&&(n=u(f,f.selection.lastFocusBookmark),f.selection.lastFocusBookmark=null,f.selection.setRng(n)),t!=f&&(t&&t.fire("blur",{focusedEditor:f}),e.setActive(f),e.focusedEditor=f,f.fire("focus",{blurredEditor:t}),f.focus(!0)),f.lastRng=null}),f.on("focusout",function(){t.setEditorTimeout(f,function(){var t=e.focusedEditor;d(l())||t!=f||(f.fire("blur",{focusedEditor:null}),e.focusedEditor=null,f.selection&&(f.selection.lastFocusBookmark=null))})}),o||(o=function(t){var n=e.activeEditor;n&&t.target.ownerDocument==document&&(n.selection&&t.target!=n.getBody()&&(n.selection.lastFocusBookmark=c(n.dom,n.lastRng)),t.target==document.body||d(t.target)||e.focusedEditor!=n||(n.fire("blur",{focusedEditor:null}),e.focusedEditor=null))},s.bind(document,"focusin",o)),f.inline&&!a&&(a=function(t){var n=e.activeEditor;if(n.inline&&!n.dom.isChildOf(t.target,n.getBody())){var r=n.selection.getRng();r.collapsed||(n.lastRng=r)}},s.bind(document,"mouseup",a))}function h(t){e.focusedEditor==t.editor&&(e.focusedEditor=null),e.activeEditor||(s.unbind(document,"selectionchange",i),s.unbind(document,"focusin",o),s.unbind(document,"mouseup",a),i=o=a=null)}e.on("AddEditor",f),e.on("RemoveEditor",h)}var i,o,a,s=e.DOM;return r.isEditorUIElement=function(e){return-1!==e.className.toString().indexOf("mce-")},r}),r(Qe,[Ke,g,w,te,h,m,oe,Ge,Je],function(e,t,n,r,i,o,a,s,l){function c(e){m(b.editors,function(t){t.fire("ResizeWindow",e)})}function u(e,n){n!==C&&(n?t(window).on("resize",c):t(window).off("resize",c),C=n)}function d(e){var t=b.editors,n;delete t[e.id];for(var r=0;r0&&m(p(e),function(e){var n;(n=h.get(e))?r(e,t,n):m(document.forms,function(n){m(n.elements,function(n){n.name===e&&(e="mce_editor_"+v++,h.setAttrib(n,"id",e),r(e,t,n))})})});break;case"textareas":case"specific_textareas":m(h.select("textarea"),function(e){t.editor_deselector&&o(e,t.editor_deselector)||(!t.editor_selector||o(e,t.editor_selector))&&r(n(e),t,e)})}t.oninit&&(e=s=0,m(l,function(t){s++,t.initialized?e++:t.on("init",function(){e++,e==s&&i("oninit")}),e==s&&i("oninit")}))}var s=this,l=[];s.settings=t,h.bind(window,"ready",a)},get:function(e){return arguments.length?e in this.editors?this.editors[e]:null:this.editors},add:function(e){var t=this,n=t.editors;return n[e.id]=e,n.push(e),u(n,!0),t.activeEditor=e,t.fire("AddEditor",{editor:e}),y||(y=function(){t.fire("BeforeUnload")},h.bind(window,"beforeunload",y)),e},createEditor:function(t,n){return this.add(new e(t,n,this))},remove:function(e){var t=this,n,r=t.editors,i;{if(e)return"string"==typeof e?(e=e.selector||e,void m(h.select(e),function(e){i=r[e.id],i&&t.remove(i)})):(i=e,r[i.id]?(d(i)&&t.fire("RemoveEditor",{editor:i}),r.length||h.unbind(window,"beforeunload",y),i.remove(),u(r,r.length>0),i):null);for(n=r.length-1;n>=0;n--)t.remove(r[n])}},execCommand:function(t,n,r){var i=this,o=i.get(r);switch(t){case"mceAddEditor":return i.get(r)||new e(r,i.settings,i).render(),!0;case"mceRemoveEditor":return o&&o.remove(),!0;case"mceToggleEditor":return o?(o.isHidden()?o.show():o.hide(),!0):(i.execCommand("mceAddEditor",0,r),!0)}return i.activeEditor?i.activeEditor.execCommand(t,n,r):!1},triggerSave:function(){m(this.editors,function(e){e.save()})},addI18n:function(e,t){s.add(e,t)},translate:function(e){return s.translate(e)},setActive:function(e){var t=this.activeEditor;this.activeEditor!=e&&(t&&t.fire("deactivate",{relatedTarget:e}),e.fire("activate",{relatedTarget:t})),this.activeEditor=e}},g(b,a),b.setup(),window.tinymce=window.tinyMCE=b,b}),r(Ze,[Qe,m],function(e,t){var n=t.each,r=t.explode;e.on("AddEditor",function(e){var t=e.editor;t.on("preInit",function(){function e(e,t){n(t,function(t,n){t&&s.setStyle(e,n,t)}),s.rename(e,"span")}function i(e){s=t.dom,l.convert_fonts_to_spans&&n(s.select("font,u,strike",e.node),function(e){o[e.nodeName.toLowerCase()](s,e)})}var o,a,s,l=t.settings;l.inline_styles&&(a=r(l.font_size_legacy_values),o={font:function(t,n){e(n,{backgroundColor:n.style.backgroundColor,color:n.color,fontFamily:n.face,fontSize:a[parseInt(n.size,10)-1]})},u:function(n,r){"html4"===t.settings.schema&&e(r,{textDecoration:"underline"})},strike:function(t,n){e(n,{textDecoration:"line-through"})}},t.on("PreProcess SetContent",i))})})}),r(et,[oe,m],function(e,t){var n={send:function(e){function r(){!e.async||4==i.readyState||o++>1e4?(e.success&&1e4>o&&200==i.status?e.success.call(e.success_scope,""+i.responseText,i,e):e.error&&e.error.call(e.error_scope,o>1e4?"TIMED_OUT":"GENERAL",i,e),i=null):setTimeout(r,10)}var i,o=0;if(e.scope=e.scope||this,e.success_scope=e.success_scope||e.scope,e.error_scope=e.error_scope||e.scope,e.async=e.async===!1?!1:!0,e.data=e.data||"",i=new XMLHttpRequest){if(i.overrideMimeType&&i.overrideMimeType(e.content_type),i.open(e.type||(e.data?"POST":"GET"),e.url,e.async),e.crossDomain&&(i.withCredentials=!0),e.content_type&&i.setRequestHeader("Content-Type",e.content_type),e.requestheaders&&t.each(e.requestheaders,function(e){i.setRequestHeader(e.key,e.value)}),i.setRequestHeader("X-Requested-With","XMLHttpRequest"),i=n.fire("beforeSend",{xhr:i,settings:e}).xhr,i.send(e.data),!e.async)return r();setTimeout(r,10)}}};return t.extend(n,e),n}),r(tt,[],function(){function e(t,n){var r,i,o,a;if(n=n||'"',null===t)return"null";if(o=typeof t,"string"==o)return i="\bb t\nn\ff\rr\"\"''\\\\",n+t.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(e,t){return'"'===n&&"'"===e?e:(r=i.indexOf(t),r+1?"\\"+i.charAt(r+1):(e=t.charCodeAt().toString(16),"\\u"+"0000".substring(e.length)+e))})+n;if("object"==o){if(t.hasOwnProperty&&"[object Array]"===Object.prototype.toString.call(t)){for(r=0,i="[";r0?",":"")+e(t[r],n);return i+"]"}i="{";for(a in t)t.hasOwnProperty(a)&&(i+="function"!=typeof t[a]?(i.length>1?","+n:n)+a+n+":"+e(t[a],n):"");return i+"}"}return""+t}return{serialize:e,parse:function(e){try{return window[String.fromCharCode(101)+"val"]("("+e+")")}catch(t){}}}}),r(nt,[tt,et,m],function(e,t,n){function r(e){this.settings=i({},e),this.count=0}var i=n.extend;return r.sendRPC=function(e){return(new r).send(e)},r.prototype={send:function(n){var r=n.error,o=n.success;n=i(this.settings,n),n.success=function(t,i){t=e.parse(t),"undefined"==typeof t&&(t={error:"JSON Parse error."}),t.error?r.call(n.error_scope||n.scope,t.error,i):o.call(n.success_scope||n.scope,t.result)},n.error=function(e,t){r&&r.call(n.error_scope||n.scope,e,t)},n.data=e.serialize({id:n.id||"c"+this.count++,method:n.method,params:n.params}),n.content_type="application/json",t.send(n)}},r}),r(rt,[w],function(e){return{callbacks:{},count:0,send:function(n){var r=this,i=e.DOM,o=n.count!==t?n.count:r.count,a="tinymce_jsonp_"+o;r.callbacks[o]=function(e){i.remove(a),delete r.callbacks[o],n.callback(e)},i.add(i.doc.body,"script",{id:a,src:n.url,type:"text/javascript"}),r.count++}}}),r(it,[],function(){function e(){s=[];for(var e in a)s.push(e);i.length=s.length}function n(){function n(e){var n,r;return r=e!==t?u+e:i.indexOf(",",u),-1===r||r>i.length?null:(n=i.substring(u,r),u=r+1,n)}var r,i,s,u=0;if(a={},c){o.load(l),i=o.getAttribute(l)||"";do{var d=n();if(null===d)break;if(r=n(parseInt(d,32)||0),null!==r){if(d=n(),null===d)break;s=n(parseInt(d,32)||0),r&&(a[r]=s)}}while(null!==r);e()}}function r(){var t,n="";if(c){for(var r in a)t=a[r],n+=(n?",":"")+r.length.toString(32)+","+r+","+t.length.toString(32)+","+t;o.setAttribute(l,n);try{o.save(l)}catch(i){}e()}}var i,o,a,s,l,c;try{if(window.localStorage)return localStorage}catch(u){}return l="tinymce",o=document.documentElement,c=!!o.addBehavior,c&&o.addBehavior("#default#userData"),i={key:function(e){return s[e]},getItem:function(e){return e in a?a[e]:null},setItem:function(e,t){a[e]=""+t,r()},removeItem:function(e){delete a[e],r()},clear:function(){a={},r()}},n(),i}),r(ot,[w,d,N,E,m,h],function(e,t,n,r,i,o){var a=window.tinymce;return a.DOM=e.DOM,a.ScriptLoader=n.ScriptLoader,a.PluginManager=r.PluginManager,a.ThemeManager=r.ThemeManager,a.dom=a.dom||{},a.dom.Event=t.Event,i.each(i,function(e,t){a[t]=e}),i.each("isOpera isWebKit isIE isGecko isMac".split(" "),function(e){a[e]=o[e.substr(2).toLowerCase()]}),{}}),r(at,[ne,m],function(e,t){return e.extend({Defaults:{firstControlClass:"first",lastControlClass:"last"},init:function(e){this.settings=t.extend({},this.Defaults,e)},preRender:function(e){e.bodyClasses.add(this.settings.containerClass)},applyClasses:function(e){var t=this,n=t.settings,r,i,o,a;r=n.firstControlClass,i=n.lastControlClass,e.each(function(e){e.classes.remove(r).remove(i).add(n.controlClass),e.visible()&&(o||(o=e),a=e)}),o&&o.classes.add(r),a&&a.classes.add(i)},renderHtml:function(e){var t=this,n="";return t.applyClasses(e.items()),e.items().each(function(e){n+=e.renderHtml()}),n},recalc:function(){},postRender:function(){},isNative:function(){return!1}})}),r(st,[at],function(e){return e.extend({Defaults:{containerClass:"abs-layout",controlClass:"abs-layout-item"},recalc:function(e){e.items().filter(":visible").each(function(e){var t=e.settings;e.layoutRect({x:t.x,y:t.y,w:t.w,h:t.h}),e.recalc&&e.recalc()})},renderHtml:function(e){return'
    '+this._super(e)}})}),r(lt,[ke],function(e){return e.extend({Defaults:{classes:"widget btn",role:"button"},init:function(e){var t=this,n;t._super(e),e=t.settings,n=t.settings.size,t.on("click mousedown",function(e){e.preventDefault()}),t.on("touchstart",function(e){t.fire("click",e),e.preventDefault()}),e.subtype&&t.classes.add(e.subtype),n&&t.classes.add("btn-"+n),e.icon&&t.icon(e.icon)},icon:function(e){return arguments.length?(this.state.set("icon",e),this):this.state.get("icon")},repaint:function(){var e=this.getEl().firstChild,t;e&&(t=e.style,t.width=t.height="100%"),this._super()},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.state.get("icon"),i,o=e.state.get("text"),a="";return i=e.settings.image,i?(r="none","string"!=typeof i&&(i=window.getSelection?i[0]:i[1]),i=" style=\"background-image: url('"+i+"')\""):i="",o&&(e.classes.add("btn-has-text"),a=''+e.encode(o)+""),r=e.settings.icon?n+"ico "+n+"i-"+r:"",'
    "},bindStates:function(){function e(e){var i=n("span."+r,t.getEl());e?(i[0]||(n("button:first",t.getEl()).append(''),i=n("span."+r,t.getEl())),i.html(t.encode(e))):i.remove(),t.classes.toggle("btn-has-text",!!e)}var t=this,n=t.$,r=t.classPrefix+"txt";return t.state.on("change:text",function(t){e(t.value)}),t.state.on("change:icon",function(n){var r=n.value,i=t.classPrefix;t.settings.icon=r,r=r?i+"ico "+i+"i-"+t.settings.icon:"";var o=t.getEl().firstChild,a=o.getElementsByTagName("i")[0];r?(a&&a==o.firstChild||(a=document.createElement("i"),o.insertBefore(a,o.firstChild)),a.className=r):a&&o.removeChild(a),e(t.state.get("text"))}),t._super()}})}),r(ct,[ge],function(e){return e.extend({Defaults:{defaultType:"button",role:"group"},renderHtml:function(){var e=this,t=e._layout;return e.classes.add("btn-group"),e.preRender(),t.preRender(e),'
    '+(e.settings.html||"")+t.renderHtml(e)+"
    "}})}),r(ut,[ke],function(e){return e.extend({Defaults:{classes:"checkbox",role:"checkbox",checked:!1},init:function(e){var t=this;t._super(e),t.on("click mousedown",function(e){e.preventDefault()}),t.on("click",function(e){e.preventDefault(),t.disabled()||t.checked(!t.checked())}),t.checked(t.settings.checked)},checked:function(e){return arguments.length?(this.state.set("checked",e),this):this.state.get("checked")},value:function(e){return arguments.length?this.checked(e):this.checked()},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix;return'
    '+e.encode(e.state.get("text"))+"
    "},bindStates:function(){function e(e){t.classes.toggle("checked",e),t.aria("checked",e)}var t=this;return t.state.on("change:text",function(e){t.getEl("al").firstChild.data=t.translate(e.value)}),t.state.on("change:checked change:value",function(n){ +t.fire("change"),e(n.value)}),t.state.on("change:icon",function(e){var n=e.value,r=t.classPrefix;if("undefined"==typeof n)return t.settings.icon;t.settings.icon=n,n=n?r+"ico "+r+"i-"+t.settings.icon:"";var i=t.getEl().firstChild,o=i.getElementsByTagName("i")[0];n?(o&&o==i.firstChild||(o=document.createElement("i"),i.insertBefore(o,i.firstChild)),o.className=n):o&&i.removeChild(o)}),t.state.get("checked")&&e(!0),t._super()}})}),r(dt,[ke,pe,ce,g],function(e,t,n,r){return e.extend({init:function(e){var t=this;t._super(e),e=t.settings,t.classes.add("combobox"),t.subinput=!0,t.ariaTarget="inp",e.menu=e.menu||e.values,e.menu&&(e.icon="caret"),t.on("click",function(n){var i=n.target,o=t.getEl();if(r.contains(o,i)||i==o)for(;i&&i!=o;)i.id&&-1!=i.id.indexOf("-open")&&(t.fire("action"),e.menu&&(t.showMenu(),n.aria&&t.menu.items()[0].focus())),i=i.parentNode}),t.on("keydown",function(e){"INPUT"==e.target.nodeName&&13==e.keyCode&&t.parents().reverse().each(function(n){var r=t.state.get("value"),i=t.getEl("inp").value;return e.preventDefault(),t.state.set("value",i),r!=i&&t.fire("change"),n.hasEventListeners("submit")&&n.toJSON?(n.fire("submit",{data:n.toJSON()}),!1):void 0})}),t.on("keyup",function(e){"INPUT"==e.target.nodeName&&t.state.set("value",e.target.value)})},showMenu:function(){var e=this,n=e.settings,r;e.menu||(r=n.menu||[],r.length?r={type:"menu",items:r}:r.type=r.type||"menu",e.menu=t.create(r).parent(e).renderTo(e.getContainerElm()),e.fire("createmenu"),e.menu.reflow(),e.menu.on("cancel",function(t){t.control===e.menu&&e.focus()}),e.menu.on("show hide",function(t){t.control.items().each(function(t){t.active(t.value()==e.value())})}).fire("show"),e.menu.on("select",function(t){e.value(t.control.value())}),e.on("focusin",function(t){"INPUT"==t.target.tagName.toUpperCase()&&e.menu.hide()}),e.aria("expanded",!0)),e.menu.show(),e.menu.layoutRect({w:e.layoutRect().w}),e.menu.moveRel(e.getEl(),e.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"])},focus:function(){this.getEl("inp").focus()},repaint:function(){var e=this,t=e.getEl(),i=e.getEl("open"),o=e.layoutRect(),a,s;a=i?o.w-n.getSize(i).width-10:o.w-10;var l=document;return l.all&&(!l.documentMode||l.documentMode<=8)&&(s=e.layoutRect().h-2+"px"),r(t.firstChild).css({width:a,lineHeight:s}),e._super(),e},postRender:function(){var e=this;return r(this.getEl("inp")).on("change",function(t){e.state.set("value",t.target.value),e.fire("change",t)}),e._super()},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.classPrefix,i=e.state.get("value")||"",o,a,s="",l="";return"spellcheck"in n&&(l+=' spellcheck="'+n.spellcheck+'"'),n.maxLength&&(l+=' maxlength="'+n.maxLength+'"'),n.size&&(l+=' size="'+n.size+'"'),n.subtype&&(l+=' type="'+n.subtype+'"'),e.disabled()&&(l+=' disabled="disabled"'),o=n.icon,o&&"caret"!=o&&(o=r+"ico "+r+"i-"+n.icon),a=e.state.get("text"),(o||a)&&(s='
    ",e.classes.add("has-open")),'
    '+s+"
    "},value:function(e){return arguments.length?(this.state.set("value",e),this):(this.state.get("rendered")&&this.state.set("value",this.getEl("inp").value),this.state.get("value"))},bindStates:function(){var e=this;return e.state.on("change:value",function(t){e.getEl("inp").value!=t.value&&(e.getEl("inp").value=t.value)}),e.state.on("change:disabled",function(t){e.getEl("inp").disabled=t.value}),e._super()},remove:function(){r(this.getEl("inp")).off(),this._super()}})}),r(ft,[dt],function(e){return e.extend({init:function(e){var t=this;e.spellcheck=!1,e.onaction&&(e.icon="none"),t._super(e),t.classes.add("colorbox"),t.on("change keyup postrender",function(){t.repaintColor(t.value())})},repaintColor:function(e){var t=this.getEl().getElementsByTagName("i")[0];if(t)try{t.style.background=e}catch(n){}},bindStates:function(){var e=this;return e.state.on("change:value",function(t){e._rendered&&e.repaintColor(t.value)}),e._super()}})}),r(ht,[lt,we],function(e,t){return e.extend({showPanel:function(){var e=this,n=e.settings;if(e.active(!0),e.panel)e.panel.show();else{var r=n.panel;r.type&&(r={layout:"grid",items:r}),r.role=r.role||"dialog",r.popover=!0,r.autohide=!0,r.ariaRoot=!0,e.panel=new t(r).on("hide",function(){e.active(!1)}).on("cancel",function(t){t.stopPropagation(),e.focus(),e.hidePanel()}).parent(e).renderTo(e.getContainerElm()),e.panel.fire("show"),e.panel.reflow()}e.panel.moveRel(e.getEl(),n.popoverAlign||(e.isRtl()?["bc-tr","bc-tc"]:["bc-tl","bc-tc"]))},hidePanel:function(){var e=this;e.panel&&e.panel.hide()},postRender:function(){var e=this;return e.aria("haspopup",!0),e.on("click",function(t){t.control===e&&(e.panel&&e.panel.visible()?e.hidePanel():(e.showPanel(),e.panel.focus(!!t.aria)))}),e._super()},remove:function(){return this.panel&&(this.panel.remove(),this.panel=null),this._super()}})}),r(pt,[ht,w],function(e,t){var n=t.DOM;return e.extend({init:function(e){this._super(e),this.classes.add("colorbutton")},color:function(e){return e?(this._color=e,this.getEl("preview").style.backgroundColor=e,this):this._color},resetColor:function(){return this._color=null,this.getEl("preview").style.backgroundColor=null,this},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.state.get("text"),i=e.settings.icon?n+"ico "+n+"i-"+e.settings.icon:"",o=e.settings.image?" style=\"background-image: url('"+e.settings.image+"')\"":"",a="";return r&&(e.classes.add("btn-has-text"),a=''+e.encode(r)+""),'
    '},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(r){r.aria&&"down"==r.aria.key||r.control!=e||n.getParent(r.target,"."+e.classPrefix+"open")||(r.stopImmediatePropagation(),t.call(e,r))}),delete e.settings.onclick,e._super()}})}),r(mt,[],function(){function e(e){function i(e,i,o){var a,s,l,c,u,d;return a=0,s=0,l=0,e/=255,i/=255,o/=255,u=t(e,t(i,o)),d=n(e,n(i,o)),u==d?(l=u,{h:0,s:0,v:100*l}):(c=e==u?i-o:o==u?e-i:o-e,a=e==u?3:o==u?1:5,a=60*(a-c/(d-u)),s=(d-u)/d,l=d,{h:r(a),s:r(100*s),v:r(100*l)})}function o(e,i,o){var a,s,l,c;if(e=(parseInt(e,10)||0)%360,i=parseInt(i,10)/100,o=parseInt(o,10)/100,i=n(0,t(i,1)),o=n(0,t(o,1)),0===i)return void(d=f=h=r(255*o));switch(a=e/60,s=o*i,l=s*(1-Math.abs(a%2-1)),c=o-s,Math.floor(a)){case 0:d=s,f=l,h=0;break;case 1:d=l,f=s,h=0;break;case 2:d=0,f=s,h=l;break;case 3:d=0,f=l,h=s;break;case 4:d=l,f=0,h=s;break;case 5:d=s,f=0,h=l;break;default:d=f=h=0}d=r(255*(d+c)),f=r(255*(f+c)),h=r(255*(h+c))}function a(){function e(e){return e=parseInt(e,10).toString(16),e.length>1?e:"0"+e}return"#"+e(d)+e(f)+e(h)}function s(){return{r:d,g:f,b:h}}function l(){return i(d,f,h)}function c(e){var t;return"object"==typeof e?"r"in e?(d=e.r,f=e.g,h=e.b):"v"in e&&o(e.h,e.s,e.v):(t=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)[^\)]*\)/gi.exec(e))?(d=parseInt(t[1],10),f=parseInt(t[2],10),h=parseInt(t[3],10)):(t=/#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(e))?(d=parseInt(t[1],16),f=parseInt(t[2],16),h=parseInt(t[3],16)):(t=/#([0-F])([0-F])([0-F])/gi.exec(e))&&(d=parseInt(t[1]+t[1],16),f=parseInt(t[2]+t[2],16),h=parseInt(t[3]+t[3],16)),d=0>d?0:d>255?255:d,f=0>f?0:f>255?255:f,h=0>h?0:h>255?255:h,u}var u=this,d=0,f=0,h=0;e&&c(e),u.toRgb=s,u.toHsv=l,u.toHex=a,u.parse=c}var t=Math.min,n=Math.max,r=Math.round;return e}),r(gt,[ke,ve,ce,mt],function(e,t,n,r){return e.extend({Defaults:{classes:"widget colorpicker"},init:function(e){this._super(e)},postRender:function(){function e(e,t){var r=n.getPos(e),i,o;return i=t.pageX-r.x,o=t.pageY-r.y,i=Math.max(0,Math.min(i/e.clientWidth,1)),o=Math.max(0,Math.min(o/e.clientHeight,1)),{x:i,y:o}}function i(e,t){var i=(360-e.h)/360;n.css(d,{top:100*i+"%"}),t||n.css(h,{left:e.s+"%",top:100-e.v+"%"}),f.style.background=new r({s:100,v:100,h:e.h}).toHex(),s.color().parse({s:e.s,v:e.v,h:e.h})}function o(t){var n;n=e(f,t),c.s=100*n.x,c.v=100*(1-n.y),i(c),s.fire("change")}function a(t){var n;n=e(u,t),c=l.toHsv(),c.h=360*(1-n.y),i(c,!0),s.fire("change")}var s=this,l=s.color(),c,u,d,f,h;u=s.getEl("h"),d=s.getEl("hp"),f=s.getEl("sv"),h=s.getEl("svp"),s._repaint=function(){c=l.toHsv(),i(c)},s._super(),s._svdraghelper=new t(s._id+"-sv",{start:o,drag:o}),s._hdraghelper=new t(s._id+"-h",{start:a,drag:a}),s._repaint()},rgb:function(){return this.color().toRgb()},value:function(e){var t=this;return arguments.length?(t.color().parse(e),void(t._rendered&&t._repaint())):t.color().toHex()},color:function(){return this._color||(this._color=new r),this._color},renderHtml:function(){function e(){var e,t,n="",i,a;for(i="filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=",a=o.split(","),e=0,t=a.length-1;t>e;e++)n+='
    ';return n}var t=this,n=t._id,r=t.classPrefix,i,o="#ff0000,#ff0080,#ff00ff,#8000ff,#0000ff,#0080ff,#00ffff,#00ff80,#00ff00,#80ff00,#ffff00,#ff8000,#ff0000",a="background: -ms-linear-gradient(top,"+o+");background: linear-gradient(to bottom,"+o+");";return i='
    '+e()+'
    ','
    '+i+"
    "}})}),r(vt,[ke],function(e){return e.extend({init:function(e){var t=this;e.delimiter||(e.delimiter="\xbb"),t._super(e),t.classes.add("path"),t.canFocus=!0,t.on("click",function(e){var n,r=e.target;(n=r.getAttribute("data-index"))&&t.fire("select",{value:t.row()[n],index:n})}),t.row(t.settings.row)},focus:function(){var e=this;return e.getEl().firstChild.focus(),e},row:function(e){return arguments.length?(this.state.set("row",e),this):this.state.get("row")},renderHtml:function(){var e=this;return'
    '+e._getDataPathHtml(e.state.get("row"))+"
    "},bindStates:function(){var e=this;return e.state.on("change:row",function(t){e.innerHtml(e._getDataPathHtml(t.value))}),e._super()},_getDataPathHtml:function(e){var t=this,n=e||[],r,i,o="",a=t.classPrefix;for(r=0,i=n.length;i>r;r++)o+=(r>0?'":"")+'
    '+n[r].name+"
    ";return o||(o='
    \xa0
    '),o}})}),r(yt,[vt,Qe],function(e,t){return e.extend({postRender:function(){function e(e){if(1===e.nodeType){if("BR"==e.nodeName||e.getAttribute("data-mce-bogus"))return!0;if("bookmark"===e.getAttribute("data-mce-type"))return!0}return!1}var n=this,r=t.activeEditor;return r.settings.elementpath!==!1&&(n.on("select",function(e){r.focus(),r.selection.select(this.row()[e.index].element),r.nodeChanged()}),r.on("nodeChange",function(t){for(var i=[],o=t.parents,a=o.length;a--;)if(1==o[a].nodeType&&!e(o[a])){var s=r.fire("ResolveName",{name:o[a].nodeName.toLowerCase(),target:o[a]});if(s.isDefaultPrevented()||i.push({name:s.name,element:o[a]}),s.isPropagationStopped())break}n.row(i)})),n._super()}})}),r(bt,[ge],function(e){return e.extend({Defaults:{layout:"flex",align:"center",defaults:{flex:1}},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.classes.add("formitem"),t.preRender(e),'
    '+(e.settings.title?'
    '+e.settings.title+"
    ":"")+'
    '+(e.settings.html||"")+t.renderHtml(e)+"
    "}})}),r(Ct,[ge,bt,m],function(e,t,n){return e.extend({Defaults:{containerCls:"form",layout:"flex",direction:"column",align:"stretch",flex:1,padding:20,labelGap:30,spacing:10,callbacks:{submit:function(){this.submit()}}},preRender:function(){var e=this,r=e.items();e.settings.formItemDefaults||(e.settings.formItemDefaults={layout:"flex",autoResize:"overflow",defaults:{flex:1}}),r.each(function(r){var i,o=r.settings.label;o&&(i=new t(n.extend({items:{type:"label",id:r._id+"-l",text:o,flex:0,forId:r._id,disabled:r.disabled()}},e.settings.formItemDefaults)),i.type="formitem",r.aria("labelledby",r._id+"-l"),"undefined"==typeof r.settings.flex&&(r.settings.flex=1),e.replace(r,i),i.add(r))})},submit:function(){return this.fire("submit",{data:this.toJSON()})},postRender:function(){var e=this;e._super(),e.fromJSON(e.settings.data)},bindStates:function(){function e(){var e=0,n=[],r,i,o;if(t.settings.labelGapCalc!==!1)for(o="children"==t.settings.labelGapCalc?t.find("formitem"):t.items(),o.filter("formitem").each(function(t){var r=t.items()[0],i=r.getEl().clientWidth;e=i>e?i:e,n.push(r)}),i=t.settings.labelGap||0,r=n.length;r--;)n[r].settings.minWidth=e+i}var t=this;t._super(),t.on("show",e),e()}})}),r(xt,[Ct],function(e){return e.extend({Defaults:{containerCls:"fieldset",layout:"flex",direction:"column",align:"stretch",flex:1,padding:"25 15 5 15",labelGap:30,spacing:10,border:1},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.preRender(),t.preRender(e),'
    '+(e.settings.title?''+e.settings.title+"":"")+'
    '+(e.settings.html||"")+t.renderHtml(e)+"
    "}})}),r(wt,[dt,m],function(e,t){return e.extend({init:function(e){var n=this,r=tinymce.activeEditor,i=r.settings,o,a,s;e.spellcheck=!1,s=i.file_picker_types||i.file_browser_callback_types,s&&(s=t.makeMap(s,/[, ]/)),(!s||s[e.filetype])&&(a=i.file_picker_callback,!a||s&&!s[e.filetype]?(a=i.file_browser_callback,!a||s&&!s[e.filetype]||(o=function(){a(n.getEl("inp").id,n.value(),e.filetype,window)})):o=function(){var i=n.fire("beforecall").meta;i=t.extend({filetype:e.filetype},i),a.call(r,function(e,t){n.value(e).fire("change",{meta:t})},n.value(),i)}),o&&(e.icon="browse",e.onaction=o),n._super(e)}})}),r(Nt,[st],function(e){return e.extend({recalc:function(e){var t=e.layoutRect(),n=e.paddingBox;e.items().filter(":visible").each(function(e){e.layoutRect({x:n.left,y:n.top,w:t.innerW-n.right-n.left,h:t.innerH-n.top-n.bottom}),e.recalc&&e.recalc()})}})}),r(Et,[st],function(e){return e.extend({recalc:function(e){var t,n,r,i,o,a,s,l,c,u,d,f,h,p,m,g,v=[],y,b,C,x,w,N,E,_,S,k,T,R,A,B,D,M,L,P,H,O,I,F,z=Math.max,W=Math.min;for(r=e.items().filter(":visible"),i=e.layoutRect(),o=e.paddingBox,a=e.settings,f=e.isRtl()?a.direction||"row-reversed":a.direction,s=a.align,l=e.isRtl()?a.pack||"end":a.pack,c=a.spacing||0,("row-reversed"==f||"column-reverse"==f)&&(r=r.set(r.toArray().reverse()),f=f.split("-")[0]),"column"==f?(S="y",E="h",_="minH",k="maxH",R="innerH",T="top",A="deltaH",B="contentH",H="left",L="w",D="x",M="innerW",P="minW",O="right",I="deltaW",F="contentW"):(S="x",E="w",_="minW",k="maxW",R="innerW",T="left",A="deltaW",B="contentW",H="top",L="h",D="y",M="innerH",P="minH",O="bottom",I="deltaH",F="contentH"),d=i[R]-o[T]-o[T],N=u=0,t=0,n=r.length;n>t;t++)h=r[t],p=h.layoutRect(),m=h.settings,g=m.flex,d-=n-1>t?c:0,g>0&&(u+=g,p[k]&&v.push(h),p.flex=g),d-=p[_],y=o[H]+p[P]+o[O],y>N&&(N=y);if(x={},0>d?x[_]=i[_]-d+i[A]:x[_]=i[R]-d+i[A],x[P]=N+i[I],x[B]=i[R]-d,x[F]=N,x.minW=W(x.minW,i.maxW),x.minH=W(x.minH,i.maxH),x.minW=z(x.minW,i.startMinWidth),x.minH=z(x.minH,i.startMinHeight),!i.autoResize||x.minW==i.minW&&x.minH==i.minH){for(C=d/u,t=0,n=v.length;n>t;t++)h=v[t],p=h.layoutRect(),b=p[k],y=p[_]+p.flex*C,y>b?(d-=p[k]-p[_],u-=p.flex,p.flex=0,p.maxFlexSize=b):p.maxFlexSize=0;for(C=d/u,w=o[T],x={},0===u&&("end"==l?w=d+o[T]:"center"==l?(w=Math.round(i[R]/2-(i[R]-d)/2)+o[T],0>w&&(w=o[T])):"justify"==l&&(w=o[T],c=Math.floor(d/(r.length-1)))),x[D]=o[H],t=0,n=r.length;n>t;t++)h=r[t],p=h.layoutRect(),y=p.maxFlexSize||p[_],"center"===s?x[D]=Math.round(i[M]/2-p[L]/2):"stretch"===s?(x[L]=z(p[P]||0,i[M]-o[H]-o[O]),x[D]=o[H]):"end"===s&&(x[D]=i[M]-p[L]-o.top),p.flex>0&&(y+=p.flex*C),x[E]=y,x[S]=w,h.layoutRect(x),h.recalc&&h.recalc(),w+=y+c}else if(x.w=x.minW,x.h=x.minH,e.layoutRect(x),this.recalc(e),null===e._lastRect){var V=e.parent();V&&(V._lastRect=null,V.recalc())}}})}),r(_t,[at],function(e){return e.extend({Defaults:{containerClass:"flow-layout",controlClass:"flow-layout-item",endClass:"break"},recalc:function(e){e.items().filter(":visible").each(function(e){e.recalc&&e.recalc()})},isNative:function(){return!0}})}),r(St,[he,ke,we,m,Qe,h],function(e,t,n,r,i,o){function a(e){function t(t,n){return function(){var r=this;e.on("nodeChange",function(i){var o=e.formatter,a=null;s(i.parents,function(e){return s(t,function(t){return n?o.matchNode(e,n,{value:t.value})&&(a=t.value):o.matchNode(e,t.value)&&(a=t.value),a?!1:void 0}),a?!1:void 0}),r.value(a)})}}function r(e){e=e.replace(/;$/,"").split(";");for(var t=e.length;t--;)e[t]=e[t].split("=");return e}function i(){function t(e){var n=[];if(e)return s(e,function(e){var o={text:e.title,icon:e.icon};if(e.items)o.menu=t(e.items);else{var a=e.format||"custom"+r++;e.format||(e.name=a,i.push(e)),o.format=a,o.cmd=e.cmd}n.push(o)}),n}function n(){var n;return n=t(e.settings.style_formats_merge?e.settings.style_formats?o.concat(e.settings.style_formats):o:e.settings.style_formats||o)}var r=0,i=[],o=[{title:"Headings",items:[{title:"Heading 1",format:"h1"},{title:"Heading 2",format:"h2"},{title:"Heading 3",format:"h3"},{title:"Heading 4",format:"h4"},{title:"Heading 5",format:"h5"},{title:"Heading 6",format:"h6"}]},{title:"Inline",items:[{title:"Bold",icon:"bold",format:"bold"},{title:"Italic",icon:"italic",format:"italic"},{title:"Underline",icon:"underline",format:"underline"},{title:"Strikethrough",icon:"strikethrough",format:"strikethrough"},{title:"Superscript",icon:"superscript",format:"superscript"},{title:"Subscript",icon:"subscript",format:"subscript"},{title:"Code",icon:"code",format:"code"}]},{title:"Blocks",items:[{title:"Paragraph",format:"p"},{title:"Blockquote",format:"blockquote"},{title:"Div",format:"div"},{title:"Pre",format:"pre"}]},{title:"Alignment",items:[{title:"Left",icon:"alignleft",format:"alignleft"},{title:"Center",icon:"aligncenter",format:"aligncenter"},{title:"Right",icon:"alignright",format:"alignright"},{title:"Justify",icon:"alignjustify",format:"alignjustify"}]}];return e.on("init",function(){s(i,function(t){e.formatter.register(t.name,t)})}),{type:"menu",items:n(),onPostRender:function(t){e.fire("renderFormatsMenu",{control:t.control})},itemDefaults:{preview:!0,textStyle:function(){return this.settings.format?e.formatter.getCssText(this.settings.format):void 0},onPostRender:function(){var t=this;t.parent().on("show",function(){var n,r;n=t.settings.format,n&&(t.disabled(!e.formatter.canApply(n)),t.active(e.formatter.match(n))),r=t.settings.cmd,r&&t.active(e.queryCommandState(r))})},onclick:function(){this.settings.format&&c(this.settings.format),this.settings.cmd&&e.execCommand(this.settings.cmd)}}}}function o(t){return function(){var n=this;e.formatter?e.formatter.formatChanged(t,function(e){n.active(e)}):e.on("init",function(){e.formatter.formatChanged(t,function(e){n.active(e)})})}}function a(t){return function(){function n(){return e.undoManager?e.undoManager[t]():!1}var r=this;t="redo"==t?"hasRedo":"hasUndo",r.disabled(!n()),e.on("Undo Redo AddUndo TypingUndo ClearUndos SwitchMode",function(){r.disabled(e.readonly||!n())})}}function l(){var t=this;e.on("VisualAid",function(e){t.active(e.hasVisual)}),t.active(e.hasVisual)}function c(t){t.control&&(t=t.control.value()),t&&e.execCommand("mceToggleFormat",!1,t)}var u;u=i(),s({bold:"Bold",italic:"Italic",underline:"Underline",strikethrough:"Strikethrough",subscript:"Subscript",superscript:"Superscript"},function(t,n){e.addButton(n,{tooltip:t,onPostRender:o(n),onclick:function(){c(n)}})}),s({outdent:["Decrease indent","Outdent"],indent:["Increase indent","Indent"],cut:["Cut","Cut"],copy:["Copy","Copy"],paste:["Paste","Paste"],help:["Help","mceHelp"],selectall:["Select all","SelectAll"],removeformat:["Clear formatting","RemoveFormat"],visualaid:["Visual aids","mceToggleVisualAid"],newdocument:["New document","mceNewDocument"]},function(t,n){e.addButton(n,{tooltip:t[0],cmd:t[1]})}),s({blockquote:["Blockquote","mceBlockQuote"],numlist:["Numbered list","InsertOrderedList"],bullist:["Bullet list","InsertUnorderedList"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],alignleft:["Align left","JustifyLeft"],aligncenter:["Align center","JustifyCenter"],alignright:["Align right","JustifyRight"],alignjustify:["Justify","JustifyFull"],alignnone:["No alignment","JustifyNone"]},function(t,n){e.addButton(n,{tooltip:t[0],cmd:t[1],onPostRender:o(n)})}),e.addButton("undo",{tooltip:"Undo",onPostRender:a("undo"),cmd:"undo"}),e.addButton("redo",{tooltip:"Redo",onPostRender:a("redo"),cmd:"redo"}),e.addMenuItem("newdocument",{text:"New document",icon:"newdocument",cmd:"mceNewDocument"}),e.addMenuItem("undo",{text:"Undo",icon:"undo",shortcut:"Meta+Z",onPostRender:a("undo"),cmd:"undo"}),e.addMenuItem("redo",{text:"Redo",icon:"redo",shortcut:"Meta+Y",onPostRender:a("redo"),cmd:"redo"}),e.addMenuItem("visualaid",{text:"Visual aids",selectable:!0,onPostRender:l,cmd:"mceToggleVisualAid"}),e.addButton("remove",{tooltip:"Remove",icon:"remove",cmd:"Delete"}),s({cut:["Cut","Cut","Meta+X"],copy:["Copy","Copy","Meta+C"],paste:["Paste","Paste","Meta+V"],selectall:["Select all","SelectAll","Meta+A"],bold:["Bold","Bold","Meta+B"],italic:["Italic","Italic","Meta+I"],underline:["Underline","Underline"],strikethrough:["Strikethrough","Strikethrough"],subscript:["Subscript","Subscript"],superscript:["Superscript","Superscript"],removeformat:["Clear formatting","RemoveFormat"]},function(t,n){e.addMenuItem(n,{text:t[0],icon:n,shortcut:t[2],cmd:t[1]})}),e.on("mousedown",function(){n.hideAll()}),e.addButton("styleselect",{type:"menubutton",text:"Formats",menu:u}),e.addButton("formatselect",function(){var n=[],i=r(e.settings.block_formats||"Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6;Preformatted=pre");return s(i,function(t){n.push({text:t[0],value:t[1],textStyle:function(){return e.formatter.getCssText(t[1])}})}),{type:"listbox",text:i[0][0],values:n,fixedWidth:!0,onselect:c,onPostRender:t(n)}}),e.addButton("fontselect",function(){var n="Andale Mono=andale mono,monospace;Arial=arial,helvetica,sans-serif;Arial Black=arial black,sans-serif;Book Antiqua=book antiqua,palatino,serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,palatino,serif;Helvetica=helvetica,arial,sans-serif;Impact=impact,sans-serif;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco,monospace;Times New Roman=times new roman,times,serif;Trebuchet MS=trebuchet ms,geneva,sans-serif;Verdana=verdana,geneva,sans-serif;Webdings=webdings;Wingdings=wingdings,zapf dingbats",i=[],o=r(e.settings.font_formats||n);return s(o,function(e){i.push({text:{raw:e[0]},value:e[1],textStyle:-1==e[1].indexOf("dings")?"font-family:"+e[1]:""})}),{type:"listbox",text:"Font Family",tooltip:"Font Family",values:i,fixedWidth:!0,onPostRender:t(i,"fontname"),onselect:function(t){t.control.settings.value&&e.execCommand("FontName",!1,t.control.settings.value)}}}),e.addButton("fontsizeselect",function(){var n=[],r="8pt 10pt 12pt 14pt 18pt 24pt 36pt",i=e.settings.fontsize_formats||r;return s(i.split(" "),function(e){var t=e,r=e,i=e.split("=");i.length>1&&(t=i[0],r=i[1]),n.push({text:t,value:r})}),{type:"listbox",text:"Font Sizes",tooltip:"Font Sizes",values:n,fixedWidth:!0,onPostRender:t(n,"fontsize"),onclick:function(t){t.control.settings.value&&e.execCommand("FontSize",!1,t.control.settings.value)}}}),e.addMenuItem("formats",{text:"Formats",menu:u})}var s=r.each;i.on("AddEditor",function(t){t.editor.rtl&&(e.rtl=!0),a(t.editor)}),e.translate=function(e){return i.translate(e)},t.tooltips=!o.iOS}),r(kt,[st],function(e){return e.extend({recalc:function(e){var t,n,r,i,o,a,s,l,c,u,d,f,h,p,m,g,v,y,b,C,x,w,N,E=[],_=[],S,k,T,R,A,B;t=e.settings,i=e.items().filter(":visible"),o=e.layoutRect(),r=t.columns||Math.ceil(Math.sqrt(i.length)),n=Math.ceil(i.length/r),y=t.spacingH||t.spacing||0,b=t.spacingV||t.spacing||0,C=t.alignH||t.align,x=t.alignV||t.align,g=e.paddingBox,A="reverseRows"in t?t.reverseRows:e.isRtl(),C&&"string"==typeof C&&(C=[C]),x&&"string"==typeof x&&(x=[x]);for(d=0;r>d;d++)E.push(0);for(f=0;n>f;f++)_.push(0);for(f=0;n>f;f++)for(d=0;r>d&&(u=i[f*r+d],u);d++)c=u.layoutRect(),S=c.minW,k=c.minH,E[d]=S>E[d]?S:E[d],_[f]=k>_[f]?k:_[f];for(T=o.innerW-g.left-g.right,w=0,d=0;r>d;d++)w+=E[d]+(d>0?y:0),T-=(d>0?y:0)+E[d];for(R=o.innerH-g.top-g.bottom,N=0,f=0;n>f;f++)N+=_[f]+(f>0?b:0),R-=(f>0?b:0)+_[f];if(w+=g.left+g.right,N+=g.top+g.bottom,l={},l.minW=w+(o.w-o.innerW),l.minH=N+(o.h-o.innerH),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH,l.minW=Math.min(l.minW,o.maxW),l.minH=Math.min(l.minH,o.maxH),l.minW=Math.max(l.minW,o.startMinWidth),l.minH=Math.max(l.minH,o.startMinHeight),!o.autoResize||l.minW==o.minW&&l.minH==o.minH){o.autoResize&&(l=e.layoutRect(l),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH);var D;D="start"==t.packV?0:R>0?Math.floor(R/n):0;var M=0,L=t.flexWidths;if(L)for(d=0;dd;d++)E[d]+=L?L[d]*P:P;for(p=g.top,f=0;n>f;f++){for(h=g.left,s=_[f]+D,d=0;r>d&&(B=A?f*r+r-1-d:f*r+d,u=i[B],u);d++)m=u.settings,c=u.layoutRect(),a=Math.max(E[d],c.startMinWidth),c.x=h,c.y=p,v=m.alignH||(C?C[d]||C[0]:null),"center"==v?c.x=h+a/2-c.w/2:"right"==v?c.x=h+a-c.w:"stretch"==v&&(c.w=a),v=m.alignV||(x?x[d]||x[0]:null),"center"==v?c.y=p+s/2-c.h/2:"bottom"==v?c.y=p+s-c.h:"stretch"==v&&(c.h=s),u.layoutRect(c),h+=a+y,u.recalc&&u.recalc();p+=s+b}}else if(l.w=l.minW,l.h=l.minH,e.layoutRect(l),this.recalc(e),null===e._lastRect){var H=e.parent();H&&(H._lastRect=null,H.recalc())}}})}),r(Tt,[ke,u],function(e,t){return e.extend({renderHtml:function(){var e=this;return e.classes.add("iframe"),e.canFocus=!1,''},src:function(e){this.getEl().src=e},html:function(e,n){var r=this,i=this.getEl().contentWindow.document.body;return i?(i.innerHTML=e,n&&n()):t.setTimeout(function(){r.html(e)}),this}})}),r(Rt,[ke,ce],function(e,t){return e.extend({init:function(e){var t=this;t._super(e),t.classes.add("widget").add("label"),t.canFocus=!1,e.multiline&&t.classes.add("autoscroll"),e.strong&&t.classes.add("strong")},initLayoutRect:function(){var e=this,n=e._super();if(e.settings.multiline){var r=t.getSize(e.getEl());r.width>n.maxW&&(n.minW=n.maxW,e.classes.add("multiline")),e.getEl().style.width=n.minW+"px",n.startMinH=n.h=n.minH=Math.min(n.maxH,t.getSize(e.getEl()).height)}return n},repaint:function(){var e=this;return e.settings.multiline||(e.getEl().style.lineHeight=e.layoutRect().h+"px"),e._super()},renderHtml:function(){var e=this,t=e.settings.forId;return'"},bindStates:function(){var e=this;return e.state.on("change:text",function(t){e.innerHtml(e.encode(t.value))}),e._super()}})}),r(At,[ge],function(e){return e.extend({Defaults:{role:"toolbar",layout:"flow"},init:function(e){var t=this;t._super(e),t.classes.add("toolbar")},postRender:function(){var e=this;return e.items().each(function(e){e.classes.add("toolbar-item")}),e._super()}})}),r(Bt,[At],function(e){return e.extend({Defaults:{role:"menubar",containerCls:"menubar",ariaRoot:!0,defaults:{type:"menubutton"}}})}),r(Dt,[lt,pe,Bt],function(e,t,n){function r(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1}var i=e.extend({init:function(e){var t=this;t._renderOpen=!0,t._super(e),e=t.settings,t.classes.add("menubtn"),e.fixedWidth&&t.classes.add("fixed-width"),t.aria("haspopup",!0),t.state.set("menu",e.menu||t.render())},showMenu:function(){var e=this,n;return e.menu&&e.menu.visible()?e.hideMenu():(e.menu||(n=e.state.get("menu")||[],n.length?n={type:"menu",items:n}:n.type=n.type||"menu",n.renderTo?e.menu=n.parent(e).show().renderTo():e.menu=t.create(n).parent(e).renderTo(),e.fire("createmenu"),e.menu.reflow(),e.menu.on("cancel",function(t){t.control.parent()===e.menu&&(t.stopPropagation(),e.focus(),e.hideMenu())}),e.menu.on("select",function(){e.focus()}),e.menu.on("show hide",function(t){t.control==e.menu&&e.activeMenu("show"==t.type),e.aria("expanded","show"==t.type)}).fire("show")),e.menu.show(),e.menu.layoutRect({w:e.layoutRect().w}),void e.menu.moveRel(e.getEl(),e.isRtl()?["br-tr","tr-br"]:["bl-tl","tl-bl"]))},hideMenu:function(){var e=this;e.menu&&(e.menu.items().each(function(e){e.hideMenu&&e.hideMenu()}),e.menu.hide())},activeMenu:function(e){this.classes.toggle("active",e)},renderHtml:function(){var e=this,t=e._id,r=e.classPrefix,i=e.settings.icon,o,a=e.state.get("text"),s="";return o=e.settings.image,o?(i="none","string"!=typeof o&&(o=window.getSelection?o[0]:o[1]),o=" style=\"background-image: url('"+o+"')\""):o="",a&&(e.classes.add("btn-has-text"),s=''+e.encode(a)+""),i=e.settings.icon?r+"ico "+r+"i-"+i:"",e.aria("role",e.parent()instanceof n?"menuitem":"button"),'
    '},postRender:function(){var e=this;return e.on("click",function(t){t.control===e&&r(t.target,e.getEl())&&(e.showMenu(),t.aria&&e.menu.items()[0].focus())}),e.on("mouseenter",function(t){var n=t.control,r=e.parent(),o;n&&r&&n instanceof i&&n.parent()==r&&(r.items().filter("MenuButton").each(function(e){e.hideMenu&&e!=n&&(e.menu&&e.menu.visible()&&(o=!0),e.hideMenu())}),o&&(n.focus(),n.showMenu()))}),e._super()},bindStates:function(){var e=this;return e.state.on("change:menu",function(){e.menu&&e.menu.remove(),e.menu=null}),e._super()},remove:function(){this._super(),this.menu&&this.menu.remove()}});return i}),r(Mt,[ke,pe,h],function(e,t,n){return e.extend({Defaults:{border:0,role:"menuitem"},init:function(e){var t=this,n;t._super(e),e=t.settings,t.classes.add("menu-item"),e.menu&&t.classes.add("menu-item-expand"),e.preview&&t.classes.add("menu-item-preview"),n=t.state.get("text"),("-"===n||"|"===n)&&(t.classes.add("menu-item-sep"),t.aria("role","separator"),t.state.set("text","-")),e.selectable&&(t.aria("role","menuitemcheckbox"),t.classes.add("menu-item-checkbox"),e.icon="selected"),e.preview||e.selectable||t.classes.add("menu-item-normal"),t.on("mousedown",function(e){e.preventDefault()}),e.menu&&!e.ariaHideMenu&&t.aria("haspopup",!0)},hasMenus:function(){return!!this.settings.menu},showMenu:function(){var e=this,n=e.settings,r,i=e.parent();if(i.items().each(function(t){t!==e&&t.hideMenu()}),n.menu){r=e.menu,r?r.show():(r=n.menu,r.length?r={type:"menu",items:r}:r.type=r.type||"menu",i.settings.itemDefaults&&(r.itemDefaults=i.settings.itemDefaults),r=e.menu=t.create(r).parent(e).renderTo(),r.reflow(),r.on("cancel",function(t){t.stopPropagation(), +e.focus(),r.hide()}),r.on("show hide",function(e){e.control.items().each(function(e){e.active(e.settings.selected)})}).fire("show"),r.on("hide",function(t){t.control===r&&e.classes.remove("selected")}),r.submenu=!0),r._parentMenu=i,r.classes.add("menu-sub");var o=r.testMoveRel(e.getEl(),e.isRtl()?["tl-tr","bl-br","tr-tl","br-bl"]:["tr-tl","br-bl","tl-tr","bl-br"]);r.moveRel(e.getEl(),o),r.rel=o,o="menu-sub-"+o,r.classes.remove(r._lastRel).add(o),r._lastRel=o,e.classes.add("selected"),e.aria("expanded",!0)}},hideMenu:function(){var e=this;return e.menu&&(e.menu.items().each(function(e){e.hideMenu&&e.hideMenu()}),e.menu.hide(),e.aria("expanded",!1)),e},renderHtml:function(){function e(e){var t,r,i={};for(i=n.mac?{alt:"⌥",ctrl:"⌘",shift:"⇧",meta:"⌘"}:{meta:"Ctrl"},e=e.split("+"),t=0;t'+("-"!==a?'\xa0":"")+("-"!==a?''+a+"":"")+(c?'
    '+c+"
    ":"")+(i.menu?'
    ':"")+"
    "},postRender:function(){var e=this,t=e.settings,n=t.textStyle;if("function"==typeof n&&(n=n.call(this)),n){var r=e.getEl("text");r&&r.setAttribute("style",n)}return e.on("mouseenter click",function(n){n.control===e&&(t.menu||"click"!==n.type?(e.showMenu(),n.aria&&e.menu.focus(!0)):(e.fire("select"),e.parent().hideAll()))}),e._super(),e},active:function(e){return"undefined"!=typeof e&&this.aria("checked",e),this._super(e)},remove:function(){this._super(),this.menu&&this.menu.remove()}})}),r(Lt,[we,Mt,m],function(e,t,n){return e.extend({Defaults:{defaultType:"menuitem",border:1,layout:"stack",role:"application",bodyRole:"menu",ariaRoot:!0},init:function(e){var t=this;if(e.autohide=!0,e.constrainToViewport=!0,e.itemDefaults)for(var r=e.items,i=r.length;i--;)r[i]=n.extend({},e.itemDefaults,r[i]);t._super(e),t.classes.add("menu")},repaint:function(){return this.classes.toggle("menu-align",!0),this._super(),this.getEl().style.height="",this.getEl("body").style.height="",this},cancel:function(){var e=this;e.hideAll(),e.fire("select")},hideAll:function(){var e=this;return this.find("menuitem").exec("hideMenu"),e._super()},preRender:function(){var e=this;return e.items().each(function(t){var n=t.settings;return n.icon||n.image||n.selectable?(e._hasIcons=!0,!1):void 0}),e._super()}})}),r(Pt,[Dt,Lt],function(e,t){return e.extend({init:function(e){function t(r){for(var a=0;a0&&(o=r[0].text,n.state.set("value",r[0].value)),n.state.set("menu",r)),n.state.set("text",e.text||o),n.classes.add("listbox"),n.on("select",function(t){var r=t.control;a&&(t.lastControl=a),e.multiple?r.active(!r.active()):n.value(t.control.value()),a=r})},bindStates:function(){function e(e,n){e instanceof t&&e.items().each(function(e){e.hasMenus()||e.active(e.value()===n)})}function n(e,t){var r;if(e)for(var i=0;i'},postRender:function(){var e=this;e._super(),e.resizeDragHelper=new t(this._id,{start:function(){e.fire("ResizeStart")},drag:function(t){"both"!=e.settings.direction&&(t.deltaX=0),e.fire("Resize",t)},stop:function(){e.fire("ResizeEnd")}})},remove:function(){return this.resizeDragHelper&&this.resizeDragHelper.destroy(),this._super()}})}),r(It,[ke],function(e){function t(e){var t="";if(e)for(var n=0;n'+e[n]+"";return t}return e.extend({Defaults:{classes:"selectbox",role:"selectbox",options:[]},init:function(e){var t=this;t._super(e),t.settings.size&&(t.size=t.settings.size),t.settings.options&&(t._options=t.settings.options)},options:function(e){return arguments.length?(this.state.set("options",e),this):this.state.get("options")},renderHtml:function(){var e=this,n,r="";return n=t(e._options),e.size&&(r=' size = "'+e.size+'"'),'"},bindStates:function(){var e=this;return e.state.on("change:options",function(n){e.getEl().innerHTML=t(n.value)}),e._super()}})}),r(Ft,[ke,ve,ce],function(e,t,n){function r(e,t,n){return t>e&&(e=t),e>n&&(e=n),e}function i(e,t){var r,i,o,a,s;"v"==e.settings.orientation?(a="top",o="height",i="h"):(a="left",o="width",i="w"),r=(e.layoutRect()[i]||100)-n.getSize(e.getEl("handle"))[o],s=r*((t-e._minValue)/(e._maxValue-e._minValue))+"px",e.getEl("handle").style[a]=s,e.getEl("handle").style.height=e.layoutRect().h+"px"}return e.extend({init:function(e){var t=this;e.previewFilter||(e.previewFilter=function(e){return Math.round(100*e)/100}),t._super(e),t.classes.add("slider"),"v"==e.orientation&&t.classes.add("vertical"),t._minValue=e.minValue||0,t._maxValue=e.maxValue||100,t._initValue=t.state.get("value")},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix;return'
    '},reset:function(){this.value(this._initValue).repaint()},postRender:function(){var e=this,i,o,a=0,s,l,c,u,d,f,h,p;l=e._minValue,c=e._maxValue,s=e.value(),"v"==e.settings.orientation?(d="screenY",f="top",h="height",p="h"):(d="screenX",f="left",h="width",p="w"),e._super(),e._dragHelper=new t(e._id,{handle:e._id+"-handle",start:function(t){i=t[d],o=parseInt(e.getEl("handle").style[f],10),u=(e.layoutRect()[p]||100)-n.getSize(e.getEl("handle"))[h],e.fire("dragstart",{value:s})},drag:function(t){var n=t[d]-i,h=e.getEl("handle");a=r(o+n,0,u),h.style[f]=a+"px",s=l+a/u*(c-l),e.value(s),e.tooltip().text(""+e.settings.previewFilter(s)).show().moveRel(h,"bc tc"),e.fire("drag",{value:s})},stop:function(){e.tooltip().hide(),e.fire("dragend",{value:s})}})},repaint:function(){this._super(),i(this,this.value())},bindStates:function(){var e=this;return e.state.on("change:value",function(t){i(e,t.value)}),e._super()}})}),r(zt,[ke],function(e){return e.extend({renderHtml:function(){var e=this;return e.classes.add("spacer"),e.canFocus=!1,'
    '}})}),r(Wt,[Dt,ce,g],function(e,t,n){return e.extend({Defaults:{classes:"widget btn splitbtn",role:"button"},repaint:function(){var e=this,r=e.getEl(),i=e.layoutRect(),o,a;return e._super(),o=r.firstChild,a=r.lastChild,n(o).css({width:i.w-t.getSize(a).width,height:i.h-2}),n(a).css({height:i.h-2}),e},activeMenu:function(e){var t=this;n(t.getEl().lastChild).toggleClass(t.classPrefix+"active",e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r,i=e.state.get("icon"),o=e.state.get("text"),a="";return r=e.settings.image,r?(i="none","string"!=typeof r&&(r=window.getSelection?r[0]:r[1]),r=" style=\"background-image: url('"+r+"')\""):r="",i=e.settings.icon?n+"ico "+n+"i-"+i:"",o&&(e.classes.add("btn-has-text"),a=''+e.encode(o)+""),'
    '},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(e){var n=e.target;if(e.control==this)for(;n;){if(e.aria&&"down"!=e.aria.key||"BUTTON"==n.nodeName&&-1==n.className.indexOf("open"))return e.stopImmediatePropagation(),void(t&&t.call(this,e));n=n.parentNode}}),delete e.settings.onclick,e._super()}})}),r(Vt,[_t],function(e){return e.extend({Defaults:{containerClass:"stack-layout",controlClass:"stack-layout-item",endClass:"break"},isNative:function(){return!0}})}),r(Ut,[be,g,ce],function(e,t,n){return e.extend({Defaults:{layout:"absolute",defaults:{type:"panel"}},activateTab:function(e){var n;this.activeTabId&&(n=this.getEl(this.activeTabId),t(n).removeClass(this.classPrefix+"active"),n.setAttribute("aria-selected","false")),this.activeTabId="t"+e,n=this.getEl("t"+e),n.setAttribute("aria-selected","true"),t(n).addClass(this.classPrefix+"active"),this.items()[e].show().fire("showtab"),this.reflow(),this.items().each(function(t,n){e!=n&&t.hide()})},renderHtml:function(){var e=this,t=e._layout,n="",r=e.classPrefix;return e.preRender(),t.preRender(e),e.items().each(function(t,i){var o=e._id+"-t"+i;t.aria("role","tabpanel"),t.aria("labelledby",o),n+='"}),'
    '+n+'
    '+t.renderHtml(e)+"
    "},postRender:function(){var e=this;e._super(),e.settings.activeTab=e.settings.activeTab||0,e.activateTab(e.settings.activeTab),this.on("click",function(t){var n=t.target.parentNode;if(t.target.parentNode.id==e._id+"-head")for(var r=n.childNodes.length;r--;)n.childNodes[r]==t.target&&e.activateTab(r)})},initLayoutRect:function(){var e=this,t,r,i;r=n.getSize(e.getEl("head")).width,r=0>r?0:r,i=0,e.items().each(function(e){r=Math.max(r,e.layoutRect().minW),i=Math.max(i,e.layoutRect().minH)}),e.items().each(function(e){e.settings.x=0,e.settings.y=0,e.settings.w=r,e.settings.h=i,e.layoutRect({x:0,y:0,w:r,h:i})});var o=n.getSize(e.getEl("head")).height;return e.settings.minWidth=r,e.settings.minHeight=i+o,t=e._super(),t.deltaH+=o,t.innerH=t.h-t.deltaH,t}})}),r($t,[ke],function(e){return e.extend({init:function(e){var t=this;t._super(e),t.classes.add("textbox"),e.multiline?t.classes.add("multiline"):(t.on("keydown",function(e){var n;13==e.keyCode&&(e.preventDefault(),t.parents().reverse().each(function(e){return e.toJSON?(n=e,!1):void 0}),t.fire("submit",{data:n.toJSON()}))}),t.on("keyup",function(e){t.state.set("value",e.target.value)}))},repaint:function(){var e=this,t,n,r,i,o=0,a;t=e.getEl().style,n=e._layoutRect,a=e._lastRepaintRect||{};var s=document;return!e.settings.multiline&&s.all&&(!s.documentMode||s.documentMode<=8)&&(t.lineHeight=n.h-o+"px"),r=e.borderBox,i=r.left+r.right+8,o=r.top+r.bottom+(e.settings.multiline?8:0),n.x!==a.x&&(t.left=n.x+"px",a.x=n.x),n.y!==a.y&&(t.top=n.y+"px",a.y=n.y),n.w!==a.w&&(t.width=n.w-i+"px",a.w=n.w),n.h!==a.h&&(t.height=n.h-o+"px",a.h=n.h),e._lastRepaintRect=a,e.fire("repaint",{},!1),e},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.encode(e.state.get("value"),!1),i="";return"spellcheck"in n&&(i+=' spellcheck="'+n.spellcheck+'"'),n.maxLength&&(i+=' maxlength="'+n.maxLength+'"'),n.size&&(i+=' size="'+n.size+'"'),n.subtype&&(i+=' type="'+n.subtype+'"'),e.disabled()&&(i+=' disabled="disabled"'),n.multiline?'":'"},value:function(e){return arguments.length?(this.state.set("value",e),this):(this.state.get("rendered")&&this.state.set("value",this.getEl().value),this.state.get("value"))},postRender:function(){var e=this;e._super(),e.$el.on("change",function(t){e.state.set("value",t.target.value),e.fire("change",t)})},bindStates:function(){var e=this;return e.state.on("change:value",function(t){e.getEl().value!=t.value&&(e.getEl().value=t.value)}),e.state.on("change:disabled",function(t){e.getEl().disabled=t.value}),e._super()},remove:function(){this.$el.off(),this._super()}})}),r(qt,[g,he,u],function(e,t,n){return function(r,i){var o=this,a,s=t.classPrefix;o.show=function(t,l){return o.hide(),a=!0,n.setTimeout(function(){a&&(e(r).append('
    '),l&&l())},t),o},o.hide=function(){var e=r.lastChild;return e&&-1!=e.className.indexOf("throbber")&&e.parentNode.removeChild(e),a=!1,o}}}),a([l,c,u,d,f,h,m,g,v,y,C,w,N,E,T,A,B,D,M,L,P,H,I,F,j,Y,G,J,ee,te,ne,re,oe,se,le,fe,he,pe,me,ge,ve,ye,be,Ce,xe,we,Ne,Ee,_e,Se,ke,Te,Re,Ae,Me,Pe,Ke,Ge,Je,Qe,et,tt,nt,rt,it,ot,at,st,lt,ct,ut,dt,ft,ht,pt,mt,gt,vt,yt,bt,Ct,xt,wt,Nt,Et,_t,St,kt,Tt,Rt,At,Bt,Dt,Mt,Lt,Pt,Ht,Ot,It,Ft,zt,Wt,Vt,Ut,$t,qt])}(this); \ No newline at end of file diff --git a/assets/js/upload.inc.js b/assets/js/upload.inc.js new file mode 100755 index 0000000..ffeffd1 --- /dev/null +++ b/assets/js/upload.inc.js @@ -0,0 +1,142 @@ +UploadAPI = function(uri) { + this.uri=null; + this.fallback_frame_id='upload-api-fallback-frame'; + + if (typeof(uri)!='undefined') + this.uri=uri; +}; + +UploadAPI.prototype.init=function(form) { + if (!this.uri && form.action.length>0) + this.uri=form.action; + else if (!this.uri) + this.uri=window.location.href; + + try { + this.initLevel2(form); + } catch(err) { + this.initFallback(form); + } +}; + +UploadAPI.prototype.initLevel2=function(form) { + var formData=new FormData(form); + var xhr = new XMLHttpRequest(); + xhr.open(form.method,this.uri); + //xhr.setRequestHeader("Content-type", "multipart/form-data"); + xhr.onreadystatechange=this.bind(this.handleState,this,xhr,form); + xhr.upload.onprogress=this.bind(this.handleProgress,this); + + xhr.send(formData); + this.disableForm(form); +}; + +UploadAPI.prototype.initFallback=function(form) { + var frame=null; + try { + frame=document.createElement(''. + '
    ' + ); + + $this->setOnFocusJSCallback( + $this->createJSCallback( + 'desk_call(dash_web_focus, this);' + ) + ); + + $this->setOnBlurJSCallback( + $this->createJSCallback( + 'desk_call(dash_web_blur, this);' + ) + ); + + $this->setOnOpenJSCallback( + $this->createJSCallback( + 'desk_call(dash_web_open, this);' + ) + ); + + $this->addVariables(array( + 'dash_web_home_page_url' => Zira\Helper::url('/',true, true), + 'dash_web_admin_url' => Zira\Helper::url('dash', true, true), + 'dash_web_wnd' => $this->getJSClassName() + )); + + $this->includeJS('dash/web'); + } +} \ No newline at end of file diff --git a/dash/windows/widget.php b/dash/windows/widget.php new file mode 100644 index 0000000..23cdf09 --- /dev/null +++ b/dash/windows/widget.php @@ -0,0 +1,81 @@ +setIconClass(self::$_icon_class); + $this->setTitle(Zira\Locale::t(self::$_title)); + $this->setSidebarEnabled(false); + + $this->setSaveActionEnabled(true); + } + + public function create() { + $this->setOnLoadJSCallback( + $this->createJSCallback( + 'desk_window_form_init(this);' + ) + ); + } + + public function load() { + if (empty($this->item)) { + return array('error' => Zira\Locale::t('An error occurred')); + } + if (!Permission::check(Permission::TO_CHANGE_LAYOUT)) { + return array('error' => Zira\Locale::t('Permission denied')); + } + + $available_widgets = Widgets::getAvailableWidgets(); + $form = new \Dash\Forms\Widget(); + + if (is_numeric($this->item)) { + $widget = new Zira\Models\Widget($this->item); + if (!$widget->loaded() || !array_key_exists($widget->name, $available_widgets)) { + return array('error' => Zira\Locale::t('An error occurred')); + } + if (!$available_widgets[$widget->name]->isEditable()) { + return array('error' => Zira\Locale::t('An error occurred')); + } + $values = $widget->toArray(); + if ($values['category_id']===null) { + $values['category_id'] = -1; + } + + $this->setTitle(Zira\Locale::t('Widget').' - '.Zira\Locale::tm($available_widgets[$widget->name]->getTitle(), $widget->module)); + } else { + if (!array_key_exists($this->item, $available_widgets)) { + return array('error' => Zira\Locale::t('An error occurred')); + } + if (!$available_widgets[$this->item]->isEditable()) { + return array('error' => Zira\Locale::t('An error occurred')); + } + $values = array( + 'id' => $this->item, + 'placeholder' => $available_widgets[$this->item]->getPlaceholder(), + 'category_id' => -1 + ); + + $module = strtolower(substr($this->item, 1, strpos($this->item, '\\', 1)-1)); + $this->setTitle(Zira\Locale::t(self::$_title).' - '.Zira\Locale::tm($available_widgets[$this->item]->getTitle(), $module)); + } + $form->setValues($values); + + $this->setBodyContent($form); + } +} \ No newline at end of file diff --git a/dash/windows/widgets.php b/dash/windows/widgets.php new file mode 100644 index 0000000..0f85bed --- /dev/null +++ b/dash/windows/widgets.php @@ -0,0 +1,224 @@ +setIconClass(self::$_icon_class); + $this->setTitle(Zira\Locale::t(self::$_title)); + $this->setSidebarEnabled(false); + $this->setBodyViewListVertical(true); + } + + public function create() { + $placeholders_menu = array(); + $placeholders = Zira\Models\Widget::getPlaceholders(); + foreach($placeholders as $placeholder_id=>$placeholder_name) { + $placeholders_menu []= $this->createMenuDropdownItem($placeholder_name, 'glyphicon glyphicon-filter', 'desk_call(dash_widgets_placeholders_filter, this, element);', 'placeholders', false, array('placeholder'=>$placeholder_id)); + } + + $this->setMenuItems(array( + $this->createMenuItem(Zira\Locale::t('Actions'), array( + $this->createMenuDropdownItem(Zira\Locale::t('Deactivate'), 'glyphicon glyphicon-minus-sign', 'desk_call(dash_widgets_deactivate, this);', 'delete', true, array('typo'=>'deactivate')), + $this->createMenuDropdownItem(Zira\Locale::t('Activate'), 'glyphicon glyphicon-ok-circle', 'desk_call(dash_widgets_activate, this);', 'delete', true, array('typo'=>'activate')), + $this->createMenuDropdownSeparator(), + $this->createMenuDropdownItem(Zira\Locale::t('Edit'), 'glyphicon glyphicon-pencil', 'desk_call(dash_widgets_edit, this);', 'edit', true, array('typo'=>'edit')), + $this->createMenuDropdownItem(Zira\Locale::t('Copy'), 'glyphicon glyphicon-duplicate', 'desk_call(dash_widgets_copy, this);', 'edit', true, array('typo'=>'copy')), + $this->createMenuDropdownItem($this->_delete_action_text, 'glyphicon glyphicon-remove-circle', 'desk_window_delete_items(this);', 'delete'), + $this->createMenuDropdownSeparator(), + $this->createMenuDropdownItem(Zira\Locale::t('Up'), 'glyphicon glyphicon-triangle-top', 'desk_call(dash_widgets_up, this);', 'edit', true, array('typo'=>'up')), + $this->createMenuDropdownItem(Zira\Locale::t('Down'), 'glyphicon glyphicon-triangle-bottom', 'desk_call(dash_widgets_down, this);', 'edit', true, array('typo'=>'down')) + )), + $this->createMenuItem(Zira\Locale::t('Placeholders'), $placeholders_menu) + )); + + $this->setContextMenuItems(array( + $this->createContextMenuItem(Zira\Locale::t('Deactivate'), 'glyphicon glyphicon-minus-sign', 'desk_call(dash_widgets_deactivate, this);', 'delete', true, array('typo'=>'deactivate')), + $this->createContextMenuItem(Zira\Locale::t('Activate'), 'glyphicon glyphicon-ok-circle', 'desk_call(dash_widgets_activate, this);', 'delete', true, array('typo'=>'activate')), + $this->createContextMenuSeparator(), + $this->createContextMenuItem(Zira\Locale::t('Edit'), 'glyphicon glyphicon-pencil', 'desk_call(dash_widgets_edit, this);', 'edit', true, array('typo'=>'edit')), + $this->createContextMenuItem(Zira\Locale::t('Copy'), 'glyphicon glyphicon-duplicate', 'desk_call(dash_widgets_copy, this);', 'edit', true, array('typo'=>'copy')), + $this->createContextMenuItem($this->_delete_action_text, 'glyphicon glyphicon-remove-circle', 'desk_window_delete_items(this);', 'delete'), + $this->createContextMenuSeparator(), + $this->createContextMenuItem(Zira\Locale::t('Up'), 'glyphicon glyphicon-triangle-top', 'desk_call(dash_widgets_up, this);', 'edit', true, array('typo'=>'up')), + $this->createContextMenuItem(Zira\Locale::t('Down'), 'glyphicon glyphicon-triangle-bottom', 'desk_call(dash_widgets_down, this);', 'edit', true, array('typo'=>'down')) + )); + + $this->setOnSelectJSCallback( + $this->createJSCallback( + 'desk_call(dash_widgets_select, this);' + ) + ); + + $this->addDefaultOnLoadScript( + 'desk_call(dash_widgets_load, this);' + ); + + $this->setOnEditItemJSCallback( + $this->createJSCallback( + 'desk_call(dash_widgets_edit, this);' + ) + ); + + $this->setOnDeleteItemsJSCallback( + $this->createJSCallback( + 'desk_call(dash_widgets_delete, this);' + ) + ); + + $this->setOnOpenJSCallback( + $this->createJSCallback( + 'desk_call(dash_widgets_drag, this);' + ) + ); + + $this->setOnDropJSCallback( + $this->createJSCallback( + 'desk_call(dash_widgets_drop, this, element);' + ) + ); + + $this->setData(array( + 'placeholder' => null + )); + + $this->addVariables(array( + 'dash_widget_status_active_id' => Zira\Models\Widget::STATUS_ACTIVE, + 'dash_widget_status_not_active_id' => Zira\Models\Widget::STATUS_NOT_ACTIVE, + 'dash_widgets_blank_src' => Zira\Helper::imgUrl('blank.png'), + 'dash_widgets_widget_wnd' => Dash::getInstance()->getWindowJSName(Widget::getClass()) + )); + + $this->includeJS('dash/widgets'); + } + + public static function getAvailableModuleWidgets($module) { + $dir = ROOT_DIR . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . 'widgets'; + if (!file_exists($dir) || !is_dir($dir)) return array(); + $widgets = array(); + $d = opendir($dir); + while(($f=readdir($d))!==false) { + if ($f=='.' || $f=='..' || is_dir($dir. DIRECTORY_SEPARATOR . $f)) continue; + if (!preg_match('/^([a-zA-Z0-9]+)\.php$/', $f, $matches)) continue; + $class = '\\'.ucfirst($module).'\\Widgets\\'.ucfirst($matches[1]); + try { + if (class_exists($class)) { + $widget = new $class; + if ($widget instanceof Zira\Widget) { + $widgets [$class]= $widget; + } else { + unset($widget); + } + } + } catch(\Exception $e) { + Zira\Log::exception($e); + } + } + closedir($d); + return $widgets; + } + + public static function getAvailableWidgets() { + $available_widgets = array(); + $active_modules = array_merge(array('zira'),Zira\Config::get('modules')); + foreach ($active_modules as $module) { + $widgets = self::getAvailableModuleWidgets($module); + if (!empty($widgets)) { + $available_widgets = array_merge($available_widgets, $widgets); + } + } + return $available_widgets; + } + + public function load() { + if (!Permission::check(Permission::TO_CHANGE_LAYOUT)) { + return array('error' => Zira\Locale::t('Permission denied')); + } + + $placeholders = Zira\Models\Widget::getPlaceholders(); + $placeholder = Zira\Request::post('placeholder'); + if ($placeholder && !array_key_exists($placeholder, $placeholders)) { + $placeholder = null; + } + + $categories = Zira\Models\Category::getArray(false); + $_categories = array( + -1 => Zira\Locale::t('All pages'), + 0 => Zira\Locale::t('Home page') + ); + $categories = $_categories + $categories; + + $available_widgets = self::getAvailableWidgets(); + + $active_widgets = array(); + $inactive_widgets = array(); + $user_widgets = array(); + $db_widgets = Zira\Models\Widget::getCollection()->order_by('sort_order', 'asc')->get(); + foreach($db_widgets as $widget) { + if (!array_key_exists($widget->name, $available_widgets)) continue; + if ($widget->active == Zira\Models\Widget::STATUS_ACTIVE) { + $active_widgets []= $widget; + } else { + $inactive_widgets []= $widget; + } + $user_widgets []= $widget->name; + } + $other_widgets = array(); + foreach ($available_widgets as $class=>$widget) { + if (in_array($class, $user_widgets)) continue; + $other_widgets [$class]= $widget; + } + $widgets = array_merge($active_widgets, $inactive_widgets); + + $items = array(); + foreach ($widgets as $widget) { + $_widget = $available_widgets[$widget->name]; + if (!$_widget->isEditable()) continue; + if ($placeholder && $widget->placeholder!=$placeholder) continue; + $_widget->setData($widget->params); + $title = Zira\Locale::tm($_widget->getTitle(), $widget->module); + $suffix = ''; + if (!$placeholder) $suffix .= ' - '.$placeholders[$widget->placeholder]; + $category_id = $widget->category_id; + if ($category_id === null) $category_id = -1; + $suffix .= ' - '.$categories[$category_id]; + $items[]=$this->createBodyItem($title, $title.$suffix, Zira\Helper::imgUrl('drag.png'), $widget->id, null, false, array('activated'=>$widget->active,'installed'=>true,'sort_order'=>$widget->sort_order)); + } + foreach ($other_widgets as $class=>$widget) { + if (!$widget->isEditable() || $widget->isDynamic()) continue; + if ($placeholder && $widget->getPlaceholder()!=$placeholder) continue; + $module = strtolower(substr($class, 1, strpos($class, '\\', 1)-1)); + $title = Zira\Locale::tm($widget->getTitle(),$module); + $suffix = ''; + if (!$placeholder) $suffix .= ' - '.$placeholders[$widget->getPlaceholder()]; + $suffix .= ' - '.$categories[-1]; + $items[]=$this->createBodyItem($title, $title.$suffix, Zira\Helper::imgUrl('drag.png'), $class, null, false, array('activated'=>Zira\Models\Widget::STATUS_NOT_ACTIVE,'installed'=>false)); + } + + $this->setBodyItems($items); + + if ($placeholder) { + $this->setTitle(Zira\Locale::t(self::$_title).' - '.$placeholders[$placeholder]); + } else { + $this->setTitle(Zira\Locale::t(self::$_title)); + } + + $this->setData(array( + 'placeholder' => $placeholder + )); + } +} \ No newline at end of file diff --git a/dash/windows/window.php b/dash/windows/window.php new file mode 100644 index 0000000..d1f1af6 --- /dev/null +++ b/dash/windows/window.php @@ -0,0 +1,843 @@ + null, + 'left' => null, + 'right' => null, + 'bottom' => null, + 'width' => null, + 'height' => null, + 'auto' => false, + 'resize' => true, + 'animate' => true, + 'maximized' => false, + 'sidebar' => true, + 'sidebar_width' => null, + 'toolbar' => true, + 'viewSwitcher' => false, + 'bodyViewList' => false, + 'icon_class' => 'glyphicon glyphicon-th-large', + 'title' => null, + 'menuItems' => [], + 'toolbarItems' => [], + 'toolbarContent' => '', + 'sidebarItems' => [], + 'sidebarContent' => '', + 'bodyItems' => [], + 'bodyContent' => '', + 'bodyFullContent' => '', + 'footerContent' => '', + 'contextMenuItems' => [], + 'onOpen' => null, + 'onLoad' => null, + 'onFocus' => null, + 'onSelect' => null, + 'onClose' => null, + 'onBlur' => null, + 'onDrop' => null, + 'onCreateItem' => null, + 'onEditItem' => null, + 'onDeleteItems' => null, + 'onUpdateContent' => null, + 'onSave' => null, + 'onResize' => null, + 'load' => null, + 'data' => null, + 'nocache' => false, + 'singleInstance' => false, + 'help_url' => null + ); + + abstract public function init(); + abstract public function create(); + + public function __construct() { + $this->_js_name = Dash\Dash::getInstance()->getWindowJSName(self::getClass()); + if (empty($this->_js_name)) throw new \Exception('Failed to construct window: ' . self::getClass()); + } + + public function build() { + $this->setDefaultMenuTitle(Locale::t('Actions')); + $this->setCreateActionText(Locale::t('Create')); + $this->setEditActionText(Locale::t('Edit')); + $this->setDeleteActionText(Locale::t('Delete')); + $this->setSaveActionText(Locale::t('Save')); + $this->setAutoSizing(true); + $this->init(); + if (method_exists($this, 'load')) { + $this->setLoadURL(Helper::url('dash/index/load')); + } + if ($this->_save_action_enabled || method_exists($this, 'save')) { + $this->setOnSaveJSCallback( + $this->createJSCallback( + 'var data = desk_window_content(this);'. + 'desk_window_request(this, \''.Helper::url('dash/index/save').'\', data);' + ) + ); + } + if (!empty($this->_options['onSave'])) { + $this->addDefaultMenuDropdownItem( + $this->createMenuDropdownItem($this->_save_action_text, 'glyphicon glyphicon-floppy-disk', 'desk_window_save(this);', 'save') + ); + $this->addDefaultToolbarItem( + $this->createToolbarButton($this->_save_action_text, $this->_save_action_text, 'glyphicon glyphicon-floppy-disk', 'desk_window_save(this);', 'save') + ); + } + if (!empty($this->_create_action_window_class)) { + $this->setOnCreateItemJSCallback( + $this->createJSCallback( + 'var data = {\'onClose\':function(){desk_window_reload_all(\''.$this->getJSClassName().'\');}};'. + Dash\Dash::getInstance()->getWindowJSName($this->_create_action_window_class).'(data);' + ) + ); + } + if (!empty($this->_options['onCreateItem'])) { + $this->addDefaultMenuDropdownItem( + $this->createMenuDropdownItem($this->_create_action_text, 'glyphicon glyphicon-file', 'desk_window_create_item(this);', 'create') + ); + $this->addDefaultContextMenuItem( + $this->createContextMenuItem($this->_create_action_text, 'glyphicon glyphicon-file', 'desk_window_create_item(this);', 'create') + ); + $this->addDefaultSidebarItem( + $this->createSidebarItem($this->_create_action_text, 'glyphicon glyphicon-file', 'desk_window_create_item(this);', 'create') + ); + } + if (!empty($this->_edit_action_window_class)) { + $this->setOnEditItemJSCallback( + $this->createJSCallback( + 'var data = {\'data\':desk_window_selected(this,1),\'onClose\':function(){desk_window_reload_all(\''.$this->getJSClassName().'\');}};'. + Dash\Dash::getInstance()->getWindowJSName($this->_edit_action_window_class).'(data);' + ) + ); + } + if (!empty($this->_options['onEditItem'])) { + $this->addDefaultMenuDropdownItem( + $this->createMenuDropdownItem($this->_edit_action_text, 'glyphicon glyphicon-pencil', 'desk_window_edit_item(this)', 'edit') + ); + $this->addDefaultContextMenuItem( + $this->createContextMenuItem($this->_edit_action_text, 'glyphicon glyphicon-pencil', 'desk_window_edit_item(this)', 'edit') + ); + } + if ($this->_delete_action_enabled || method_exists($this, 'delete')) { + $this->setOnDeleteItemsJSCallback( + $this->createJSCallback( + 'var data = desk_window_selected(this);'. + 'desk_window_request(this, \''.Helper::url('dash/index/delete').'\', data);' + ) + ); + } + if (!empty($this->_options['onDeleteItems'])) { + $this->addDefaultMenuDropdownItem( + $this->createMenuDropdownItem($this->_delete_action_text, 'glyphicon glyphicon-remove-circle', 'desk_window_delete_items(this);', 'delete') + ); + $this->addDefaultContextMenuItem( + $this->createContextMenuItem($this->_delete_action_text, 'glyphicon glyphicon-remove-circle', 'desk_window_delete_items(this);', 'delete') + ); + } + if (property_exists($this, 'search')) { + $this->addDefaultToolbarItem( + $this->createToolbarInput(Locale::t('Search'), Locale::t('Search'), 'glyphicon glyphicon-search', 'var text=$(element).val();desk_window_search(this, text);', 'search') + ); + $this->addDefaultOnLoadScript('desk_window_search_init(this);'); + } + if (method_exists($this, 'load') && $this->_reload_button) { + $this->addDefaultToolbarItem( + $this->createToolbarButton(null, Locale::t('Reload'), 'glyphicon glyphicon-repeat', 'desk_window_reload(this);', 'reload') + ); + } + if (property_exists($this, 'page')) { + $this->addDefaultToolbarItem( + $this->createToolbarButtonGroup(array( + $this->createToolbarButton(null, Locale::t('Previous'), 'glyphicon glyphicon-arrow-left', 'desk_window_pagination_prev(this);', 'pagination-prev', true), + $this->createToolbarButton(null, Locale::t('Next'), 'glyphicon glyphicon-arrow-right', 'desk_window_pagination_next(this);', 'pagination-next', true) + ), true) + ); + $this->addDefaultOnLoadScript('desk_window_pagination_init(this);'); + } + if (property_exists($this, 'order')) { + $this->addDefaultToolbarItem( + $this->createToolbarButtonGroup(array( + $this->createToolbarButton(null, Locale::t('Sort descending'), 'glyphicon glyphicon-sort-by-attributes-alt', 'desk_window_sort_desc(this);', 'order-desc', true), + $this->createToolbarButton(null, Locale::t('Sort ascending'), 'glyphicon glyphicon-sort-by-attributes', 'desk_window_sort_asc(this);', 'order-asc', true) + ), true) + ); + $this->addDefaultOnLoadScript('desk_window_sorter_init(this);'); + } + + $this->create(); + + if (!empty($this->_default_onload_scripts)) { + $this->setOnLoadJSCallback( + $this->createJSCallback( + implode(' ', $this->_default_onload_scripts) + ), + true + ); + } + + if ($this->_options['data']==null) $this->setData(array()); + } + + public static function getParentClass() { + return get_class(); + } + + public static function getClass() { + return get_called_class(); + } + + public function getJSClassName() { + return $this->_js_name; + } + + public function getOptions() { + return $this->_options; + } + + public function resetOptions() { + $this->_options = array(); + } + + public function setDefaultMenuTitle($title) { + $this->_default_menu_title = (string)$title; + } + + public function setDefaultMenu(array $menu) { + $this->_default_menu = $menu; + } + + public function getDefaultMenu() { + return $this->_default_menu; + } + + public function addDefaultMenuItem(array $menuItem) { + $this->_default_menu []= $menuItem; + } + + public function setDefaultMenuDropdown(array $menu) { + $this->_default_menu_dropdown = $menu; + } + + public function getDefaultMenuTitle() { + return $this->_default_menu_title; + } + + public function getDefaultMenuDropdown() { + return $this->_default_menu_dropdown; + } + + public function addDefaultMenuDropdownItem(array $menuItem) { + $this->_default_menu_dropdown []= $menuItem; + } + + public function setDefaultContextMenu(array $menu) { + $this->_default_context_menu = $menu; + } + + public function getDefaultContextMenu() { + return $this->_default_context_menu; + } + + public function addDefaultContextMenuItem(array $menuItem) { + $this->_default_context_menu []= $menuItem; + } + + public function setDefaultToolbar(array $toolbar) { + $this->_default_toolbar = $toolbar; + } + + public function getDefaultToolbar() { + return $this->_default_toolbar; + } + + public function addDefaultToolbarItem(array $toolbarItem) { + $this->_default_toolbar []= $toolbarItem; + } + + public function setDefaultSidebar(array $sidebar) { + $this->_default_sidebar = $sidebar; + } + + public function getDefaultSidebar() { + return $this->_default_sidebar; + } + + public function addDefaultSidebarItem(array $sidebarItem) { + $this->_default_sidebar []= $sidebarItem; + } + + public function setCreateActionText($text) { + $this->_create_action_text = (string)$text; + } + + public function setEditActionText($text) { + $this->_edit_action_text = (string)$text; + } + + public function setDeleteActionText($text) { + $this->_delete_action_text = (string)$text; + } + + public function setSaveActionText($text) { + $this->_save_action_text = (string)$text; + } + + public function setCreateActionWindowClass($class) { + if (!method_exists($class,'getParentClass') || $class::getParentClass()!='Dash\Windows\Window') throw new \Exception('Invalid window class passed'); + $this->_create_action_window_class = $class; + } + + public function setEditActionWindowClass($class) { + if (!method_exists($class,'getParentClass') || $class::getParentClass()!='Dash\Windows\Window') throw new \Exception('Invalid window class passed'); + $this->_edit_action_window_class = $class; + } + + public function setSaveActionEnabled($enabled) { + $this->_save_action_enabled = (bool)$enabled; + } + + public function setDeleteActionEnabled($enabled) { + $this->_delete_action_enabled = (bool)$enabled; + } + + public function addDefaultOnLoadScript($js) { + if (substr($js, -1)!=';') $js.=';'; + $this->_default_onload_scripts[]=$js; + } + + public function getDefaultOnLoadScripts() { + return implode(' ', $this->_default_onload_scripts); + } + + public function setSelectionLinksEnabled($enabled) { + $this->_selection_links = (bool)$enabled; + } + + public static function setCallbackStringMode($mode) { + self::$_callback_string_mode = (bool)$mode; + } + + protected function setOption($name, $value) { + $this->_options[$name] = $value; + } + + public function setTop($value) { + $this->setOption('top', intval($value)); + } + + public function setLeft($value) { + $this->setOption('left', intval($value)); + } + + public function setRight($value) { + $this->setOption('right', intval($value)); + } + + public function setBottom($value) { + $this->setOption('bottom', intval($value)); + } + + public function setWidth($value) { + $this->setOption('width', intval($value)); + } + + public function setHeight($value) { + $this->setOption('height', intval($value)); + } + + public function setAutoSizing($value) { + $this->setOption('auto', boolval($value)); + } + + public function setResizing($value) { + $this->setOption('resize', boolval($value)); + } + + public function setAnimating($value) { + $this->setOption('animate', boolval($value)); + } + + public function setMaximized($value) { + $this->setOption('maximized', boolval($value)); + } + + public function setSidebarEnabled($value) { + $this->setOption('sidebar', boolval($value)); + } + + public function setSidebarWidth($value) { + $this->setOption('sidebar_width', intval($value)); + } + + public function setToolbarEnabled($value) { + $this->setOption('toolbar', boolval($value)); + } + + public function setViewSwitcherEnabled($value) { + $this->setOption('viewSwitcher', boolval($value)); + } + + public function setBodyViewListVertical($value) { + $this->setOption('bodyViewList', boolval($value)); + } + + public function setIconClass($value) { + $this->setOption('icon_class', (string)$value); + } + + public function setTitle($value) { + $this->setOption('title', (string)$value); + } + + public function setMenuItems(array $value) { + $this->setOption('menuItems', $value); + } + + public function setToolbarItems(array $value) { + $this->setOption('toolbarItems', $value); + } + + public function setSidebarItems(array $value) { + $this->setOption('sidebarItems', $value); + } + + public function setBodyItems(array $value) { + $this->setOption('bodyItems', $value); + } + + public function setContextMenuItems(array $value) { + $this->setOption('contextMenuItems', $value); + } + + public function setToolbarContent($value) { + $this->setOption('toolbarContent', (string)$value); + } + + public function setSidebarContent($value) { + $this->setOption('sidebarContent', (string)$value); + } + + public function setBodyContent($value) { + $this->setOption('bodyContent', (string)$value); + } + + public function setBodyFullContent($value) { + $this->setOption('bodyFullContent', (string)$value); + } + + public function setFooterContent($value) { + $this->setOption('footerContent', (string)$value); + } + + public function setOnOpenJSCallback($value) { + $this->setOption('onOpen', (string)$value); + } + + public function setOnLoadJSCallback($value, $force=false) { + if (!$force && (property_exists($this, 'page') || property_exists($this, 'order'))) throw new \Exception('Cannot setOnLoadJSCallback. Use addDefaultOnLoadScript instead.'); + $this->setOption('onLoad', (string)$value); + } + + public function setOnFocusJSCallback($value) { + $this->setOption('onFocus', (string)$value); + } + + public function setOnBlurJSCallback($value) { + $this->setOption('onBlur', (string)$value); + } + + public function setOnSelectJSCallback($value) { + $this->setOption('onSelect', (string)$value); + } + + public function setOnDropJSCallback($value) { + $this->setOption('onDrop', (string)$value); + } + + public function setOnCloseJSCallback($value) { + $this->setOption('onClose', (string)$value); + } + + public function setOnCreateItemJSCallback($value) { + $this->setOption('onCreateItem', (string)$value); + } + + public function setOnEditItemJSCallback($value) { + $this->setOption('onEditItem', (string)$value); + } + + public function setOnDeleteItemsJSCallback($value) { + $this->setOption('onDeleteItems', (string)$value); + } + + public function setOnSaveJSCallback($value) { + $this->setOption('onSave', (string)$value); + } + + public function setOnUpdateContentJSCallback($value) { + $this->setOption('onUpdateContent', (string)$value); + } + + public function setOnResizeJSCallback($value) { + $this->setOption('onResize', (string)$value); + } + + public function setLoadURL($value) { + $this->setOption('load', (string)$value); + } + + public function setData(array $value) { + $value['token'] = Dash\Dash::getToken(); + $this->setOption('data', $value); + } + + public function setNoCache($value) { + $this->setOption('nocache', (bool)$value); + } + + + public function setSingleInstance($value) { + $this->setOption('singleInstance', (bool)$value); + } + + public function setReloadButtonEnabled($reload_button) { + $this->_reload_button = (bool)$reload_button; + } + + public function createJSCallback($js) { + if (empty($js)) return null; + if (self::$_callback_string_mode) { + return $this->createJSCallbackString($js); + } else { + return $this->createJSCallbackFunction($js); + } + } + + public function createJSCallbackFunction($js) { + $js = trim($js); + if (substr($js,-1)!=';') $js .= ';'; + return 'function(element){'.$js.'}'; + } + + public function createJSCallbackString($js) { + $js = trim($js); + if (substr($js,-1)!=';') $js .= ';'; + //return 'new Function(\'element\', \''.$js.'\')'; + return '(function(element){'.$js.'})'; + } + + public function createMenuItem($title, array $dropdownItems) { + return array( + 'title' => (string)$title, + 'items' => $dropdownItems + ); + } + + public function createMenuDropdownItem($title, $icon_class, $js, $action_name=null, $disabled=false, array $extra = array()) { + return array_merge(array( + 'title' => (string)$title, + 'icon_class' => (string)$icon_class, + 'callback' => $this->createJSCallback($js), + 'action' => (string)$action_name, + 'disabled' => (bool)$disabled + ), $extra); + } + + public function createMenuDropdownSeparator() { + return array( + 'type' => 'separator' + ); + } + + public function createContextMenuItem($title, $icon_class, $js, $action_name=null, $disabled=false, array $extra = array()) { + return array_merge(array( + 'title' => (string)$title, + 'icon_class' => (string)$icon_class, + 'callback' => $this->createJSCallback($js), + 'action' => (string)$action_name, + 'disabled' => (bool)$disabled + ), $extra); + } + + public function createContextMenuSeparator() { + return array( + 'type' => 'separator' + ); + } + + public function createToolbarButton($title, $tooltip, $icon_class, $js, $action_name=null, $disabled=false, $align_right=false, array $extra = array()) { + return array_merge(array( + 'title' => (string)$title, + 'tooltip' => (string)$tooltip, + 'icon_class' => (string)$icon_class, + 'align' => $align_right ? 'right' : 'left', + 'callback' => $this->createJSCallback($js), + 'action' => (string)$action_name, + 'disabled' => (bool)$disabled + ), $extra); + } + + public function createToolbarInput($title, $tooltip, $icon_class, $js, $action_name=null, $disabled=false, $align_right=false, array $extra = array()) { + return array_merge(array( + 'type' => 'input', + 'title' => (string)$title, + 'tooltip' => (string)$tooltip, + 'icon_class' => (string)$icon_class, + 'align' => $align_right ? 'right' : 'left', + 'callback' => $this->createJSCallback($js), + 'action' => (string)$action_name, + 'disabled' => (bool)$disabled + ), $extra); + } + + public function createToolbarButtonGroup(array $buttons, $align_right=false, array $extra = array()) { + return array_merge(array( + 'type' => 'button_group', + 'align' => $align_right ? 'right' : 'left', + 'items' => $buttons + ), $extra); + } + + public function createSidebarItem($title, $icon_class, $js, $action_name=null, $disabled=false, array $extra = array()) { + return array_merge(array( + 'title' => (string)$title, + 'icon_class' => (string)$icon_class, + 'callback' => $this->createJSCallback($js), + 'action' => (string)$action_name, + 'disabled' => (bool)$disabled + ), $extra); + } + + public function createSidebarSeparator() { + return array( + 'type' => 'separator' + ); + } + + public function createBodyItem($title, $tooltip, $src, $data=null, $js=null, $disabled=false, array $extra = array()) { + return array_merge(array( + 'title' => (string)$title, + 'tooltip' => (string)$tooltip, + 'src' => (string)$src, + 'callback' => $this->createJSCallback($js), + 'data' => $data, + 'disabled' => (bool)$disabled + ), $extra); + } + + public function createBodyFolderItem($title, $tooltip, $data=null, $js=null, $disabled=false, array $extra = array()) { + return array_merge(array( + 'type' => 'folder', + 'title' => (string)$title, + 'tooltip' => (string)$tooltip, + 'callback' => $this->createJSCallback($js), + 'data' => $data, + 'disabled' => (bool)$disabled + ), $extra); + } + + public function createBodyFileItem($title, $tooltip, $data=null, $js=null, $disabled=false, array $extra = array()) { + return array_merge(array( + 'type' => 'file', + 'title' => (string)$title, + 'tooltip' => (string)$tooltip, + 'callback' => $this->createJSCallback($js), + 'data' => $data, + 'disabled' => (bool)$disabled + ), $extra); + } + + public function createBodyArchiveItem($title, $tooltip, $data=null, $js=null, $disabled=false, array $extra = array()) { + return array_merge(array( + 'type' => 'archive', + 'title' => (string)$title, + 'tooltip' => (string)$tooltip, + 'callback' => $this->createJSCallback($js), + 'data' => $data, + 'disabled' => (bool)$disabled + ), $extra); + } + + public function generateOptions() { + $js = "\t".'{'; + $stack = array(); + $stack_indexes = array(); + $stack_objects = array(); + $stack[]=$this->_options; + $stack_indexes[]=0; + $stack_objects[]=false; + $is_object = false; + while(count($stack)>0) { + $index = count($stack)-1; + $prefix = "\r\n".str_repeat("\t", $index+2); + $total = count($stack[$index]); + $co = 0; + if ($stack_indexes[$index]>0 && $is_object) { + $js .= $prefix.'}'; + } else if ($stack_indexes[$index]>0) { + $js .= $prefix.']'; + } + if ($stack_indexes[$index]>0 && $stack_indexes[$index]<$total) { + $js .= ','; + } + if ($stack_indexes[$index]<$total) { + foreach($stack[$index] as $option_name=>$option_value) { + $co++; + if ($co<=$stack_indexes[$index]) continue; + $js .= $prefix; + if (!is_int($option_name)) { + $js .= "'".$option_name."': "; + if (is_array($option_value)) $js .= $prefix; + } + if (is_array($option_value) && (is_int(key($option_value)) || empty($option_value))) { + $js .= '['; + $is_object = false; + } else if (is_array($option_value)) { + $js .= '{'; + $is_object = true; + } + if (is_array($option_value)) { + $stack_indexes[$index] = $co; + $stack[]=$option_value; + $stack_indexes[]=0; + $stack_objects[]=$is_object; + $co=0; + break; + } else if (is_int($option_value)) { + $js .= $option_value; + } else if (is_bool($option_value)) { + $js .= $option_value ? 'true': 'false'; + } else if (is_null($option_value)) { + $js .= 'null'; + } else { + if ($option_name=='callback' || strpos($option_name,'on')===0) { + $js .= $option_value; + } else { + $js .= "'".$option_value."'"; + } + } + if ($co<$total) $js .= ','; + } + } else { + $co = $total; + } + if ($co==$total) { + array_pop($stack); + array_pop($stack_indexes); + $is_object = array_pop($stack_objects); + } + } + $js .= "\r\n\t".'}'; + $stack = null; + $stack_indexes = null; + $stack_objects = null; + return $js; + } + + public function setExtraJS($js) { + if (substr(trim($js),-1)!=';') $js=trim($js).';'; + $this->_extra_js = $js; + } + + public function addStrings(array $strings) { + foreach($strings as $str) { + Dash\Dash::getInstance()->registerWindowString($str); + } + } + + public function addVariables(array $vars, $once = false) { + foreach($vars as $name=>$val) { + if ($once) { + Dash\Dash::getInstance()->registerWindowVariableOnce($name, $val); + } else { + Dash\Dash::getInstance()->registerWindowVariable($name, $val); + } + } + } + + public function includeJS($path) { + Dash\Dash::getInstance()->registerWindowScript($path); + } + + public function render() { + if (empty($this->_options['menuItems']) && (!empty($this->_default_menu) || !empty($this->_default_menu_dropdown))) { + if (!empty($this->_default_menu_dropdown)) { + $this->addDefaultMenuItem( + $this->createMenuItem($this->_default_menu_title, $this->_default_menu_dropdown) + ); + } + $this->setMenuItems($this->_default_menu); + } + if ($this->_selection_links) { + if (!empty($this->_default_context_menu)) { + $this->addDefaultContextMenuItem( + $this->createContextMenuSeparator() + ); + } + $this->addDefaultContextMenuItem( + $this->createContextMenuItem(Locale::t('Select all'), 'glyphicon glyphicon-ok-sign', 'desk_window_select_items(this);', 'select') + ); + $this->addDefaultContextMenuItem( + $this->createContextMenuItem(Locale::t('Unselect all'), 'glyphicon glyphicon-ok-circle', 'desk_window_unselect_items(this);', 'select') + ); + } + if (empty($this->_options['contextMenuItems']) && !empty($this->_default_context_menu)) { + $this->setContextMenuItems($this->_default_context_menu); + } + if (empty($this->_options['toolbarItems']) && !empty($this->_default_toolbar)) { + $this->setToolbarItems($this->_default_toolbar); + } + if (empty($this->_options['sidebarItems']) && !empty($this->_default_sidebar)) { + $this->setSidebarItems($this->_default_sidebar); + } + if ($this->_help_url) { + $this->setOption('help_url', $this->_help_url); + } + $js = 'var '.$this->getJSClassName().' = function(data) {'."\r\n\t"; + $js .= 'desk_window('.'\''.$this->getJSClassName().'\','."\r\n".$this->generateOptions().', data);'."\r\n"; + $js .= '};'."\r\n"; + $js .= $this->_extra_js; + + return $js; + } + + public function __toString() { + return $this->render(); + } +} \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..63a807a Binary files /dev/null and b/favicon.ico differ diff --git a/htaccess.txt b/htaccess.txt new file mode 100644 index 0000000..f6e08e0 --- /dev/null +++ b/htaccess.txt @@ -0,0 +1,33 @@ +DirectoryIndex index.php index.html + +ErrorDocument 404 /404.html +ErrorDocument 403 /403.html + + + + Require all denied + + + Order deny,allow + Deny from all + + + + +RewriteEngine On +#RewriteBase / + +RewriteRule ^(?:cache|log)\b.* - [R=403,L] + +RewriteCond %{REQUEST_FILENAME} \.php$ +RewriteRule !index\.php.* - [R=403,L] + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule ^assets/css/cache$ assets/css/index.php [L] + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule ^assets/js/cache$ assets/js/index.php [L] + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule .* index.php/$0 [L] + \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..97b818d --- /dev/null +++ b/index.php @@ -0,0 +1,53 @@ +shutdown(); + } else if (isset($error['type']) && $error['type']==E_ERROR) { + // trying to log fatal errors + $message = isset($error['message']) ? $error['message'] : 'unknown error'; + $file = isset($error['file']) ? $error['file'] : 'unknown file'; + $line = isset($error['line']) ? $error['line'] : 'unknown line'; + Zira\Log::write('Fatal error: '.$message.' in '.$file.':'.$line); + } +} +register_shutdown_function('shutdown_handler'); + +spl_autoload_extensions('.php'); +spl_autoload_register(); + +try { + \Zira\Config::setSystemDefaults($config); + unset($config); + Zira::getInstance()->bootstrap(); +} catch (Exception $e) { + Zira\Response::exception($e); +} \ No newline at end of file diff --git a/install/check/index.php b/install/check/index.php new file mode 100644 index 0000000..405d8f1 --- /dev/null +++ b/install/check/index.php @@ -0,0 +1,2 @@ +getToken(), $field); + if (Zira\Request::post($_field)===null && Zira\Session::get($field)) { + Zira\Request::setPost($_field, Zira\Session::get($field)); + } +} + +// checking previous form +if (!$form->isValid()) { + return array( + 'error' => $form->getError() + ); +} else { + // saving form data + foreach($infoFields as $field) { + Zira\Session::set($field, $form->getValue($field)); + } +} + +$form = new \Install\Forms\Configuration(); +$form->setValues(Zira\Session::getArray()); +if (!Zira\Session::get('db_type')) $form->setValue('db_type', 'mysql'); +if (!Zira\Session::get('db_host')) $form->setValue('db_host', 'localhost'); +if (!Zira\Session::get('db_port')) $form->setValue('db_port', '3306'); +if (!Zira\Session::get('db_file')) $form->setValue('db_file', '../zira.db'); +if (!Zira\Session::get('db_prefix')) $form->setValue('db_prefix', 'zira_'); +if (!Zira\Session::get('root_dir')) $form->setValue('root_dir', '.'); +if (!Zira\Session::get('base_url')) { + $uri = trim($_SERVER['REQUEST_URI'],'/'); + $uri = preg_replace('/^([^\?]+).*$/', '$1', $uri); + $uri_parts = explode('/', $uri); + if ($uri_parts[count($uri_parts)-1] == 'index.php') array_pop($uri_parts); + if ($uri_parts[count($uri_parts)-1] == 'install') array_pop($uri_parts); + $base_url = '/' . implode('/', $uri_parts); + $form->setValue('base_url', $base_url); +} + +return array( + 'content' => Zira\Helper::tag('p', Zira\Locale::t('Zira CMS stores data in database. Currently, MySQL 5 and SQLite 3 are supported.')). + (string)$form, + 'script' => 'if (zira_install_clean_url) {'. + '$(\'#zira_install_clean_url_input\').val(1);'. + '} else {'. + '$(\'#zira_install_clean_url_input\').val(0);'. + '}'. + 'zira_install_database_select = function() {'. + 'var zira_init_db_type = $(\'#zira-install-db-type-select\').val();'. + 'if (zira_init_db_type == \'mysql\') {'. + '$(\'#zira-install-mysql-credentials\').show();'. + '$(\'#zira-install-sqlite-credentials\').hide();'. + '} else if (zira_init_db_type == \'sqlite\') {'. + '$(\'#zira-install-mysql-credentials\').hide();'. + '$(\'#zira-install-sqlite-credentials\').show();'. + '}'. + '};'. + 'zira_install_database_select();' +); \ No newline at end of file diff --git a/install/credentials.php b/install/credentials.php new file mode 100644 index 0000000..499dc5f --- /dev/null +++ b/install/credentials.php @@ -0,0 +1,16 @@ +setValues(Zira\Session::getArray()); + +return array( + 'content' => Zira\Helper::tag('p', Zira\Locale::t('Your website must have unique name and slogan!')). + (string)$form +); \ No newline at end of file diff --git a/install/default.php b/install/default.php new file mode 100644 index 0000000..118d7fb --- /dev/null +++ b/install/default.php @@ -0,0 +1,50 @@ + 'UTC', + 'clean_url' => true, + 'language' => 'ru', + 'languages' => array('ru'), + 'detect_language' => false, + 'db_translates' => false, + 'theme' => 'default', + 'layout' => 'layout', + 'modules' => array(), + 'caching' => false, + 'cache_lifetime' => 3600, + 'thumbs_width' => 200, + 'thumbs_height' => 150, + 'watermark_enabled' => false, + 'watermark' => '', + 'use_smtp' => false, + 'smtp_host' => 'smtp.gmail.com', + 'smtp_port' => 587, + 'smtp_secure' => 'tls', + 'smtp_username' => '', + 'smtp_password' => '', + 'email_from' => 'info@'.$_SERVER['HTTP_HOST'], + 'email_from_name' => $_SERVER['HTTP_HOST'], + 'feedback_email' => 'info@'.$_SERVER['HTTP_HOST'], + 'date_format' => 'd.m.Y', + 'datepicker_date_format' => 'DD.MM.YYYY', + 'user_photo_min_width' => 250, + 'user_photo_min_height' => 250, + 'user_photo_max_width' => 700, + 'user_photo_max_height' => 700, + 'user_thumb_width' => 100, + 'user_thumb_height' => 100, + 'gzip' => true, + 'site_name' => 'Zira', + 'site_title' => 'Zira CMS', + 'site_slogan' => '', + 'site_logo' => 'assets/images/zira.png', + 'site_copyright' => '', + 'site_keywords' => '', + 'site_description' => '', + 'site_window_title' => true, + 'config_version' => 1 +); \ No newline at end of file diff --git a/install/environment.php b/install/environment.php new file mode 100644 index 0000000..4607aba --- /dev/null +++ b/install/environment.php @@ -0,0 +1,143 @@ +(floatval($phpversion)>=5.5 ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); + +$pdo_installed = class_exists('PDO'); +if ($pdo_installed) { + $pdo_drivers = \PDO::getAvailableDrivers(); +} else { + $supported = false; +} +$pdo = Zira\Helper::tag('span',null,array('class'=>($pdo_installed ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$pdo .= ' PDO: '.($pdo_installed ? implode(', ',$pdo_drivers) : Zira\Locale::t('not supported')); + +$gdversion = 0; +if (function_exists('gd_info')) { + $gd_info = gd_info(); + $gdversion = $gd_info['GD Version'] ; +} +if (!$gdversion) $supported = false; +$gd = Zira\Helper::tag('span',null,array('class'=>($gdversion ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$gd .= ' GD '.($gdversion ? $gdversion : Zira\Locale::t('not supported')); + +$zip_supported = class_exists('ZipArchive'); +$zip = Zira\Helper::tag('span',null,array('class'=>($zip_supported ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$zip .= ' ZIP '.($zip_supported ? Zira\Locale::t('supported') : Zira\Locale::t('not supported')); + +$gzip_supported = function_exists('gzencode') && !@ini_get('zlib.output_compression'); +$gzip = Zira\Helper::tag('span',null,array('class'=>($gzip_supported ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$gzip .= ' GZIP '.($gzip_supported ? Zira\Locale::t('supported') : Zira\Locale::t('not supported')); + +$openssl_supported = function_exists('openssl_random_pseudo_bytes'); +if (!$openssl_supported) $supported = false; +$openssl = Zira\Helper::tag('span',null,array('class'=>($openssl_supported ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$openssl .= ' OpenSSL '.($openssl_supported ? Zira\Locale::t('supported') : Zira\Locale::t('not supported')); + +$mbstring_supported = function_exists('mb_check_encoding'); +if (!$mbstring_supported) $supported = false; +$mbstring = Zira\Helper::tag('span',null,array('class'=>($mbstring_supported ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$mbstring .= ' mbstring '.($mbstring_supported ? Zira\Locale::t('supported') : Zira\Locale::t('not supported')); + +$json_supported = function_exists('json_encode'); +if (!$json_supported) $supported = false; +$json = Zira\Helper::tag('span',null,array('class'=>($json_supported ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$json .= ' JSON '.($json_supported ? Zira\Locale::t('supported') : Zira\Locale::t('not supported')); + +$cache_dir_writatable = is_writable(ROOT_DIR . DIRECTORY_SEPARATOR . CACHE_DIR); +if (!$cache_dir_writatable) $supported = false; +$cache_dir = Zira\Helper::tag('span',null,array('class'=>($cache_dir_writatable ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$cache_dir .= ' '.Zira\Locale::t('%s directory','cache').' '.($cache_dir_writatable ? Zira\Locale::t('is writable') : Zira\Locale::t('is not writable')); + +$log_dir_writatable = is_writable(ROOT_DIR . DIRECTORY_SEPARATOR . LOG_DIR); +if (!$log_dir_writatable) $supported = false; +$log_dir = Zira\Helper::tag('span',null,array('class'=>($log_dir_writatable ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$log_dir .= ' '.Zira\Locale::t('%s directory','log').' '.($log_dir_writatable ? Zira\Locale::t('is writable') : Zira\Locale::t('is not writable')); + +$upload_dir_writatable = is_writable(ROOT_DIR . DIRECTORY_SEPARATOR . UPLOADS_DIR); +if (!$upload_dir_writatable) $supported = false; +$upload_dir = Zira\Helper::tag('span',null,array('class'=>($upload_dir_writatable ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$upload_dir .= ' '.Zira\Locale::t('%s directory','uploads').' '.($upload_dir_writatable ? Zira\Locale::t('is writable') : Zira\Locale::t('is not writable')); + +$htaccess_exists = file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . '.htaccess'); +if (!$htaccess_exists) $supported = false; +$htaccess = Zira\Helper::tag('span',null,array('class'=>($htaccess_exists ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$htaccess .= ' '.Zira\Locale::t('File %s','.htaccess').' '.($htaccess_exists ? Zira\Locale::t('is exists') : Zira\Locale::t('is not exists')); + +$robots_exists = file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . 'robots.txt'); +if (!$robots_exists) $supported = false; +$robots = Zira\Helper::tag('span',null,array('class'=>($robots_exists ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +$robots .= ' '.Zira\Locale::t('File %s','robots.txt').' '.($robots_exists ? Zira\Locale::t('is exists') : Zira\Locale::t('is not exists')); + +$config_exists = file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . 'config.php'); +$config_writatable = false; +if (!$config_exists) $supported = false; +else $config_writatable = is_writable(ROOT_DIR . DIRECTORY_SEPARATOR . 'config.php'); +if (!$config_writatable) $supported = false; +$config = Zira\Helper::tag('span',null,array('class'=>($config_exists && $config_writatable ? 'glyphicon glyphicon-ok-sign system-ok' : 'glyphicon glyphicon-warning-sign system-warning'))); +if (!$config_exists) $config .= ' '.Zira\Locale::t('File %s','config.php').' '.($config_exists ? Zira\Locale::t('is exists') : Zira\Locale::t('is not exists')); +else $config .= ' '.Zira\Locale::t('File %s','config.php').' '.($config_writatable ? Zira\Locale::t('is writeable') : Zira\Locale::t('is not writeable')); + +$response = array('content'=>Zira\Helper::tag('style', '.system-ok { color: green; } .system-warning { color: red; }'). + ($supported ? Zira\Helper::tag_open('h2').Zira\Helper::tag('span', null, array('class'=>'glyphicon glyphicon-ok-sign')).' '.Zira\Locale::t('System is ready to be installed').Zira\Helper::tag_close('h2') : Zira\Helper::tag('h2', Zira\Locale::t('Preparing to install'))). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + (!$htaccess_exists || !$robots_exists || !$config_exists ? + Zira\Helper::tag('p', Zira\Locale::t('You have to rename the following files:')). + Zira\Helper::tag_open('ul'). + Zira\Helper::tag('li', 'htaccess.txt ⇨ .htaccess'). + Zira\Helper::tag('li', 'robots.src.txt ⇨ robots.txt'). + Zira\Helper::tag('li', 'config.src.php ⇨ config.php'). + Zira\Helper::tag_close('ul'). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p') + : ''). + Zira\Helper::tag('p', Zira\Locale::t('Server test:')). + Zira\Helper::tag_open('ul', array('class'=>'system-options-list', 'style'=>'list-style-type: none; padding: 0px')). + Zira\Helper::tag_open('li').Zira\Helper::tag('span',null,array('class'=>'glyphicon glyphicon-info-sign')).' '.$os_name.' / '.$server_name.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$php_prefix.' PHP '.$phpversion.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$pdo.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$gd.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$zip.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$gzip.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$openssl.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$mbstring.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$json.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').Zira\Helper::tag('span',null,array('class'=>'glyphicon glyphicon-question-sign')).' '.Zira\Locale::t('Clean URLs').' '.Zira\Helper::tag('span',Zira\Locale::t('is being checked...'),array('id'=>'sys-info-clean-url-option')).Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$cache_dir.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$log_dir.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$upload_dir.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$htaccess.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$robots.Zira\Helper::tag_close('li'). + Zira\Helper::tag_open('li').$config.Zira\Helper::tag_close('li'). + Zira\Helper::tag_close('ul'), + 'script' => + 'zira_install_clean_url = false;'. + '$.get(\''.Zira\Helper::baseUrl('install/check/1').'\', function(response){'. + 'if (response) zira_install_clean_url = true;'. + '}).always(function(){'. + 'if (zira_install_clean_url) {'. + '$(\'#sys-info-clean-url-option\').text(\''.Zira\Locale::t('supported').'\');'. + '$(\'#sys-info-clean-url-option\').parent().children(\'.glyphicon\').removeClass(\'glyphicon-question-sign\').addClass(\'glyphicon-ok-sign\').addClass(\'system-ok\');'. + '} else {'. + '$(\'#sys-info-clean-url-option\').text(\''.Zira\Locale::t('not supported').'\');'. + '$(\'#sys-info-clean-url-option\').parent().children(\'.glyphicon\').removeClass(\'glyphicon-question-sign\').addClass(\'glyphicon-warning-sign\').addClass(\'system-warning\');'. + '}'. + '});' +); + +if (!$supported) $response['error'] = !$htaccess_exists || !$robots_exists || !$config_exists ? Zira\Locale::t('Filesystem need to be prepared for installation') : Zira\Locale::t('Zira installer cannot continue'); + +return $response; \ No newline at end of file diff --git a/install/forms/configuration.php b/install/forms/configuration.php new file mode 100644 index 0000000..e771cd3 --- /dev/null +++ b/install/forms/configuration.php @@ -0,0 +1,77 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('Configuration')); + $this->setDescription(Locale::t('Please fill out form fields')); + } + + protected function _render() { + $html = $this->open(); + $html .= Helper::tag_open('div', array('class'=>'form-group')); + $html .= Helper::tag('label', Locale::t('Database').':', array('class'=>'col-sm-3 control-label')); + $html .= Helper::tag_close('div'); + + $html .= $this->select(Locale::t('Type').'*', 'db_type', array('mysql'=>'MySQL', 'sqlite'=>'SQLite'), array('onchange'=>'zira_install_database_select()', 'id'=>'zira-install-db-type-select')); + + $html .= Helper::tag_open('div', array('id'=>'zira-install-mysql-credentials')); + $html .= $this->input(Locale::t('Server').'*', 'db_host'); + $html .= $this->input(Locale::t('Port').'*', 'db_port'); + $html .= $this->input(Locale::t('Name').'*', 'db_name'); + $html .= $this->input(Locale::t('User').'*', 'db_username'); + $html .= $this->input(Locale::t('Password'), 'db_password'); + $html .= Helper::tag_close('div'); + + $html .= Helper::tag_open('div', array('id'=>'zira-install-sqlite-credentials')); + $html .= $this->input(Locale::t('File').'*', 'db_file'); + $html .= Helper::tag_close('div'); + + $html .= $this->input(Locale::t('Table prefix').'*', 'db_prefix', array('title'=>Locale::t('change to unique string'))); + $html .= Helper::tag('div', null, array('style'=>'margin: 40px 0px')); + $html .= Helper::tag_open('div', array('class'=>'form-group')); + $html .= Helper::tag('label', Locale::t('Website').':', array('class'=>'col-sm-3 control-label')); + $html .= Helper::tag_close('div'); + $html .= $this->input(Locale::t('Document root').'*', 'root_dir', array('title'=>Locale::t('change only if a problem occurres'))); + $html .= $this->input(Locale::t('Base URL').'*', 'base_url', array('title'=>Locale::t('change only if it was detected incorrectly'))); + $html .= $this->input(Locale::t('Console password'), 'console_password', array('placeholder'=>Locale::t('min. %s chars',8), 'title'=>Locale::t('leave blank if you\'re not planning to use console'))); + $html .= $this->hidden('clean_url', array('id'=>'zira_install_clean_url_input')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + + $db_type = $this->getValue('db_type'); + if ($db_type == 'mysql') { + $validator->registerString('db_host', null, 255, true, Locale::t('Please fill out form fields')); + $validator->registerNumber('db_port', 1, null, true, Locale::t('Please fill out form fields')); + $validator->registerString('db_name', null, 255, true, Locale::t('Please fill out form fields')); + $validator->registerString('db_username', null, 255, true, Locale::t('Please fill out form fields')); + } else if ($db_type == 'sqlite') { + $validator->registerString('db_file', null, 255, true, Locale::t('Please fill out form fields')); + } + + $validator->registerString('db_prefix', null, 255, true, Locale::t('Please fill out form fields')); + $validator->registerString('root_dir', null, 255, true, Locale::t('Please fill out form fields')); + $validator->registerString('base_url', null, 255, true, Locale::t('Please fill out form fields')); + $validator->registerString('console_password', 8, 255, false, Locale::t('Console password is too short')); + } +} \ No newline at end of file diff --git a/install/forms/credentials.php b/install/forms/credentials.php new file mode 100644 index 0000000..fd31652 --- /dev/null +++ b/install/forms/credentials.php @@ -0,0 +1,64 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('Required information')); + $this->setDescription(Locale::t('Please fill out form fields')); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('Website name').'*', 'site_name'); + $html .= $this->input(Locale::t('Website slogan').'*', 'site_slogan'); + $html .= $this->input(Locale::t('Contact Email').'*', 'email_from'); + $html .= $this->input(Locale::t('Secret key').'*', 'secret', array('placeholder'=>Locale::t('min. %s chars',8),'title'=>Locale::t('enter random chars'))); + $html .= Helper::tag('div', null, array('style'=>'margin: 40px 0px')); + $html .= Helper::tag_open('div', array('class'=>'form-group')); + $html .= Helper::tag('label', Locale::t('Administrator').':', array('class'=>'col-sm-3 control-label')); + $html .= Helper::tag_close('div'); + $html .= $this->input(Locale::t('First name').'*', 'firstname'); + $html .= $this->input(Locale::t('Last name').'*', 'secondname'); + $html .= $this->input(Locale::t('Login').'*', 'username'); + $html .= $this->input(Locale::t('Password').'*', 'password'); + $html .= $this->input(Locale::t('Email').'*', 'email'); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + + $validator->registerString('site_name', null, 255, true, Locale::t('Please fill out form fields')); + $validator->registerNoTags('site_name', Locale::t('Invalid character detected')); + $validator->registerString('site_slogan', null, 255, true, Locale::t('Please fill out form fields')); + $validator->registerNoTags('site_slogan', Locale::t('Invalid character detected')); + $validator->registerEmail('email_from', true, Locale::t('Invalid email')); + $validator->registerString('secret', 8, 255, true, Locale::t('Secret key is too short')); + $validator->registerString('firstname', null, 255, true, Locale::t('Please fill out form fields')); + $validator->registerNoTags('firstname', Locale::t('Invalid character detected')); + $validator->registerString('secondname', null, 255, true, Locale::t('Please fill out form fields')); + $validator->registerNoTags('secondname', Locale::t('Invalid character detected')); + $validator->registerString('username', \Zira\User::LOGIN_MIN_CHARS, \Zira\User::LOGIN_MAX_CHARS, true, Locale::t('Invalid username')); + $validator->registerRegexp('username', \Zira\User::REGEXP_LOGIN, Locale::t('Login must contain only letters and numbers')); + $validator->registerString('password', \Zira\User::PASSWORD_MIN_CHARS, \Zira\User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerRegexp('password', \Zira\User::REGEXP_PASSWORD, Locale::t('Password contain bad characters')); + $validator->registerEmail('email', true, Locale::t('Invalid email')); + } +} \ No newline at end of file diff --git a/install/index.php b/install/index.php new file mode 100644 index 0000000..5425ae1 --- /dev/null +++ b/install/index.php @@ -0,0 +1,204 @@ +count($steps)) $step=0; +$process = isset($_GET['process']) ? intval($_GET['process']) : 0; + +if (!defined('ROOT_DIR')) define('ROOT_DIR','..'); +if (!defined('BASE_URL')) define('BASE_URL', '..'); +if (!defined('SECRET')) define('SECRET', 'zIraTmPseCret'); + +Zira\Session::start(); +Zira\Locale::load($language, 'install'); + +if ($process<=0 && $step>0) { + $response = include('.' . DIRECTORY_SEPARATOR . $steps[$step-1] . '.php'); + echo json_encode($response); + Zira\Session::close(); + exit; +} else if ($process>0) { + $response = include('.' . DIRECTORY_SEPARATOR . 'operate.php'); + echo json_encode($response); + Zira\Session::close(); + exit; +} + +Zira\View::setTheme(DEFAULT_THEME); +Zira\View::setRenderJsStrings(false); +Zira\View::setRenderBreadcrumbs(false); +Zira\View::addDefaultAssets(); +Zira\View::addThemeAssets(); +Zira\View::addWidget('\Zira\Widgets\Logo'); + +Zira\Config::set('language', $language); +Zira\Config::set('languages', $languages); +Zira\Config::set('site_name', 'Zira CMS'); +Zira\Config::set('site_slogan', ''); +Zira\Config::set('site_logo', 'assets/images/zira.png'); + +Zira\Helper::setAddingLanguageToUrl(false); +$html = Zira\Helper::tag_open('ul', array('id'=>'language-switcher')); +foreach($languages as $_language) { + if ($_language == $language) $class='active'; + else $class = ''; + $html .= Zira\Helper::tag_open('li'); + $html .= Zira\Helper::tag('a', Zira\Helper::html(ucfirst($_language)), array('href'=>'?lang='.Zira\Helper::html($_language), 'class'=>$class)); + $html .= Zira\Helper::tag_close('li'); +} +$html .= Zira\Helper::tag_close('ul'); +Zira\View::addHTML($html, Zira\View::VAR_HEADER); + +$init_content = Zira\Helper::tag_open('div', array('id'=>'zira-install-container')). + Zira\Helper::tag('h2', Zira\Locale::t('Welcome to Zira CMS installer')). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', Zira\Locale::t('Zira CMS is a lightweight, flexible and easy to use content management system.')). + Zira\Helper::tag('p', Zira\Locale::t('Installing Zira CMS, you get the most commonly used features right out of the box.')). + Zira\Helper::tag('p', Zira\Locale::t('No need for extra downloads and plugins setup.')). + Zira\Helper::tag('p', Zira\Locale::t('Zira CMS brings desktop experience to your website - no web development skills required!')). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', Zira\Locale::t('Main features:')). + Zira\Helper::tag_open('ul'). + Zira\Helper::tag('li', Zira\Locale::t('Simple management')). + Zira\Helper::tag('li', Zira\Locale::t('Fast and flexible')). + Zira\Helper::tag('li', Zira\Locale::t('SEO friendly')). + Zira\Helper::tag('li', Zira\Locale::t('Free of charge')). + Zira\Helper::tag_close('ul'). + Zira\Helper::tag_open('div', array('style'=>'margin:40px 0px 100px')). + Zira\Helper::tag('button', Zira\Locale::t('Install'), array('class'=>'btn btn-primary', 'id'=>'zira-install-start-btn')). + Zira\Helper::tag_close('div'). + Zira\Helper::tag_close('div'). + Zira\Helper::tag_open('div', array('id'=>'zira-install-pager', 'class'=>'btn-group', 'style'=>'display:none;margin:40px 0px 100px')). + Zira\Helper::tag('button', '⇦ '.Zira\Locale::t('Backward'), array('class'=>'btn btn-default', 'id'=>'zira-install-backward-btn', 'disabled'=>'disabled')). + Zira\Helper::tag('button', Zira\Locale::t('Forward').' ⇨', array('class'=>'btn btn-primary', 'id'=>'zira-install-forward-btn', 'disabled'=>'disabled')). + Zira\Helper::tag_close('div'); + +$init_js = Zira\Helper::tag_open('script',array('type'=>'text/javascript')). + 'zira_strings = {\'Error\':\''.Zira\Locale::t('Error').'\', \'Message\':\''.Zira\Locale::t('Message').'\', \'Close\':\''.Zira\Locale::t('Close').'\', \'Please wait\': \''.Zira\Locale::t('Please wait').'\'};'. + 'zira_install_clean_url = false;'. + '(function($){'. + 'zira_install_page = 0;'. + 'zira_process_page = 0;'. + 'zira_install_init = function() {'. + 'if (zira_install_page>1) $(\'#zira-install-backward-btn\').removeAttr(\'disabled\');'. + 'else $(\'#zira-install-backward-btn\').attr(\'disabled\', \'disabled\');'. + 'if (zira_install_page<'.count($steps).') $(\'#zira-install-forward-btn\').removeAttr(\'disabled\');'. + 'else $(\'#zira-install-forward-btn\').attr(\'disabled\', \'disabled\');'. + '$(\'form\').submit(function(e){'. + 'e.stopPropagation(); e.preventDefault();'. + 'zira_install_forward();'. + '});'. + '};'. + 'zira_install_backward = function() {'. + '$(\'#zira-install-backward-btn\').attr(\'disabled\', \'disabled\');'. + '$(\'#zira-install-forward-btn\').attr(\'disabled\', \'disabled\');'. + 'zira_install_page--;'. + 'zira_install_request();'. + '};'. + 'zira_install_forward = function() {'. + '$(\'#zira-install-backward-btn\').attr(\'disabled\', \'disabled\');'. + '$(\'#zira-install-forward-btn\').attr(\'disabled\', \'disabled\');'. + 'zira_install_page++;'. + 'zira_install_request();'. + '};'. + 'zira_install_request = function() {'. + '$(\'body\').css(\'cursor\',\'wait\');'. + 'var data = {};'. + 'var form = $(\'#zira-install-container\').find(\'form\');'. + 'if ($(form).length>0) {'. + 'var formData = $(form).eq(0).serializeArray();'. + 'for (var i=0; i Zira\Locale::t('Installation'), + Zira\View::VAR_CONTENT => $init_content . $init_js +), $view_file, $layout_file); + +Zira\Session::close(); \ No newline at end of file diff --git a/install/layout.php b/install/layout.php new file mode 100644 index 0000000..132cf5b --- /dev/null +++ b/install/layout.php @@ -0,0 +1,55 @@ + + + + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    + + + + +
    + +
    +
    + +
    + + + \ No newline at end of file diff --git a/install/license.php b/install/license.php new file mode 100644 index 0000000..9de9b95 --- /dev/null +++ b/install/license.php @@ -0,0 +1,22 @@ + Zira\Helper::tag('h2', Zira\Locale::t('Agreement')). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', Zira\Locale::t('By installing Zira CMS you are agree to the following terms and conditions:')). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', Zira\Locale::t('Zira CMS is a free software and can be used in both commercial and non-commercial projects without limitation.')). + Zira\Helper::tag_open('p').Zira\Locale::t('You can modify system files for your needs, but Zira CMS\' copyright string with active link to %s must exists on every generated page.',Zira\Helper::tag('a','http://dro1d.ru', array('href'=>'http://dro1d.ru','target'=>'_blank'))).Zira\Helper::tag_close('p'). + Zira\Helper::tag_open('p').Zira\Locale::t('If this doesn\'t fit your needs, you may want to purchase a license. Please visit our %s for further details.',Zira\Helper::tag('a',Zira\Locale::t('website'), array('href'=>'http://dro1d.ru','target'=>'_blank'))).Zira\Helper::tag_close('p'). + Zira\Helper::tag_open('p').Zira\Locale::t('If you have any questions, feel free to %s.',Zira\Helper::tag('a',Zira\Locale::t('contact us'), array('href'=>'http://dro1d.ru/contact','target'=>'_blank'))).Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', Zira\Locale::t('Don\'t forget to visit our forum and share your impressions with other users.')). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', Zira\Locale::t('Ready to proceed ?')) +); \ No newline at end of file diff --git a/install/operate.php b/install/operate.php new file mode 100644 index 0000000..c945875 --- /dev/null +++ b/install/operate.php @@ -0,0 +1,362 @@ +$total_processes) throw new \Exception('Unknown task'); + + $data = Zira\Session::get('zira_data'); + if (empty($data)) throw new \Exception('No data recieved'); + + // defining constants + foreach ($constants as $field) { + if (!isset($data[$field])) throw new \Exception('No data recieved'); + $const = strtoupper($field); + if (!defined($const)) define($const, $data[$field]); + } + + // connecting to database + Zira\Db\Loader::initialize(); + Zira\Db\Db::open(); + + if ($process == 1) { + // creating db tables + $dir = ROOT_DIR . DIRECTORY_SEPARATOR . 'zira' . DIRECTORY_SEPARATOR . 'install'; + $tables = array(); + $d = opendir($dir); + while (($f = readdir($d)) !== false) { + if ($f == '.' || $f == '..' || is_dir($dir . DIRECTORY_SEPARATOR . $f)) continue; + if (!preg_match('/^([a-zA-Z0-9]+)\.php$/', $f, $matches)) continue; + $class = '\\Zira\\Install\\' . ucfirst($matches[1]); + try { + if (class_exists($class)) { + $table = new $class; + if ($table instanceof Zira\Db\Table) { + $tables [] = $table; + } else { + unset($table); + } + } + } catch (\Exception $e) { + + } + } + closedir($d); + + if (!empty($tables)) { + foreach ($tables as $table) { + $table->install(); + } + } + + $message = Zira\Locale::t('Creating user'); + } else if ($process == 2) { + // creating user + if (empty($data['username']) || + empty($data['password']) || + empty($data['email']) || + empty($data['firstname']) || + empty($data['secondname']) + ) { + throw new \Exception('No user data'); + } + $user = new Zira\Models\User(); + + $user->group_id = Zira\User::GROUP_SUPERADMIN; + $user->username = $data['username']; + $user->email = $data['email']; + $user->password = Zira\User::getHashedUserToken($data['password']); + $user->firstname = $data['firstname']; + $user->secondname = $data['secondname']; + $user->verified = Zira\Models\User::STATUS_VERIFIED; + $user->active = Zira\Models\User::STATUS_ACTIVE; + $user->date_created = date('Y-m-d H:i:s'); + $user->date_logged = date('Y-m-d H:i:s'); + $user->code = Zira\User::generateRememberCode($user->username, $user->email); + $user->save(); + + $message = Zira\Locale::t('Creating home page'); + } else if ($process == 3) { + // creating home page + $record = new Zira\Models\Record(); + $record->category_id = 0; + $record->name = Zira\Locale::t('home'); + $record->title = Zira\Locale::t('Home page'); + $record->description = Zira\Locale::t('Welcome to Zira CMS!'); + $record->content = Zira\Helper::tag('p', Zira\Locale::t('Welcome to Zira CMS!')). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', Zira\Locale::t('Zira CMS is a lightweight, flexible and easy to use content management system.')). + Zira\Helper::tag('p', Zira\Locale::t('Installing Zira CMS, you get the most commonly used features right out of the box.')). + Zira\Helper::tag('p', Zira\Locale::t('No need for extra downloads and plugins setup.')). + Zira\Helper::tag('p', Zira\Locale::t('Zira CMS brings desktop experience to your website - no web development skills required!')). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag_open('p').Zira\Locale::t('If you have any questions, feel free to %s.',Zira\Helper::tag('a',Zira\Locale::t('contact us'), array('href'=>'http://dro1d.ru/contact','target'=>'_blank'))).Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', Zira\Locale::t('Don\'t forget to visit our forum and share your impressions with other users.')) + ; + $record->language = $language; + $record->access_check = 0; + $record->published = Zira\Models\Record::STATUS_PUBLISHED; + $record->front_page = Zira\Models\Record::STATUS_NOT_FRONT_PAGE; + $record->author_id = 1; + $record->creation_date = date('Y-m-d H:i:s'); + $record->modified_date = date('Y-m-d H:i:s'); + $record->save(); + + // settings + if (!empty($data['site_name'])) { + $optionObj = new Zira\Models\Option(); + $optionObj->name = 'home_window_title'; + $optionObj->value = $data['site_name']; + $optionObj->module = 'zira'; + $optionObj->save(); + } + + $optionObj = new Zira\Models\Option(); + $optionObj->name = 'home_layout'; + $optionObj->value = Zira\View::LAYOUT_RIGHT_SIDEBAR; + $optionObj->module = 'zira'; + $optionObj->save(); + + $optionObj = new Zira\Models\Option(); + $optionObj->name = 'home_record_name'; + $optionObj->value = Zira\Locale::t('home'); + $optionObj->module = 'zira'; + $optionObj->save(); + $message = Zira\Locale::t('Creating news category'); + } else if ($process == 4) { + // creating news category + $category = new Zira\Models\Category(); + $category->name = Zira\Locale::t('news'); + $category->title = Zira\Locale::t('News'); + $category->layout = Zira\View::LAYOUT_RIGHT_SIDEBAR; + $category->parent_id = 0; + $category->access_check = 0; + $category->display_author = 1; + $category->display_date = 1; + $category->rating_enabled = 1; + $category->records_list = 1; + $category->save(); + + $record = new Zira\Models\Record(); + $record->category_id = $category->id; + $record->name = Zira\Locale::t('launch'); + $record->title = Zira\Locale::t('Our new website is now open!'); + $record->description = Zira\Locale::t('Our website is now open for visitors.'); + $record->content = Zira\Helper::tag('p', Zira\Locale::t('Our website is now open for visitors.')).Zira\Helper::tag('p', Zira\Locale::t('This is an example page created by installer.')); + $record->language = $language; + $record->access_check = 0; + $record->published = Zira\Models\Record::STATUS_PUBLISHED; + $record->front_page = Zira\Models\Record::STATUS_NOT_FRONT_PAGE; + $record->author_id = 1; + $record->creation_date = date('Y-m-d H:i:s'); + $record->modified_date = date('Y-m-d H:i:s'); + $record->save(); + + $max_order = Zira\Models\Widget::getCollection()->max('sort_order')->get('mx'); + + $widget = new Zira\Models\Widget(); + $widget->name = Zira\Models\Category::WIDGET_CLASS; + $widget->module = 'zira'; + $widget->placeholder = Zira\Models\Category::WIDGET_PLACEHOLDER; + $widget->params = $category->id; + $widget->category_id = 0; + $widget->sort_order = ++$max_order; + $widget->active = Zira\Models\Widget::STATUS_ACTIVE; + $widget->save(); + + $message = Zira\Locale::t('Creating menu'); + } else if ($process == 5) { + // creating menu + $menuItem = new Zira\Models\Menu(); + $menuItem->menu_id = Zira\Menu::MENU_PRIMARY; + $menuItem->parent_id = 0; + $menuItem->sort_order = 1; + $menuItem->url = '/'; + $menuItem->title = 'Home'; + $menuItem->external = 0; + $menuItem->active = Zira\Models\Menu::STATUS_ACTIVE; + $menuItem->save(); + + $menuItem = new Zira\Models\Menu(); + $menuItem->menu_id = Zira\Menu::MENU_PRIMARY; + $menuItem->parent_id = 0; + $menuItem->sort_order = 2; + $menuItem->url = Zira\Locale::t('news'); + $menuItem->language = $language; + $menuItem->title = Zira\Locale::t('News'); + $menuItem->external = 0; + $menuItem->active = Zira\Models\Menu::STATUS_ACTIVE; + $menuItem->save(); + + $menuItem = new Zira\Models\Menu(); + $menuItem->menu_id = Zira\Menu::MENU_FOOTER; + $menuItem->parent_id = 0; + $menuItem->sort_order = 3; + $menuItem->url = '/'; + $menuItem->title = 'Home'; + $menuItem->external = 0; + $menuItem->active = Zira\Models\Menu::STATUS_ACTIVE; + $menuItem->save(); + + $menuItem = new Zira\Models\Menu(); + $menuItem->menu_id = Zira\Menu::MENU_FOOTER; + $menuItem->parent_id = 0; + $menuItem->sort_order = 4; + $menuItem->url = 'contact'; + $menuItem->title = 'Contacts'; + $menuItem->external = 0; + $menuItem->active = Zira\Models\Menu::STATUS_ACTIVE; + $menuItem->save(); + + $menuItem = new Zira\Models\Menu(); + $menuItem->menu_id = Zira\Menu::MENU_FOOTER; + $menuItem->parent_id = 0; + $menuItem->sort_order = 5; + $menuItem->url = 'sitemap'; + $menuItem->title = 'Site map'; + $menuItem->external = 0; + $menuItem->active = Zira\Models\Menu::STATUS_ACTIVE; + $menuItem->save(); + + $message = Zira\Locale::t('Writing settings to %s', 'config.php'); + } else if ($process == 6) { + // writing config + if (empty($data['root_dir']) || empty($data['base_url'])) { + throw new \Exception('No data'); + } + $head = '/**'."\r\n". + ' * Zira CMS'."\r\n". + ' * config.php'."\r\n". + ' * (c)'.date('Y').' http://dro1d.ru'."\r\n". + ' */'."\r\n"; + $info = '/**'."\r\n". + ' * Defined during installation on '.date('Y-m-d')."\r\n". + ' */'."\r\n"; + $config = 'const ROOT_DIR = \''.$data['root_dir'].'\';'."\r\n". + 'const BASE_URL = \''.$data['base_url'].'\';'."\r\n". + 'const SECRET = \''.$data['secret'].'\';'."\r\n". + 'const DB_TYPE = \''.DB_TYPE.'\';'."\r\n"; + if (DB_TYPE == 'mysql') { + $config .= + 'const DB_HOST = \'' . DB_HOST . '\';' . "\r\n" . + 'const DB_PORT = ' . DB_PORT . ';' . "\r\n" . + 'const DB_NAME = \'' . DB_NAME . '\';' . "\r\n" . + 'const DB_USERNAME = \'' . DB_USERNAME . '\';' . "\r\n" . + 'const DB_PASSWORD = \'' . DB_PASSWORD . '\';' . "\r\n"; + } else if (DB_TYPE == 'sqlite') { + $db_file = DB_FILE; + if (substr($db_file, 0, 6)=='../../') { + $db_file = substr($db_file, 3); + } + $config .= 'const DB_FILE = \'' . $db_file . '\';' . "\r\n"; + } + $config .= 'const DB_PREFIX = \''.DB_PREFIX.'\';'."\r\n". + 'const CONSOLE_PASSWORD = \''.(CONSOLE_PASSWORD ? md5(rawurlencode(CONSOLE_PASSWORD)) : '').'\';'."\r\n"; + + if (!isset($data['clean_url']) || + empty($data['email_from']) || + empty($data['site_name']) || + empty($data['site_slogan']) + ) { + throw new \Exception('No site info'); + } + $settings = @include('default.php'); + if (empty($settings) || !is_array($settings)) throw new \Exception('Bad defaults'); + $settings['clean_url'] = $data['clean_url']; + $settings['language'] = $language; + $settings['languages'] = array($language); + $settings['email_from'] = $data['email_from']; + $settings['email_from_name'] = $data['site_name']; + $settings['feedback_email'] = $data['email_from']; + $settings['site_name'] = $data['site_name']; + $settings['site_title'] = $data['site_name']; + $settings['site_slogan'] = $data['site_slogan']; + + $defaults = '/**'."\r\n". + ' * System default settings'."\r\n". + ' */'."\r\n". + 'return array('."\r\n"; + $default_strs = array(); + foreach ($settings as $key => $value) { + if (is_int($value)) { + $default_strs []= "\t'".$key."' => ".$value; + } else if (is_bool($value)) { + $default_strs []= "\t'".$key."' => ".($value ? 'true' : 'false'); + } else if (is_string($value)) { + $default_strs []= "\t'".$key."' => '".$value."'"; + } else if (is_array($value)) { + $_value = 'array('; + if (!empty($value)) { + $_value .= "'".implode("', '", $value)."'"; + } + $_value .= ')'; + $default_strs []= "\t'".$key."' => ".$_value; + } else { + throw new \Exception('Unknown type'); + } + } + $defaults .= implode(",\r\n", $default_strs)."\r\n"; + $defaults .= ');'."\r\n"; + + file_put_contents(ROOT_DIR . DIRECTORY_SEPARATOR . 'config.php', ' 'zira_modal_progress_update(' . $percent . ');' . + '$(\'#zira-install-container\').append(\''.Zira\Helper::tag('p', '- '.$message).'\');'. + 'zira_process_page++;' . + 'window.setTimeout(\'zira_install_request();\', 1000);' + ); + } else { + // Done! + return array( + 'content' => Zira\Helper::tag('h2', Zira\Locale::t('Congratulations!')). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', Zira\Locale::t('Zira CMS is successfully installed.')). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', Zira\Locale::t('For security reasons turn off write permissions of %s file.', 'config.php')). + Zira\Helper::tag_open('p').Zira\Locale::t('Please visit our %s for detailed information.', Zira\Helper::tag('a', Zira\Locale::t('website'), array('href'=>'http://dro1d.ru','target'=>'_blank'))).Zira\Helper::tag_close('p'). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag_open('p').Zira\Locale::t('Go to your new %s!', Zira\Helper::tag('a', Zira\Locale::t('website'), array('href'=>$data['base_url']))).Zira\Helper::tag_close('p'), + 'script' => 'zira_modal_progress_hide();' + ); + } +} else { + // something went wrong + return array( + 'error' => Zira\Locale::t('An error occurred') + ); +} \ No newline at end of file diff --git a/install/process.php b/install/process.php new file mode 100644 index 0000000..4f041f0 --- /dev/null +++ b/install/process.php @@ -0,0 +1,135 @@ +getToken(), $field); + if (Zira\Request::post($_field)===null && Zira\Session::get($field)) { + Zira\Request::setPost($_field, Zira\Session::get($field)); + } +} + +// checking previous form +if (!$form->isValid()) { + return array( + 'error' => $form->getError() + ); +} else { + // saving form data + foreach($constants as $field) { + Zira\Session::set($field, $form->getValue($field)); + } +} + +$data = array(); +$data['clean_url'] = (bool)$form->getValue('clean_url'); +$error = false; + +// checking collected data before installation +$info = array( + 'site_name', + 'site_slogan', + 'email_from', + 'secret', + 'firstname', + 'secondname', + 'username', + 'password', + 'email' +); +foreach($info as $field) { + if (!Zira\Session::get($field)) { + $error = Zira\Locale::t('Please check the specified data once again.'); + break; + } + $data[$field] = Zira\Session::get($field); +} +// checking constants once again +if (!$error) { + foreach ($constants as $field) { + if (Zira\Session::get($field)===null) { + $error = Zira\Locale::t('Please check the specified data once again.'); + break; + } + $data[$field] = Zira\Session::get($field); + } +} +// checking root_dir + +if (!$error && $data['root_dir']!='.') { + $data['root_dir'] = rtrim($data['root_dir'], '/\\'); + if (!file_exists($data['root_dir'] . DIRECTORY_SEPARATOR . 'zira.php')) { + $error = Zira\Locale::t('Incorrect document root is specified.'); + } +} +// checking base url +if (!$error && $data['base_url']!='/') { + $data['base_url'] = '/'.trim($data['base_url'],'/'); + $asset_path = realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR . rtrim(str_repeat('..' . DIRECTORY_SEPARATOR, count(explode('/',$data['base_url']))), DIRECTORY_SEPARATOR) . str_replace('/', DIRECTORY_SEPARATOR, rtrim($data['base_url'], '/') . '/assets/images/zira.png'); + if (!file_exists($asset_path)) { + $error = Zira\Locale::t('Incorrect base url is specified.'); + } +} +// trying to connect to db +if (!$error) { + foreach($constants as $field) { + if (!isset($data[$field])) continue; + $const = strtoupper($field); + if ($field == 'db_file' && !empty($data[$field]) && substr($data[$field], 0, 3)=='../') { + $data[$field] = '../'.$data[$field]; + } + if (!defined($const)) define($const, $data[$field]); + } + try { + Zira\Db\Loader::initialize(); + Zira\Db\Db::open(); + Zira\Db\Db::close(); + } catch(\Exception $e) { + if ($data['db_type']=='sqlite') { + $error = Zira\Locale::t('Failed to create database file.'); + } else { + $error = Zira\Locale::t('Failed to connect to database.'); + } + } +} + +if (!$error) { + // ready to install + Zira\Session::set('zira_data', $data); + return array( + 'content' => Zira\Helper::tag('p', Zira\Locale::t('Please wait...')). + Zira\Helper::tag_open('p').' '.Zira\Helper::tag_close('p'). + Zira\Helper::tag('p', '- '.Zira\Locale::t('Creating database tables')), + 'script' => '$(\'#zira-install-backward-btn\').attr(\'disabled\', \'disabled\');'. + '$(\'#zira-install-forward-btn\').attr(\'disabled\', \'disabled\');'. + '$(\'#zira-install-pager\').remove();'. + 'zira_modal_progress(\''.Zira\Locale::t('Installation').'\');'. + 'zira_process_page++;'. + 'window.setTimeout(\'zira_install_request();\', 1000);' + ); +} else { + return array( + 'error' => Zira\Locale::t('An error occurred').'. '.$error + ); +} \ No newline at end of file diff --git a/key.pub b/key.pub new file mode 100644 index 0000000..14329d8 --- /dev/null +++ b/key.pub @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+b6Qg9qbcHORgCb2xOIUNC9Ly +mmNY2WfQSGkpgTTXxdoIiUs2Rex9x6uDpyHD26I7u5lVDBOG0zZqob+IrPzGOmZH +Zr92vXc3SFxBZJ1IHraVeRdGV0hdSA7JKdtgpU46vO90QMaVG5+0QVyIc4Ir/oCQ +49X8o97/VEgeQb71IQIDAQAB +-----END PUBLIC KEY----- diff --git a/languages/en/dash.js.php b/languages/en/dash.js.php new file mode 100644 index 0000000..207cc1e --- /dev/null +++ b/languages/en/dash.js.php @@ -0,0 +1,5 @@ + array('Deactivated %s user', 'Deactivated %s users'), + 'Activated %s users' => array('Activated %s user', 'Activated %s users'), + 'Deactivated %s groups' => array('Deactivated %s group', 'Deactivated %s groups'), + 'Activated %s groups' => array('Activated %s group', 'Activated %s groups'), + 'Deleted %s groups' => array('Deleted %s group', 'Deleted %s groups'), + 'Deactivated %s widgets' => array('Deactivated %s widget', 'Deactivated %s widgets'), + 'Activated %s widgets' => array('Activated %s widget', 'Activated %s widgets'), + 'Activated %s comments' => array('Activated %s comment', 'Activated %s comments'), + '%s comments was posted' => array('%s comment was posted', '%s comments was posted'), + 'max. length: %s chars' => array('max. length: %s char', 'max. length: %s chars') +); \ No newline at end of file diff --git a/languages/en/en.js.php b/languages/en/en.js.php new file mode 100644 index 0000000..207cc1e --- /dev/null +++ b/languages/en/en.js.php @@ -0,0 +1,5 @@ + 'English', + 'Added %s files' => array('Added %s file', 'Added %s files'), + 'Message should contain at least %s characters' => array('Message should contain at least %s character', 'Message should contain at least %s characters') +); \ No newline at end of file diff --git a/languages/en/zira.php b/languages/en/zira.php new file mode 100644 index 0000000..06cc40b --- /dev/null +++ b/languages/en/zira.php @@ -0,0 +1,5 @@ + array('At least %s character required','At least %s characters required'), +); \ No newline at end of file diff --git a/languages/ru/dash.js.php b/languages/ru/dash.js.php new file mode 100644 index 0000000..5e9544c --- /dev/null +++ b/languages/ru/dash.js.php @@ -0,0 +1,28 @@ + 'Закрыть', + 'Sending' => 'Отправка', + 'Message' => 'Сообщение', + 'Error' => 'Ошибка', + 'Confirmation' => 'Подтверждение', + 'Yes' => 'Да', + 'No' => 'Нет', + 'Cancel' => 'Отмена', + 'Please wait' => 'Пожалуйста, подождите', + 'Load failed' => 'Ошибка загрузки', + 'Are you sure ?' => 'Вы уверены ?', + 'An error occurred' => 'Возникла ошибка', + 'Window' => 'Окно', + 'Help' => 'Помощь', + 'Left Sidebar' => 'Левая колонка', + 'Toolbar' => 'Панель инструментов', + 'Snap to left side' => 'Показывать слева', + 'Snap to right side' => 'Показывать справа', + 'Delete' => 'Удалить', + 'Create' => 'Создать', + 'Edit' => 'Редактировать', + 'from' => 'из', + 'Maximum upload size:' => 'Максимальный размер загрузки:', + 'Sorry, but it seems that your browser is not supported.' => 'Извините, но похоже, ваш браузер не поддерживается.' +); \ No newline at end of file diff --git a/languages/ru/dash.php b/languages/ru/dash.php new file mode 100644 index 0000000..14fc922 --- /dev/null +++ b/languages/ru/dash.php @@ -0,0 +1,354 @@ + 'Действия', + 'Delete' => 'Удалить', + 'Create' => 'Создать', + 'Select all' => 'Выделить всё', + 'Unselect all' => 'Снять выделение', + 'Save' => 'Сохранить', + 'Sort descending' => 'Сортировать по убыванию', + 'Sort ascending' => 'Сортировать по возрастанию', + 'Load current page' => 'Загрузить текущую страницу', + 'URL address' => 'URL адрес', + 'Reload' => 'Перезагрузить', + 'Initialization' => 'Инициализация', + 'Up' => 'Вверх', + 'Down' => 'Вниз', + 'Permission denied' => 'Нет прав доступа', + 'Invalid file' => 'Некорректный файл', + 'Invalid image' => 'Некорректное изображение', + 'Invalid directory' => 'Некорректная директория', + 'Deleted successfully' => 'Удалено успешно', + 'New folder' => 'Новая папка', + 'Enter name' => 'Введите имя', + 'Folder must be empty' => 'Папка должна быть пустой', + 'File or directory with such name already exists' => 'Файл или директория с таким именем уже существует', + 'Upload' => 'Загрузить', + 'Rename' => 'Переименовать', + 'Upload from URL' => 'Загрузить из URL', + 'Enter URL address' => 'Введите URL адрес', + 'Load failed' => 'Ошибка загрузки', + 'Download' => 'Скачать', + 'Copy' => 'Копировать', + 'Enter folder path' => 'Введите путь к папке', + 'Folder not found' => 'Папка не найдена', + 'Create archive' => 'Создать архив', + 'Enter archive name' => 'Введите название архива', + 'Added %s files' => array('Добавлен %s файл', 'Добавлено %s файла', 'Добавлено %s файлов'), + 'Extract' => 'Извлечь', + 'Information' => 'Информация', + 'Select' => 'Выбрать', + 'Image editor' => 'Редактор изображения', + 'Zoom In' => 'Увеличить', + 'Zoom Out' => 'Уменьшить', + 'Change width' => 'Изменить ширину', + 'Change height' => 'Изменить высоту', + 'Image width' => 'Ширина изображения', + 'Image height' => 'Высота изображения', + 'Crop' => 'Обрезка', + 'Cut' => 'Обрезать', + 'Aspect ratio' => 'Соотношение сторон', + 'Replace image ?' => 'Заменить изображение ?', + 'Save as' => 'Сохранить как', + 'Crop width' => 'Обрезать по ширине', + 'Crop height' => 'Обрезать по высоте', + 'Text editor' => 'Текстовый редактор', + 'HTML editor' => 'HTML редактор', + 'Create text file' => 'Создать текстовый файл', + 'Create HTML file' => 'Создать HTML файл', + 'Open as text' => 'Открыть как текст', + 'New user' => 'Новый пользователь', + 'User not found' => 'Пользователь не найден', + 'Group not found' => 'Группа не найдена', + 'Invalid username' => 'Некорректный логин', + 'Invalid email' => 'Некорректный email', + 'Invalid password' => 'Некорректный пароль', + 'At least %s characters required' => array('Введите минимум %s символ','Введите минимум %s символа','Введите минимум %s символов'), + 'Enter a valid email' => 'Укажите существующий email', + 'Login must contain only letters and numbers' => 'Логин должен содержать только буквы и цифры', + 'Password contain bad characters' => 'Пароль содержит некорректный символ', + 'Specified login already exists' => 'Указанный логин уже существует', + 'Specified email already exists' => 'Указанный email уже существует', + 'Please enter first name' => 'Пожалуйста, укажите имя', + 'Please enter second name' => 'Пожалуйста, укажите фамилию', + 'Phone should be specified in international format' => 'Телефон должен быть указан в международном формате', + 'verified' => 'проверен', + 'active' => 'активен', + 'hidden' => 'скрыт', + 'Change avatar' => 'Сменить аватару', + 'Delete avatar' => 'Удалить аватару', + 'Deactivate' => 'Деактивировать', + 'Activate' => 'Активировать', + 'Deactivated %s users' => array('Деактивирован %s пользователь', 'Деактивировано %s пользователя', 'Деактивировано %s пользователей'), + 'Activated %s users' => array('Активирован %s пользователь', 'Активировано %s пользователя', 'Активировано %s пользователей'), + 'Deactivated %s groups' => array('Деактивирована %s группа', 'Деактивировано %s группы', 'Деактивировано %s групп'), + 'Activated %s groups' => array('Активирована %s группа', 'Активировано %s группы', 'Активировано %s групп'), + 'Deleted %s groups' => array('Удалена %s группа', 'Удалено %s группы', 'Удалено %s групп'), + 'Verified user' => 'Подтвержденный пользователь', + 'Not verified user' => 'Не подтвержденный пользователь', + 'Show avatar' => 'Просмотр аватары', + 'Groups' => 'Группы', + 'Permissions' => 'Права доступа', + 'Access system dashboard' => 'Доступ к панеле управления', + 'Execute system tasks' => 'Выполнять системные задачи', + 'Change system options' => 'Изменять настройки системы', + 'Change theme layout' => 'Изменять макет темы', + 'Create users' => 'Создавать пользователей', + 'Edit users' => 'Редактировать пользователей', + 'Delete users' => 'Удалять пользователей', + 'Upload files' => 'Загружать файлы', + 'Delete files' => 'Удалять файлы', + 'View files list' => 'Просматривать список файлов', + 'Upload images' => 'Загружать изображения', + 'Delete images' => 'Удалять изображения', + 'View images list' => 'Просматривать список изображений', + 'Create records' => 'Создавать записи', + 'Edit records' => 'Редактировать записи', + 'Delete records' => 'Удалять записи', + 'View records list' => 'Просматривать список записей', + 'View record' => 'Просматривать запись', + 'Permissions of group "%s"' => 'Права доступа группы "%s"', + 'Thumbs width' => 'Ширина миниатюр', + 'Thumbs height' => 'Высота миниатюр', + 'Watermark' => 'Водяной знак', + 'Enable watermark' => 'Включить водяной знак', + 'PHP date format' => 'Формат даты PHP', + 'JS date format' => 'Формат даты JS', + 'Caching' => 'Кэширование', + 'Cache lifetime (sec.)' => 'Время жизни кэша (сек.)', + 'Clean URLs' => 'ЧПУ', + 'GZIP compression' => 'GZIP компрессия', + 'Add watermark' => 'Добавить водяной знак', + 'Send from email' => 'Отправлять от Email', + 'Send from name' => 'Отправлять от имени', + 'Use SMTP server' => 'Использовать SMTP', + 'SMTP host' => 'SMTP сервер', + 'SMTP port' => 'SMTP порт', + 'SMTP connection' => 'SMTP соединение', + 'SMTP username' => 'SMTP пользователь', + 'SMTP password' => 'SMTP пароль', + 'Email confirmation message' => 'Сообщение подтверждения Email', + 'Password recovery message' => 'Сообщение восстановления пароля', + 'New password message' => 'Сообщение нового пароля', + 'Supported variables: %s' => 'Поддерживаемые переменные: %s', + 'Sticky top bar' => 'Закрепить верхнюю панель', + 'Photo min. width' => 'Мин. ширина фото', + 'Photo min. height' => 'Мин. высота фото', + 'Photo max. width' => 'Макс. ширина фото', + 'Photo max. height' => 'Макс. высота фото', + 'Thumb width' => 'Ширина миниатюры', + 'Thumb height' => 'Высота миниатюры', + 'Allow sign-up' => 'Разрешить регистрацию', + 'Access user profiles' => 'Доступ к профилям', + 'Allow login change' => 'Разрешить смену логина', + 'Verify email' => 'Проверять Email', + 'Check user browser' => 'Проверять браузер', + 'Invalid value "%s"' => 'Некорректное значение "%s"', + 'Make default' => 'Сделать по-умолчанию', + 'Translates' => 'Переводы', + 'Custom translates' => 'Пользовательские переводы', + 'String already exists' => 'Строка уже существует', + 'Enter translate' => 'Введите перевод', + 'Enter string to translate' => 'Введите строку для перевода', + 'DB translates' => 'Переводы БД', + 'DB translates are not enabled' => 'Переводы БД не включены', + 'User' => 'Пользователь', + 'Author: %s' => 'Автор: %s', + 'Preview' => 'Предпросмотр', + 'Install' => 'Установить', + 'Uninstall' => 'Удалить', + 'Remove module from database ?' => 'Удалить модуль из базы данных ?', + 'Cannot install activated module' => 'Невозможно установить активированный модуль', + 'Cannot uninstall activated module' => 'Невозможно удалить активированный модуль', + 'Failed to install module' => 'При установке модуля возникла ошибка', + 'Failed to uninstall module' => 'При удалении модуля возникла ошибка', + 'Module successfully installed' => 'Модуль установлен успешно', + 'Module successfully uninstalled' => 'Модуль удалён успешно', + 'Module is already installed' => 'Модуль уже установлен', + 'Module is not installed' => 'Модуль не установлен', + 'Website title' => 'Название сайта', + 'Website slogan' => 'Слоган сайта', + 'Website logo' => 'Логотип сайта', + 'Copyright string' => 'Строка авторских прав', + 'Show website name in window title' => 'Показывать название сайта в заголовке окна', + 'Open' => 'Открыть', + 'Please wait ...' => 'Пожалуйста, подождите ...', + 'supported' => 'поддерживается', + 'not supported' => 'не поддерживается', + 'Memory limit' => 'Лимит памяти', + 'Max. upload size' => 'Макс. размер загрузки', + '%s directory' => 'Директория %s', + 'is writable' => 'доступна для записи', + 'is not writable' => 'не доступна для записи', + 'is protected' => 'защищен', + 'is not protected' => 'не защищен', + 'is being checked...' => 'проверяется...', + 'Version: %s' => 'Версия: %s', + 'Database dump' => 'Дамп базы данных', + 'System files' => 'Системные файлы', + 'last run %s' => 'последний раз запускался %s', + 'never run' => 'никогда не запускался', + 'Server time: %s' => 'Время сервера: %s', + 'Category' => 'Категория', + 'Category: %s' => 'Категория: %s', + 'New category' => 'Новая категория', + 'System name' => 'Системное имя', + 'Layout' => 'Схема', + 'Title' => 'Заголовок', + 'Category with such name already exists' => 'Категория с таким именем уже существует', + 'Layout with both left and right sidebars' => 'Схема с левой и правой колонками', + 'Layout with left sidebar' => 'Схема с левой колонкой', + 'Layout with right sidebar' => 'Схема с правой колонкой', + 'Layout without sidebars' => 'Схема без колонок', + 'Deactivated %s widgets' => array('Деактивирован %s виджет', 'Деактивировано %s виджета', 'Деактивировано %s виджетов'), + 'Activated %s widgets' => array('Активирован %s виджет', 'Активировано %s виджета', 'Активировано %s виджетов'), + 'Placeholders' => 'Расположения', + 'HEAD tag' => 'Тег HEAD', + 'BODY tag top' => 'Начало тега BODY', + 'Header' => 'Шапка', + 'Left sidebar' => 'Левая колонка', + 'Right sidebar' => 'Правая колонка', + 'Before content' => 'Перед материалом', + 'After content' => 'После материала', + 'Footer' => 'Подвал', + 'BODY tag bottom' => 'Конец тега BODY', + 'Placeholder' => 'Расположение', + 'Page' => 'Страница', + 'All pages' => 'Все страницы', + 'Widget' => 'Виджет', + 'show on record pages only' => 'показывать только на страницах записей', + 'Default layout' => 'Схема по-умолчанию', + 'Detect language' => 'Определять язык', + 'Keywords' => 'Ключевые слова', + 'Description' => 'Описание', + 'max. %s characters' => 'макс. %s символов', + 'Window title' => 'Заголовок окна', + 'Clear all' => 'Очистить все', + 'Clear cache' => 'Очистить кэш', + 'Cache cleared' => 'Кэш очищен', + 'Server time' => 'Серверное время', + 'Local time' => 'Локальное время', + 'Show image' => 'Просмотр изображения', + 'File' => 'Файл', + 'Timezone' => 'Часовой пояс', + 'Block' => 'Блок', + 'New block' => 'Новый блок', + 'Content' => 'Содержимое', + 'Use template' => 'Использовать шаблон', + 'Widget placeholder' => 'Расположение виджета', + 'Create widget' => 'Создать виджет', + 'Editor' => 'Редактор', + 'Edit as text' => 'Редактировать как текст', + 'Edit as HTML' => 'Редактировать как HTML', + 'Open text' => 'Открыть текст', + 'Open HTML' => 'Открыть HTML', + 'Restrict access' => 'Ограничить доступ', + 'Enable comments' => 'Включить комментарии', + 'Enable rating' => 'Включить рейтинг', + 'Display author' => 'Показывать автора', + 'Display date' => 'Показывать дату', + 'New record' => 'Новая запись', + 'Record' => 'Запись', + 'Record: %s' => 'Запись: %s', + 'Language' => 'Язык', + 'Publish' => 'Опубликовать', + 'Show on front page' => 'Показать на главной', + 'Record with such name already exists' => 'Запись с таким именем уже существует', + 'Edit code' => 'Редактировать код', + 'Open editor' => 'Открыть редактор', + 'Edit description' => 'Редактировать описание', + 'Enter description' => 'Введите описание', + 'Attach picture' => 'Прикрепить изображение', + 'SEO tags' => 'SEO теги', + 'View page' => 'Просмотр страницы', + 'Open page' => 'Открыть страницу', + 'Cannot delete category that contains records' => 'Невозможно удалить категорию, содержащую записи', + 'Gallery' => 'Галерея', + 'Image' => 'Изображение', + 'Add image' => 'Добавить изображение', + 'Enter category' => 'Введите категорию', + 'Category not found' => 'Категория не найдена', + 'Move' => 'Переместить', + 'Picture' => 'Изображение', + 'Show slider' => 'Показывать слайдер', + 'Show gallery' => 'Показывать галерею', + 'numbers and letters in lower case' => 'буквы и цифры в нижнем регистре', + 'saved to drafts' => 'сохранено в черновики', + 'Load saved draft ?' => 'Загрузить сохранённый черновик ?', + 'Records limit' => 'Лимит записей', + 'Category records limit' => 'Лимит записей категории', + 'Display records' => 'Показывать записи', + 'Category sorting' => 'Сортировка категорий', + 'ascending' => 'по возрастанию', + 'descending' => 'по убыванию', + 'by name' => 'по имени', + 'Link record' => 'Привязать запись', + 'Enter system name' => 'Введите системное имя', + 'Filter' => 'Фильтр', + 'Do not apply filter' => 'Не применять фильтр', + 'Display on category page only' => 'Показывать только на странице категории', + 'Display on record page only' => 'Показывать только на странице записи', + 'Show child category records' => 'Показывать записи дочерних категорий', + 'Category records' => 'Записи категории', + 'Top records' => 'Топ записей', + 'Category previous records' => 'Предыдущие записи категории', + 'Most discussed records' => 'Самые обсуждаемые записи', + 'All languages' => 'Все языки', + 'System settings' => 'Настройки системы', + 'User settings' => 'Настройки пользователей', + 'Website settings' => 'Настройки сайта', + 'Records settings' => 'Настройки записей', + 'Home page settings' => 'Настройки главной страницы', + 'Comments settings' => 'Настройки комментариев', + 'Nesting level' => 'Уровень вложенности', + 'Comments limit' => 'Лимит комментариев', + 'Moderation' => 'Модерация', + 'Anonymous comments' => 'Анонимное комментирование', + 'Notification Email' => 'Email для оповещений', + 'Allow commenting' => 'Разрешить комментирование', + 'Always show CAPTCHA' => 'Всегда показывать CAPTCHA', + 'Moderate comments' => 'Модерировать комментарии', + 'New comment message' => 'Сообщение о новом комментарии', + 'Comment min. length' => 'Мин. длина комментария', + 'Comment' => 'Комментарий', + 'Activated %s comments' => array('Активирован %s комментарий', 'Активировано %s комментария', 'Активировано %s комментариев'), + 'Enable widgets' => 'Включить виджеты', + '%s comments was posted' => array('Оставлен %s комментарий', 'Оставлено %s комментария', 'Оставлено %s комментариев'), + 'Top menu' => 'Верхнее меню', + 'Bottom menu' => 'Нижнее меню', + 'New item' => 'Новый элемент', + 'Menu item' => 'Элемент меню', + 'New menu item' => 'Новый элемент меню', + 'Class' => 'Класс', + 'Open in new tab' => 'Открывать в новой вкладке', + 'Child items' => 'Дочерние элементы', + 'Secondary menu' => 'Вторичное меню', + 'Predefined classes: %s' => 'Доступные классы: %s', + 'Display item' => 'Показывать элемент', + 'Contact email' => 'Email для контактов', + 'Feedback message' => 'Сообщение обратной связи', + 'Full name / Company' => 'Ф.И.О. / Компания', + 'Enable Google Map' => 'Включить карту Google', + 'Enable Yandex Map' => 'Включить карту Яндекс', + 'Show Email' => 'Показывать Email', + 'Google Maps API key' => 'API ключ Google Maps', + 'Yandex Maps API key' => 'API ключ Яндекс Карт', + 'Latitude' => 'Широта', + 'Longitude' => 'Долгота', + 'Slider' => 'Слайдер', + 'New message notification' => 'Оповещение о новом сообщении', + 'View profile' => 'Открыть профиль', + 'max. length: %s chars' => array('макс. длина: %s символ', 'макс. длина: %s символа', 'макс. длина: %s символов'), + 'Subject' => 'Тема', + 'Start mailing' => 'Начать рассылку', + 'Subscribers' => 'Подписчики', + 'Successfully finished. Emails sent:' => 'Завершено успешно. Отправлено писем:', + 'Successfully finished. Messages sent:' => 'Завершено успешно. Отправлено сообщений:', + 'User menu' => 'Меню пользователя', + 'Remove assigned image' => 'Удалить прикрепленное изображение', + 'Version %s is available for download' => 'Версия %s доступна для скачивания', + 'File manager' => 'Файловый менеджер', + 'File or directory already exists' => 'Файл или директория уже существует', + 'Display records list' => 'Показывать список записей' +); \ No newline at end of file diff --git a/languages/ru/install.php b/languages/ru/install.php new file mode 100644 index 0000000..c0b759f --- /dev/null +++ b/languages/ru/install.php @@ -0,0 +1,120 @@ + 'Установка', + 'Welcome to Zira CMS installer' => 'Добро пожаловать в установщик Zira CMS', + 'Backward' => 'Назад', + 'Forward' => 'Дальше', + 'Install' => 'Установить', + 'Zira CMS is a lightweight, flexible and easy to use content management system.' => 'Zira CMS - это лёгкая, простая в управлении, и в то-же время гибкая система управления сайтом.', + 'Installing Zira CMS, you get the most commonly used features right out of the box.' => 'Устанавливая Zira CMS, вы получаете наиболее часто используемые функции сразу из коробки.', + 'No need for extra downloads and plugins setup.' => 'Нет необходимости в дополнительном скачивании и настройке плагинов.', + 'Zira CMS brings desktop experience to your website - no web development skills required!' => 'Zira CMS привносит возможности рабочего стола в ваш сайт - нет необходимости иметь опыт веб-разработки!', + 'Main features:' => 'Основные достоинства:', + 'Simple management' => 'Простое управление', + 'Fast and flexible' => 'Быстрота и гибкость', + 'SEO friendly' => 'Дружелюбность к SEO', + 'Free of charge' => 'Не требует денег', + 'Error' => 'Ошибка', + 'Message' => 'Сообщение', + 'Close' => 'Закрыть', + 'An error occurred' => 'Возникла ошибка', + 'supported' => 'поддерживается', + 'not supported' => 'не поддерживается', + '%s directory' => 'Директория %s', + 'is writable' => 'доступна для записи', + 'is not writable' => 'недоступна для записи', + 'Clean URLs' => 'ЧПУ', + 'is being checked...' => 'проверяется...', + 'Zira installer cannot continue' => 'Установка не может быть продолжена', + 'Preparing to install' => 'Подготовка к установке', + 'File %s' => 'Файл %s', + 'is exists' => 'найден', + 'is not exists' => 'не найден', + 'You have to rename the following files:' => 'Вы должны переименовать следующие файлы:', + 'File config.php should be empty.' => 'Файл config.php должен быть пустым.', + 'is writeable' => 'доступен для записи', + 'is not writeable' => 'недоступен для записи', + 'Filesystem need to be prepared for installation' => 'Файловая система должна быть подготовлена к установке', + 'System is ready to be installed' => 'Система готова к установке', + 'Agreement' => 'Соглашение', + 'By installing Zira CMS you are agree to the following terms and conditions:' => 'Устанавливая Zira CMS, вы соглашаетесь со следующими условиями:', + 'Zira CMS is a free software and can be used in both commercial and non-commercial projects without limitation.' => 'Zira CMS - это бесплатная система и может быть использована, как в коммерческих, так и в некоммерческих проектах без ограничений.', + 'You can modify system files for your needs, but Zira CMS\' copyright string with active link to %s must exists on every generated page.' => 'Вы можете модифицировать системные файлы для своих нужд, однако авторская строка Zira CMS с активной ссылкой на %s должна присутствовать на каждой сгенерированной странице.', + 'If this doesn\'t fit your needs, you may want to purchase a license. Please visit our %s for further details.' => 'Если это вам не подходит, вы можете приобрести лицензию. Пожалуйста посетите наш %s для дальнейших инструкций.', + 'website' => 'вебсайт', + 'If you have any questions, feel free to %s.' => 'Если у вас есть какие-либо вопросы, вы можете %s.', + 'contact us' => 'связаться с нами', + 'Don\'t forget to visit our forum and share your impressions with other users.' => 'Не забудьте посетить наш форум и поделиться своими впечатлениями с другими пользователями.', + 'Ready to proceed ?' => 'Готовы приступить ?', + 'Required information' => 'Необходимая информация', + 'Please fill out form fields' => 'Пожалуйста, заполните поля формы', + 'Website name' => 'Название сайта', + 'Website slogan' => 'Слоган сайта', + 'Invalid character detected' => 'Обнаружен некорректный символ', + 'Contact Email' => 'Контактный Email', + 'First name' => 'Имя', + 'Last name' => 'Фамилия', + 'Login' => 'Логин', + 'Email' => 'Email', + 'Secret key' => 'Секретный ключ', + 'Administrator' => 'Администратор', + 'Invalid email' => 'Некорректный email', + 'Secret key is too short' => 'Секретный ключ слишком короткий', + 'min. %s chars' => 'мин. %s символов', + 'Console password is too short' => 'Пароль от консоли слишком короткий', + 'Configuration' => 'Конфигурация', + 'Database' => 'База данных', + 'Server' => 'Сервер', + 'Port' => 'Порт', + 'Name' => 'Имя', + 'User' => 'Пользователь', + 'Password' => 'Пароль', + 'Table prefix' => 'Префикс таблиц', + 'Website' => 'Вебсайт', + 'Document root' => 'Корневая директория', + 'Base URL' => 'Базовый URL', + 'Console password' => 'Пароль от консоли', + 'Invalid username' => 'Некорректный логин', + 'Login must contain only letters and numbers' => 'Логин должен содержать только буквы и цифры', + 'Invalid password' => 'Некорректный пароль', + 'Password contain bad characters' => 'Пароль содержит некорректный символ', + 'change only if a problem occurres' => 'измените, если возникнут проблемы', + 'change only if it was detected incorrectly' => 'измените, если определено неверно', + 'leave blank if you\'re not planning to use console' => 'оставьте пустым, если вам не нужна консоль', + 'change to unique string' => 'измените на уникальную строку', + 'enter random chars' => 'введите произвольные символы', + 'Your website must have unique name and slogan!' => 'Ваш сайт должен иметь уникальное название и слоган!', + 'Zira CMS stores data in database. Currently, MySQL 5 and SQLite 3 are supported.' => 'Zira CMS хранит информацию в базе данных. Поддерживаются MySQL 5 и SQLite 3.', + 'Server test:' => 'Проверка сервера:', + 'Please check the specified data once again.' => 'Пожалуйста, проверьте введенные данные еще раз.', + 'Incorrect document root is specified.' => 'Указана некорректная корневая директория.', + 'Incorrect base url is specified.' => 'Указан некорректный базовый URL.', + 'Failed to connect to database.' => 'Невозможно подключиться к базе данных.', + 'Please wait...' => 'Пожалуйста, подождите...', + 'Please wait' => 'Пожалуйста, подождите', + 'Congratulations!' => 'Поздравляем!', + 'Zira CMS is successfully installed.' => 'Zira CMS успешно установлена.', + 'For security reasons turn off write permissions of %s file.' => 'В целях безопасности, защитите файл %s от записи.', + 'Please visit our %s for detailed information.' => 'Пожалуйста, посетите наш %s для получения более подробной информации.', + 'Go to your new %s!' => 'Перейти на ваш новый %s!', + 'Creating database tables' => 'Создание таблиц базы данных', + 'Writing settings to %s' => 'Запись настроек в %s', + 'Creating user' => 'Создание пользователя', + 'Creating home page' => 'Создание главной страницы', + 'Creating news category' => 'Создание категории новостей', + 'Creating menu' => 'Создание меню', + 'Creating news widget' => 'Создание виджета новостей', + 'home' => 'главная', + 'Home page' => 'Главная страница', + 'Welcome to Zira CMS!' => 'Добро пожаловать в Zira CMS!', + 'This is an example page created by installer.' => 'Это пример страницы, созданный установщиком.', + 'news' => 'новости', + 'News' => 'Новости', + 'launch' => 'открытие', + 'Our new website is now open!' => 'Наш новый вебсайт заработал!', + 'Our website is now open for visitors.' => 'Наш вебсайт теперь открыт для посетителей.', + 'File' => 'Файл', + 'Type' => 'Тип', + 'Failed to create database file.' => 'Невозможно создать файл базы данных.' +); \ No newline at end of file diff --git a/languages/ru/oauth.php b/languages/ru/oauth.php new file mode 100644 index 0000000..feae7cf --- /dev/null +++ b/languages/ru/oauth.php @@ -0,0 +1,26 @@ + 'Социальные сети', + 'Connect your website to social networks' => 'Подключите свой сайт к социальным сетям', + 'Login with social networks' => 'Авторизация через социальные сети', + 'Facebook App ID' => 'ID приложения в Facebook', + 'Facebook App Secret' => 'Секретный код приложения в Facebook', + 'Enable Facebook authentication' => 'Включить авторизацию через Facebook', + 'Sorry, this user is disabled' => 'Извините, этот пользователь заблокирован', + 'You have to grant access to your profile' => 'Вы должны предоставить доступ к вашему профилю', + 'Vkontakte App ID' => 'ID приложения в Вконтакте', + 'Vkontakte App Secret' => 'Секретный код приложения в Вконтакте', + 'Enable Vkontakte authentication' => 'Включить авторизацию через Вконтакте', + 'Login with: %s' => 'Войти с помощью: %s', + 'Facebook Page URL' => 'URL страницы на Facebook', + 'Facebook page widget' => 'Виджет страницы на Facebook', + 'Facebook comments widget' => 'Виджет комментариев Facebook', + 'Vkontakte Group ID' => 'ID группы Вконтакте', + 'Vkontakte group widget' => 'Виджет группы Вконтакте', + 'Vkontakte comments widget' => 'Виджет комментариев Вконтакте', + 'Your new account' => 'Ваш новый аккаунт', + 'Hello %s !' => 'Привет %s !', + 'We created an account for you on %s.' => 'Мы создали для вас аккаунт на %s.', + 'Your new password: %s' => 'Ваш новый пароль: %s', + 'You recieved this message, because you logged in to %s first time, using your social network account.' => 'Вы получили это письмо, потому-что вы в первый раз авторизовались на %s, использовав свой аккаунт в социальной сети.' +); \ No newline at end of file diff --git a/languages/ru/ru.js.php b/languages/ru/ru.js.php new file mode 100644 index 0000000..2c9ada5 --- /dev/null +++ b/languages/ru/ru.js.php @@ -0,0 +1,19 @@ + 'Закрыть', + 'Sending' => 'Отправка', + 'Message' => 'Сообщение', + 'Error' => 'Ошибка', + 'Confirmation' => 'Подтверждение', + 'Yes' => 'Да', + 'No' => 'Нет', + 'Cancel' => 'Отмена', + 'Please wait' => 'Пожалуйста, подождите', + 'Load failed' => 'Ошибка загрузки', + 'Are you sure ?' => 'Вы уверены ?', + 'An error occurred' => 'Возникла ошибка', + 'Reply to' => 'Ответ на', + 'Reason' => 'Причина', + 'Please specify the reason' => 'Пожалуйста, укажите причину' +); \ No newline at end of file diff --git a/languages/ru/ru.php b/languages/ru/ru.php new file mode 100644 index 0000000..6e73cdc --- /dev/null +++ b/languages/ru/ru.php @@ -0,0 +1,130 @@ + 'Русский', + 'Page not found' => 'Страница не найдена', + 'Access denied' => 'Доступ запрещен', + 'An error occurred' => 'Возникла ошибка', + 'Browse' => 'Обзор', + 'Close' => 'Закрыть', + 'Sending' => 'Отправка', + 'Message' => 'Сообщение', + 'Error' => 'Ошибка', + 'Please wait' => 'Пожалуйста, подождите', + 'Home' => 'Главная', + 'Sign Up' => 'Регистрация', + 'Sign In' => 'Авторизация', + 'User Signup' => 'Регистрация пользователя', + 'Pick a username and password' => 'Выберите логин и пароль', + 'Submit' => 'Отправить', + 'Username' => 'Логин', + 'Email' => 'Email', + 'Username or Email' => 'Логин или Email', + 'Password' => 'Пароль', + 'Repeat password' => 'Повторите пароль', + 'Enter result' => 'Введите результат', + 'Wrong CAPTCHA result' => 'Неверный результат кода безопасности', + 'User profile' => 'Профиль пользователя', + 'Profile' => 'Личный кабинет', + 'User name' => 'Имя пользователя', + 'First name' => 'Имя', + 'Second name' => 'Фамилия', + 'not specified' => 'не указано', + 'Location' => 'Расположение', + 'Country' => 'Страна', + 'City' => 'Город', + 'Street' => 'Улица', + 'Date of birth' => 'Дата рождения', + 'Phone' => 'Телефон', + 'Group' => 'Группа', + 'Sign-up date' => 'Дата регистрации', + 'Last login date' => 'Дата последнего посещения', + 'Photo' => 'Фото', + 'unknown' => 'неизвестно', + 'Super-Administrators' => 'Супер-администраторы', + 'Administrators' => 'Администраторы', + 'Users' => 'Пользователи', + 'Guests' => 'Гости', + 'User information' => 'Информация о пользователе', + 'Successfully saved' => 'Сохранено успешно', + 'Logout' => 'Выйти', + 'Edit' => 'Редактировать', + 'Invalid character specified' => 'Введен некорректный символ', + 'Invalid date format' => 'Некорректный формат даты', + 'Avatar' => 'Аватара', + 'Verify' => 'Подтвердить', + 'Search' => 'Поиск', + 'Previous' => 'Предыдущие', + 'Next' => 'Следующие', + 'Home page' => 'Главная страница', + 'System dashboard' => 'Панель управления', + 'Dashboard' => 'Панель управления', + 'System' => 'Система', + 'Settings' => 'Настройки', + 'Modules' => 'Модули', + 'Website' => 'Сайт', + 'Web page' => 'Веб-страница', + 'Terminal' => 'Консоль', + 'File Manager' => 'Файловый менеджер', + 'Yes' => 'Да', + 'No' => 'Нет', + 'Confirmation' => 'Подтверждение', + 'OK' => 'OK', + 'Cancel' => 'Отмена', + 'Mail settings' => 'Почтовые настройки', + 'Languages' => 'Языки', + 'Localisation' => 'Локализация', + 'Themes' => 'Темы', + 'Powered by %s' => 'Работает на %s', + 'Error logs' => 'Логи ошибок', + 'Cache' => 'Кэш', + 'Cron' => 'Крон', + 'Categories' => 'Категории', + 'Category: %s' => 'Категория: %s', + 'Widgets' => 'Виджеты', + 'Blocks' => 'Блоки', + 'Records' => 'Записи', + 'Rating: %s' => 'Рейтинг: %s', + 'Comments: %s' => 'Комментарии: %s', + 'Last updated' => 'Последнее обновление', + 'Author' => 'Автор', + 'Gallery' => 'Галерея', + 'Social buttons' => 'Социальные кнопки', + 'View more' => 'Смотреть еще', + 'Page title' => 'Заголовок страницы', + 'Mail' => 'Почта', + 'Top rated' => 'Лучшее', + 'View also' => 'Смотрите также', + 'Most discussed' => 'Обсуждаемое', + 'Comments' => 'Комментарии', + 'Leave a comment' => 'Оставить комментарий', + 'Message should contain at least %s characters' => array('Сообщение должно содержать, хотя-бы, %s символ', 'Сообщение должно содержать, хотя-бы, %s символа', 'Сообщение должно содержать, хотя-бы, %s символов'), + 'Message contains bad character' => 'Сообщение содержит некорректный символ', + 'Thank you. Your message was published' => 'Спасибо. Ваше сообщение опубликовано', + 'Thank you. Your message is awaiting moderation' => 'Спасибо. Ваше сообщение ожидает модерации', + 'Guest' => 'Гость', + 'Reply' => 'Ответить', + '%s to leave a comment' => '%s, чтобы оставить комментарий', + 'Login' => 'Авторизуйтесь', + 'moderator' => 'модератор', + 'New comment was posted' => 'Оставлен новый комментарий', + 'New comment was posted on: %s' => 'Новый комментарий оставлен на: %s', + 'Page URL address: %s' => 'URL адрес страницы: %s', + 'Comment text' => 'Текст комментария', + 'You recieved this message, because your Email address is specified as a notification Email on %s' => 'Вы получили это сообщение, потому-что ваш адрес указан как Email для оповещения на %s', + 'Name' => 'Имя', + 'Invalid name' => 'Некорректное имя', + 'Sorry, your comment is too big' => 'Извините, ваш комментарий слишком длинный', + 'Menu' => 'Меню', + 'Contacts' => 'Контакты', + 'Up' => 'Наверх', + 'Address' => 'Адрес', + 'Vkontakte' => 'Вконтакте', + 'Log In' => 'Войти', + 'Messages' => 'Сообщения', + 'Invalid token' => 'Неверный токен', + 'Posts' => 'Сообщения', + 'Mailing' => 'Рассылка', + 'Authorization' => 'Авторизация', + 'Site map' => 'Карта сайта' +); \ No newline at end of file diff --git a/languages/ru/zira.php b/languages/ru/zira.php new file mode 100644 index 0000000..e471f57 --- /dev/null +++ b/languages/ru/zira.php @@ -0,0 +1,121 @@ + 'Некорректный логин', + 'Invalid email' => 'Некорректный email', + 'Invalid password' => 'Некорректный пароль', + 'Passwords do not match' => 'Пароли не совпадают', + 'At least %s characters required' => array('Введите минимум %s символ','Введите минимум %s символа','Введите минимум %s символов'), + 'Enter a valid email' => 'Укажите существующий email', + 'Enter password again' => 'Введите пароль еще раз', + 'Login must contain only letters and numbers' => 'Логин должен содержать только буквы и цифры', + 'Password contain bad characters' => 'Пароль содержит некорректный символ', + 'Specified login already exists' => 'Указанный логин уже существует', + 'Specified email already exists' => 'Указанный email уже существует', + 'Email confirmation' => 'Подтверждение почтового адреса', + 'Verification' => 'Верификация', + 'Hello %s !' => 'Привет %s !', + 'Please confirm your Email address.' => 'Пожалуйста, подтвердите ваш Email адрес.', + 'Your verification code: %s' => 'Ваш код подтверждения: %s', + 'Enter code on the following page %s' => 'Введите код на следующей странице %s', + 'You recieved this message, because your Email address was specified during registration process on %s' => 'Вы получили это письмо, потому-что ваш Email адрес был указан в процессе регистрации на %s', + 'Enter your username or email' => 'Введите ваш логин или Email', + 'Email or password incorrect' => 'Неверный Email или пароль', + 'Username or password incorrect' => 'Неверный логин или пароль', + 'Verification code was sent to your Email address' => 'Код подтверждения был отправлен на ваш почтовый адрес', + 'Verification code' => 'Код подтверждения', + 'Incorrect verification code' => 'Неверный код подтверждения', + 'Did not recieve verification code ?' => 'Не получили код подтверждения ?', + 'Send confirmation code' => 'Отправка кода подтверждения', + 'User not found' => 'Пользователь не найден', + 'Remember me' => 'Запомнить меня', + 'Please enter your first name' => 'Пожалуйста, укажите ваше имя', + 'Please enter your second name' => 'Пожалуйста, укажите вашу фамилию', + 'Forgot password ?' => 'Забыли пароль ?', + 'Recovery' => 'Восстановление', + 'Password recovery' => 'Восстановление пароля', + 'Verification code will be sent to your Email address' => 'Код подтверждения будет отправлен на ваш почтовый адрес', + 'We recieved password recovery request for your account.' => 'Мы получили запрос на восстановление пароля к вашему аккаунту.', + 'You recieved this message, because your Email address or login was specified during password recovery process on %s. If it was not you, ignore this message' => 'Вы получили это письмо, потому-что ваш Email или логин был указан в процессе восстановления пароля на %s. Если это были не вы, игнорируйте это сообщение', + 'Your new password: %s' => 'Ваш новый пароль: %s', + 'You can now sign in on the following page %s' => 'Теперь вы можете авторизоваться на следуюшей странице %s', + 'You recieved this message, because your Email address or login was specified during password recovery process on %s' => 'Вы получили это письмо, потому-что ваш Email или логин был указан в процессе восстановления пароля на %s', + 'Your new password' => 'Ваш новый пароль', + 'Change password' => 'Смена пароля', + 'New password' => 'Новый пароль', + 'Current password' => 'Текущий пароль', + 'Current password incorrect' => 'Неверный текущий пароль', + 'Edit profile' => 'Редактировать профиль', + 'Edit email' => 'Изменить Email', + 'Edit password' => 'Изменить пароль', + 'Change email' => 'Смена почтового адреса', + 'Change profile' => 'Редактирование профиля', + 'Information' => 'Информация', + 'Please enter your first name and second name' => 'Пожалуйста, укажите ваше имя и фамилию', + 'Phone should be specified in international format' => 'Телефон должен быть указан в международном формате', + 'Edit photo' => 'Изменить фото', + 'Change photo' => 'Смена фото', + 'Allowed file extensions: %s' => 'Допустимые расширения файлов: %s', + 'Invalid image file' => 'Некорректный файл изображения', + 'Delete photo' => 'Удалить фото', + 'Remove photo' => 'Удаление фото', + 'Please enter your password' => 'Пожалуйста, введите пароль', + 'Change username' => 'Смена логина', + 'Edit username' => 'Изменить логин', + 'Edit avatar' => 'Редактировать аватару', + 'Change avatar' => 'Редактирование аватары', + 'Select your desired area' => 'Выберите желаемую область фотографии', + 'Photo size should be at least %s pixels' => 'Фотография должна быть размером не меньше %s пикселей', + 'Cron executed less than an hour ago' => 'Крон запускался меньше часа назад', + 'Database cleaned up' => 'База данных почищена', + 'Languages panel' => 'Языковая панель', + 'Logo' => 'Логотип', + 'Invalid search text' => 'Некорректный текст для поиска', + 'Search text contains bad character' => 'Текст для поиска содержит некорректный символ', + 'Search results' => 'Результаты поиска', + 'Your search did not match any documents' => 'По вашему запросу ничего не найдено', + 'Search this site' => 'Поиск по сайту', + 'Enter search text' => 'Введите текст для поиска', + 'Feedback' => 'Обратная связь', + 'Please specify your name and Email address' => 'Пожалуйста, укажите ваше имя и почтовый адрес', + 'Sorry, your message is too big' => 'Извините, ваше сообщение слишком длинное', + 'You recieved this message, because your Email address is specified as a contact email on %s' => 'Вы получили это сообщение, потому-что ваш адрес указан как Email для контактов на %s', + 'Name: %s' => 'Имя: %s', + 'Email: %s' => 'Email: %s', + 'Sorry, could not send your message. Try later' => 'Извините, ваше сообщение не отправлено. Попробуйте позже', + 'Thank you. Your message was sent' => 'Спасибо. Ваше сообщение отправлено', + 'not specified' => 'не указано', + 'Sorry, contacts are not specified' => 'Извините, контакты не указаны', + 'Send message' => 'Отправить сообщение', + 'New message' => 'Новое сообщение', + 'Subject' => 'Тема', + 'Message to: %s' => 'Сообщение для: %s', + 'Please specify the subject of your message' => 'Пожалуйста, укажите тему вашего сообщения', + 'Message sent' => 'Сообщение отправлено', + 'Subject contains bad character' => 'Тема содержит некорректный символ', + 'User deleted' => 'Пользователь удален', + 'You have no messages' => 'У вас нет сообщений', + 'My account' => 'Мой профиль', + 'You have new message' => 'У вас новое сообщение', + 'You have new message from %s.' => 'Вы получили новое сообщение от пользователя: %s.', + 'Log in %s to read it.' => 'Авторизуйтесь %s, чтобы прочитать его.', + 'You recieved this message, because you are subscribed to Email notifications on %s' => 'Вы получили это письмо, потому-что вы подписаны на Email оповещения на %s', + 'recieve notifications' => 'получать оповещения', + 'Mark as read' => 'Пометить как прочитанное', + 'Mark all as read' => 'Пометить все как прочитанное', + 'Delete' => 'Удалить', + 'Comments posted' => 'Оставлено комментариев', + 'Verified' => 'Проверен', + 'Add to black list' => 'Добавить в черный список', + 'Remove from black list' => 'Удалить из черного списка', + 'Sorry, you were added to black list. Reason: %s' => 'Извините, вы были добавлены в чёрный список. Причина: %s', + 'Sorry, you are in %s\'s black list' => 'Извините, вы в черном списке пользователя %s', + 'Please enter user login, full name or ID' => 'Пожалуйста, введите логин, полное имя или ID пользователя', + 'Please enter correct user login, full name or ID' => 'Пожалуйста, введите правильный логин, полное имя или ID пользователя', + 'User' => 'Пользователь', + 'Recipient' => 'Получатель', + 'Add recipient' => 'Добавить получателя', + 'Compose message' => 'Написать сообщение', + 'No recipients' => 'Нет получателей', + 'Conversation is closed' => 'Тема закрыта' +); \ No newline at end of file diff --git a/oauth/controllers/login.php b/oauth/controllers/login.php new file mode 100644 index 0000000..f2f0357 --- /dev/null +++ b/oauth/controllers/login.php @@ -0,0 +1,220 @@ +includeFacebookSdk(); + + $enabled = Zira\Config::get('oauth_fb_on'); + $app_id = Zira\Config::get('oauth_fb_app_id'); + $app_secret = Zira\Config::get('oauth_fb_app_secret'); + + if (!$enabled || !$app_id || !$app_secret) { + Zira\Response::forbidden(); + } + + $fb = new \Facebook\Facebook([ + 'app_id' => $app_id, + 'app_secret' => $app_secret, + 'default_graph_version' => 'v2.5', + ]); + + // getting access token + $jsHelper = $fb->getJavaScriptHelper(); + try { + $accessToken = $jsHelper->getAccessToken(); + } catch(\Facebook\Exceptions\FacebookResponseException $e) { + Zira\Response::exception($e); + } catch(\Facebook\Exceptions\FacebookSDKException $e) { + Zira\Response::exception($e); + } + + $fb->setDefaultAccessToken($accessToken); + + // getting user data + try { + $response = $fb->get(Oauth\Models\Oauth::FACEBOOK_API_URL); + $userNode = $response->getGraphUser(); + } catch(\Facebook\Exceptions\FacebookResponseException $e) { + Zira\Response::exception($e); + } catch(\Facebook\Exceptions\FacebookSDKException $e) { + Zira\Response::exception($e); + } + + $id = $userNode->getId(); + $name = $userNode->getName(); + $email = $userNode->getField('email'); + + if (empty($id) || empty($name)) { + Zira\Response::error(Zira\Locale::tm('You have to grant access to your profile', 'oauth')); + } + + // checking if user is already registered + $fb_user = Oauth\Models\Fbuser::getCollection() + ->where('fb_id','=',$id) + ->get(0); + + if (!$fb_user) { + // registering new user if not exists + if (!empty($email)) { + $user = Oauth\Models\Oauth::getUserByEmail($email); + } + if (empty($user)) { + // new user + $username = 'fb_' . $id; + $name_parts = explode(' ', $name); + if (count($name_parts) > 1) { + $firstname = array_shift($name_parts); + $secondname = implode(' ', $name_parts); + } else { + $firstname = $name; + $secondname = $name; + } + $user = Oauth\Models\Oauth::registerUser($username, $email ? $email : $id.'@facebook.com', $firstname, $secondname, !empty($email)); + } + + // saving facebook user + $fb_user = new Oauth\Models\Fbuser(); + $fb_user->user_id = $user->id; + $fb_user->fb_id = $id; + $fb_user->email = $email ? $email : ''; + $fb_user->profile_name = $name; + $fb_user->date_created = date('Y-m-d H:i:s'); + $fb_user->save(); + } else { + // getting existing user + $user = new Zira\Models\User($fb_user->user_id); + if (!$user->loaded()) { + Zira\Response::error(Zira\Locale::tm('Sorry, this user is disabled', 'oauth')); + } + } + + if (!Oauth\Models\Oauth::isUserActive($user, !empty($email))) { + Zira\Response::error(Zira\Locale::tm('Sorry, this user is disabled', 'oauth')); + } + + // logging in and redirecting + Zira\User::onUserLogin(false); + + $redirect = Zira\Request::get('redirect'); + if (!empty($redirect) && strpos($redirect,'//')===false && strpos($redirect, '.')===false) { + if ($redirect=='dash') Zira\Helper::setAddingLanguageToUrl(false); + Zira\Response::redirect($redirect); + } else { + Zira\Response::redirect('user/profile'); + } + } + + public function vkresponse() { + Zira\View::render(array( + 'code' => Zira\Request::get('code') + ),'oauth/vk-response'); + } + + public function vkontakte() { + $enabled = Zira\Config::get('oauth_vk_on'); + $app_id = Zira\Config::get('oauth_vk_app_id'); + $app_secret = Zira\Config::get('oauth_vk_app_secret'); + + if (!$enabled || !$app_id || !$app_secret) { + Zira\Response::forbidden(); + } + + $code = Zira\Request::get('code'); + if (empty($code)) { + Zira\Response::error(Zira\Locale::tm('You have to grant access to your profile', 'oauth')); + } + + // getting access token with user_id and email + $response = @file_get_contents(Oauth\Oauth::getVkontakteAccessTokenUrl($code)); + if (empty($response)) { + Zira\Response::error(Zira\Locale::tm('You have to grant access to your profile', 'oauth')); + } + $data = json_decode($response, true); + if (empty($data['user_id'])) { + Zira\Response::error(Zira\Locale::tm('You have to grant access to your profile', 'oauth')); + } + $id = $data['user_id']; + $email = !empty($data['email']) ? $data['email'] : ''; + + // checking if user is already registered + $vk_user = Oauth\Models\Vkuser::getCollection() + ->where('vk_id','=',$id) + ->get(0); + + if (!$vk_user) { + // getting profile name + $response = @file_get_contents(Oauth\Oauth::getVkontakteUserApiUrl($data['access_token'], $data['user_id'])); + if (empty($response)) { + Zira\Response::error(Zira\Locale::tm('You have to grant access to your profile', 'oauth')); + } + $info = json_decode($response, true); + if (empty($info['response']) || + !is_array($info['response']) || + count($info['response'])==0 || + empty($info['response'][0]['first_name']) || + empty($info['response'][0]['last_name']) + ) { + Zira\Response::error(Zira\Locale::tm('You have to grant access to your profile', 'oauth')); + } + $firstname = $info['response'][0]['first_name']; + $secondname = $info['response'][0]['last_name']; + + // registering new user if not exists + if (!empty($email)) { + $user = Oauth\Models\Oauth::getUserByEmail($email); + } + if (empty($user)) { + // new user + $username = 'vk_' . $id; + $user = Oauth\Models\Oauth::registerUser($username, $email ? $email : $id.'@vk.com', $firstname, $secondname, !empty($email)); + } + + // saving vk user + $vk_user = new Oauth\Models\Vkuser(); + $vk_user->user_id = $user->id; + $vk_user->vk_id = $id; + $vk_user->email = $email ? $email : ''; + $vk_user->profile_name = $firstname.' '.$secondname; + $vk_user->date_created = date('Y-m-d H:i:s'); + $vk_user->save(); + } else { + // getting existing user + $user = new Zira\Models\User($vk_user->user_id); + if (!$user->loaded()) { + Zira\Response::error(Zira\Locale::tm('Sorry, this user is disabled', 'oauth')); + } + } + + if (!Oauth\Models\Oauth::isUserActive($user, !empty($email))) { + Zira\Response::error(Zira\Locale::tm('Sorry, this user is disabled', 'oauth')); + } + + // logging in and redirecting + Zira\User::onUserLogin(false); + + $redirect = Zira\Request::get('redirect'); + if (!empty($redirect) && strpos($redirect,'//')===false && strpos($redirect, '.')===false) { + if ($redirect=='dash') Zira\Helper::setAddingLanguageToUrl(false); + Zira\Response::redirect($redirect); + } else { + Zira\Response::redirect('user/profile'); + } + } +} \ No newline at end of file diff --git a/oauth/facebook-sdk-v5/Authentication/AccessToken.php b/oauth/facebook-sdk-v5/Authentication/AccessToken.php new file mode 100644 index 0000000..582ea61 --- /dev/null +++ b/oauth/facebook-sdk-v5/Authentication/AccessToken.php @@ -0,0 +1,160 @@ +value = $accessToken; + if ($expiresAt) { + $this->setExpiresAtFromTimeStamp($expiresAt); + } + } + + /** + * Generate an app secret proof to sign a request to Graph. + * + * @param string $appSecret The app secret. + * + * @return string + */ + public function getAppSecretProof($appSecret) + { + return hash_hmac('sha256', $this->value, $appSecret); + } + + /** + * Getter for expiresAt. + * + * @return \DateTime|null + */ + public function getExpiresAt() + { + return $this->expiresAt; + } + + /** + * Determines whether or not this is an app access token. + * + * @return bool + */ + public function isAppAccessToken() + { + return strpos($this->value, '|') !== false; + } + + /** + * Determines whether or not this is a long-lived token. + * + * @return bool + */ + public function isLongLived() + { + if ($this->expiresAt) { + return $this->expiresAt->getTimestamp() > time() + (60 * 60 * 2); + } + + if ($this->isAppAccessToken()) { + return true; + } + + return false; + } + + /** + * Checks the expiration of the access token. + * + * @return boolean|null + */ + public function isExpired() + { + if ($this->getExpiresAt() instanceof \DateTime) { + return $this->getExpiresAt()->getTimestamp() < time(); + } + + if ($this->isAppAccessToken()) { + return false; + } + + return null; + } + + /** + * Returns the access token as a string. + * + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * Returns the access token as a string. + * + * @return string + */ + public function __toString() + { + return $this->getValue(); + } + + /** + * Setter for expires_at. + * + * @param int $timeStamp + */ + protected function setExpiresAtFromTimeStamp($timeStamp) + { + $dt = new \DateTime(); + $dt->setTimestamp($timeStamp); + $this->expiresAt = $dt; + } +} diff --git a/oauth/facebook-sdk-v5/Authentication/AccessTokenMetadata.php b/oauth/facebook-sdk-v5/Authentication/AccessTokenMetadata.php new file mode 100644 index 0000000..f302a6d --- /dev/null +++ b/oauth/facebook-sdk-v5/Authentication/AccessTokenMetadata.php @@ -0,0 +1,390 @@ +metadata = $metadata['data']; + + $this->castTimestampsToDateTime(); + } + + /** + * Returns a value from the metadata. + * + * @param string $field The property to retrieve. + * @param mixed $default The default to return if the property doesn't exist. + * + * @return mixed + */ + public function getField($field, $default = null) + { + if (isset($this->metadata[$field])) { + return $this->metadata[$field]; + } + + return $default; + } + + /** + * Returns a value from the metadata. + * + * @param string $field The property to retrieve. + * @param mixed $default The default to return if the property doesn't exist. + * + * @return mixed + * + * @deprecated 5.0.0 getProperty() has been renamed to getField() + * @todo v6: Remove this method + */ + public function getProperty($field, $default = null) + { + return $this->getField($field, $default); + } + + /** + * Returns a value from a child property in the metadata. + * + * @param string $parentField The parent property. + * @param string $field The property to retrieve. + * @param mixed $default The default to return if the property doesn't exist. + * + * @return mixed + */ + public function getChildProperty($parentField, $field, $default = null) + { + if (!isset($this->metadata[$parentField])) { + return $default; + } + + if (!isset($this->metadata[$parentField][$field])) { + return $default; + } + + return $this->metadata[$parentField][$field]; + } + + /** + * Returns a value from the error metadata. + * + * @param string $field The property to retrieve. + * @param mixed $default The default to return if the property doesn't exist. + * + * @return mixed + */ + public function getErrorProperty($field, $default = null) + { + return $this->getChildProperty('error', $field, $default); + } + + /** + * Returns a value from the "metadata" metadata. *Brain explodes* + * + * @param string $field The property to retrieve. + * @param mixed $default The default to return if the property doesn't exist. + * + * @return mixed + */ + public function getMetadataProperty($field, $default = null) + { + return $this->getChildProperty('metadata', $field, $default); + } + + /** + * The ID of the application this access token is for. + * + * @return string|null + */ + public function getAppId() + { + return $this->getField('app_id'); + } + + /** + * Name of the application this access token is for. + * + * @return string|null + */ + public function getApplication() + { + return $this->getField('application'); + } + + /** + * Any error that a request to the graph api + * would return due to the access token. + * + * @return bool|null + */ + public function isError() + { + return $this->getField('error') !== null; + } + + /** + * The error code for the error. + * + * @return int|null + */ + public function getErrorCode() + { + return $this->getErrorProperty('code'); + } + + /** + * The error message for the error. + * + * @return string|null + */ + public function getErrorMessage() + { + return $this->getErrorProperty('message'); + } + + /** + * The error subcode for the error. + * + * @return int|null + */ + public function getErrorSubcode() + { + return $this->getErrorProperty('subcode'); + } + + /** + * DateTime when this access token expires. + * + * @return \DateTime|null + */ + public function getExpiresAt() + { + return $this->getField('expires_at'); + } + + /** + * Whether the access token is still valid or not. + * + * @return boolean|null + */ + public function getIsValid() + { + return $this->getField('is_valid'); + } + + /** + * DateTime when this access token was issued. + * + * Note that the issued_at field is not returned + * for short-lived access tokens. + * + * @see https://developers.facebook.com/docs/facebook-login/access-tokens#debug + * + * @return \DateTime|null + */ + public function getIssuedAt() + { + return $this->getField('issued_at'); + } + + /** + * General metadata associated with the access token. + * Can contain data like 'sso', 'auth_type', 'auth_nonce'. + * + * @return array|null + */ + public function getMetadata() + { + return $this->getField('metadata'); + } + + /** + * The 'sso' child property from the 'metadata' parent property. + * + * @return string|null + */ + public function getSso() + { + return $this->getMetadataProperty('sso'); + } + + /** + * The 'auth_type' child property from the 'metadata' parent property. + * + * @return string|null + */ + public function getAuthType() + { + return $this->getMetadataProperty('auth_type'); + } + + /** + * The 'auth_nonce' child property from the 'metadata' parent property. + * + * @return string|null + */ + public function getAuthNonce() + { + return $this->getMetadataProperty('auth_nonce'); + } + + /** + * For impersonated access tokens, the ID of + * the page this token contains. + * + * @return string|null + */ + public function getProfileId() + { + return $this->getField('profile_id'); + } + + /** + * List of permissions that the user has granted for + * the app in this access token. + * + * @return array + */ + public function getScopes() + { + return $this->getField('scopes'); + } + + /** + * The ID of the user this access token is for. + * + * @return string|null + */ + public function getUserId() + { + return $this->getField('user_id'); + } + + /** + * Ensures the app ID from the access token + * metadata is what we expect. + * + * @param string $appId + * + * @throws FacebookSDKException + */ + public function validateAppId($appId) + { + if ($this->getAppId() !== $appId) { + throw new FacebookSDKException('Access token metadata contains unexpected app ID.', 401); + } + } + + /** + * Ensures the user ID from the access token + * metadata is what we expect. + * + * @param string $userId + * + * @throws FacebookSDKException + */ + public function validateUserId($userId) + { + if ($this->getUserId() !== $userId) { + throw new FacebookSDKException('Access token metadata contains unexpected user ID.', 401); + } + } + + /** + * Ensures the access token has not expired yet. + * + * @throws FacebookSDKException + */ + public function validateExpiration() + { + if (!$this->getExpiresAt() instanceof \DateTime) { + return; + } + + if ($this->getExpiresAt()->getTimestamp() < time()) { + throw new FacebookSDKException('Inspection of access token metadata shows that the access token has expired.', 401); + } + } + + /** + * Converts a unix timestamp into a DateTime entity. + * + * @param int $timestamp + * + * @return \DateTime + */ + private function convertTimestampToDateTime($timestamp) + { + $dt = new \DateTime(); + $dt->setTimestamp($timestamp); + + return $dt; + } + + /** + * Casts the unix timestamps as DateTime entities. + */ + private function castTimestampsToDateTime() + { + foreach (static::$dateProperties as $key) { + if (isset($this->metadata[$key])) { + $this->metadata[$key] = $this->convertTimestampToDateTime($this->metadata[$key]); + } + } + } +} diff --git a/oauth/facebook-sdk-v5/Authentication/OAuth2Client.php b/oauth/facebook-sdk-v5/Authentication/OAuth2Client.php new file mode 100644 index 0000000..8e364ec --- /dev/null +++ b/oauth/facebook-sdk-v5/Authentication/OAuth2Client.php @@ -0,0 +1,292 @@ +app = $app; + $this->client = $client; + $this->graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION; + } + + /** + * Returns the last FacebookRequest that was sent. + * Useful for debugging and testing. + * + * @return FacebookRequest|null + */ + public function getLastRequest() + { + return $this->lastRequest; + } + + /** + * Get the metadata associated with the access token. + * + * @param AccessToken|string $accessToken The access token to debug. + * + * @return AccessTokenMetadata + */ + public function debugToken($accessToken) + { + $accessToken = $accessToken instanceof AccessToken ? $accessToken->getValue() : $accessToken; + $params = ['input_token' => $accessToken]; + + $this->lastRequest = new FacebookRequest( + $this->app, + $this->app->getAccessToken(), + 'GET', + '/debug_token', + $params, + null, + $this->graphVersion + ); + $response = $this->client->sendRequest($this->lastRequest); + $metadata = $response->getDecodedBody(); + + return new AccessTokenMetadata($metadata); + } + + /** + * Generates an authorization URL to begin the process of authenticating a user. + * + * @param string $redirectUrl The callback URL to redirect to. + * @param array $scope An array of permissions to request. + * @param string $state The CSPRNG-generated CSRF value. + * @param array $params An array of parameters to generate URL. + * @param string $separator The separator to use in http_build_query(). + * + * @return string + */ + public function getAuthorizationUrl($redirectUrl, $state, array $scope = [], array $params = [], $separator = '&') + { + $params += [ + 'client_id' => $this->app->getId(), + 'state' => $state, + 'response_type' => 'code', + 'sdk' => 'php-sdk-' . Facebook::VERSION, + 'redirect_uri' => $redirectUrl, + 'scope' => implode(',', $scope) + ]; + + return static::BASE_AUTHORIZATION_URL . '/' . $this->graphVersion . '/dialog/oauth?' . http_build_query($params, null, $separator); + } + + /** + * Get a valid access token from a code. + * + * @param string $code + * @param string $redirectUri + * + * @return AccessToken + * + * @throws FacebookSDKException + */ + public function getAccessTokenFromCode($code, $redirectUri = '') + { + $params = [ + 'code' => $code, + 'redirect_uri' => $redirectUri, + ]; + + return $this->requestAnAccessToken($params); + } + + /** + * Exchanges a short-lived access token with a long-lived access token. + * + * @param AccessToken|string $accessToken + * + * @return AccessToken + * + * @throws FacebookSDKException + */ + public function getLongLivedAccessToken($accessToken) + { + $accessToken = $accessToken instanceof AccessToken ? $accessToken->getValue() : $accessToken; + $params = [ + 'grant_type' => 'fb_exchange_token', + 'fb_exchange_token' => $accessToken, + ]; + + return $this->requestAnAccessToken($params); + } + + /** + * Get a valid code from an access token. + * + * @param AccessToken|string $accessToken + * @param string $redirectUri + * + * @return AccessToken + * + * @throws FacebookSDKException + */ + public function getCodeFromLongLivedAccessToken($accessToken, $redirectUri = '') + { + $params = [ + 'redirect_uri' => $redirectUri, + ]; + + $response = $this->sendRequestWithClientParams('/oauth/client_code', $params, $accessToken); + $data = $response->getDecodedBody(); + + if (!isset($data['code'])) { + throw new FacebookSDKException('Code was not returned from Graph.', 401); + } + + return $data['code']; + } + + /** + * Send a request to the OAuth endpoint. + * + * @param array $params + * + * @return AccessToken + * + * @throws FacebookSDKException + */ + protected function requestAnAccessToken(array $params) + { + $response = $this->sendRequestWithClientParams('/oauth/access_token', $params); + $data = $response->getDecodedBody(); + + if (!isset($data['access_token'])) { + throw new FacebookSDKException('Access token was not returned from Graph.', 401); + } + + // Graph returns two different key names for expiration time + // on the same endpoint. Doh! :/ + $expiresAt = 0; + if (isset($data['expires'])) { + // For exchanging a short lived token with a long lived token. + // The expiration time in seconds will be returned as "expires". + $expiresAt = time() + $data['expires']; + } elseif (isset($data['expires_in'])) { + // For exchanging a code for a short lived access token. + // The expiration time in seconds will be returned as "expires_in". + // See: https://developers.facebook.com/docs/facebook-login/access-tokens#long-via-code + $expiresAt = time() + $data['expires_in']; + } + + return new AccessToken($data['access_token'], $expiresAt); + } + + /** + * Send a request to Graph with an app access token. + * + * @param string $endpoint + * @param array $params + * @param string|null $accessToken + * + * @return FacebookResponse + * + * @throws FacebookResponseException + */ + protected function sendRequestWithClientParams($endpoint, array $params, $accessToken = null) + { + $params += $this->getClientParams(); + + $accessToken = $accessToken ?: $this->app->getAccessToken(); + + $this->lastRequest = new FacebookRequest( + $this->app, + $accessToken, + 'GET', + $endpoint, + $params, + null, + $this->graphVersion + ); + + return $this->client->sendRequest($this->lastRequest); + } + + /** + * Returns the client_* params for OAuth requests. + * + * @return array + */ + protected function getClientParams() + { + return [ + 'client_id' => $this->app->getId(), + 'client_secret' => $this->app->getSecret(), + ]; + } +} diff --git a/oauth/facebook-sdk-v5/Exceptions/FacebookAuthenticationException.php b/oauth/facebook-sdk-v5/Exceptions/FacebookAuthenticationException.php new file mode 100644 index 0000000..449cf93 --- /dev/null +++ b/oauth/facebook-sdk-v5/Exceptions/FacebookAuthenticationException.php @@ -0,0 +1,33 @@ +response = $response; + $this->responseData = $response->getDecodedBody(); + + $errorMessage = $this->get('message', 'Unknown error from Graph.'); + $errorCode = $this->get('code', -1); + + parent::__construct($errorMessage, $errorCode, $previousException); + } + + /** + * A factory for creating the appropriate exception based on the response from Graph. + * + * @param FacebookResponse $response The response that threw the exception. + * + * @return FacebookResponseException + */ + public static function create(FacebookResponse $response) + { + $data = $response->getDecodedBody(); + + if (!isset($data['error']['code']) && isset($data['code'])) { + $data = ['error' => $data]; + } + + $code = isset($data['error']['code']) ? $data['error']['code'] : null; + $message = isset($data['error']['message']) ? $data['error']['message'] : 'Unknown error from Graph.'; + + $previousException = null; + + if (isset($data['error']['error_subcode'])) { + switch ($data['error']['error_subcode']) { + // Other authentication issues + case 458: + case 459: + case 460: + case 463: + case 464: + case 467: + return new static($response, new FacebookAuthenticationException($message, $code)); + } + } + + switch ($code) { + // Login status or token expired, revoked, or invalid + case 100: + case 102: + case 190: + return new static($response, new FacebookAuthenticationException($message, $code)); + + // Server issue, possible downtime + case 1: + case 2: + return new static($response, new FacebookServerException($message, $code)); + + // API Throttling + case 4: + case 17: + case 341: + return new static($response, new FacebookThrottleException($message, $code)); + + // Duplicate Post + case 506: + return new static($response, new FacebookClientException($message, $code)); + } + + // Missing Permissions + if ($code == 10 || ($code >= 200 && $code <= 299)) { + return new static($response, new FacebookAuthorizationException($message, $code)); + } + + // OAuth authentication error + if (isset($data['error']['type']) && $data['error']['type'] === 'OAuthException') { + return new static($response, new FacebookAuthenticationException($message, $code)); + } + + // All others + return new static($response, new FacebookOtherException($message, $code)); + } + + /** + * Checks isset and returns that or a default value. + * + * @param string $key + * @param mixed $default + * + * @return mixed + */ + private function get($key, $default = null) + { + if (isset($this->responseData['error'][$key])) { + return $this->responseData['error'][$key]; + } + + return $default; + } + + /** + * Returns the HTTP status code + * + * @return int + */ + public function getHttpStatusCode() + { + return $this->response->getHttpStatusCode(); + } + + /** + * Returns the sub-error code + * + * @return int + */ + public function getSubErrorCode() + { + return $this->get('error_subcode', -1); + } + + /** + * Returns the error type + * + * @return string + */ + public function getErrorType() + { + return $this->get('type', ''); + } + + /** + * Returns the raw response used to create the exception. + * + * @return string + */ + public function getRawResponse() + { + return $this->response->getBody(); + } + + /** + * Returns the decoded response used to create the exception. + * + * @return array + */ + public function getResponseData() + { + return $this->responseData; + } + + /** + * Returns the response entity used to create the exception. + * + * @return FacebookResponse + */ + public function getResponse() + { + return $this->response; + } +} diff --git a/oauth/facebook-sdk-v5/Exceptions/FacebookSDKException.php b/oauth/facebook-sdk-v5/Exceptions/FacebookSDKException.php new file mode 100644 index 0000000..03219b0 --- /dev/null +++ b/oauth/facebook-sdk-v5/Exceptions/FacebookSDKException.php @@ -0,0 +1,33 @@ +app = new FacebookApp($appId, $appSecret); + + $httpClientHandler = null; + if (isset($config['http_client_handler'])) { + if ($config['http_client_handler'] instanceof FacebookHttpClientInterface) { + $httpClientHandler = $config['http_client_handler']; + } elseif ($config['http_client_handler'] === 'curl') { + $httpClientHandler = new FacebookCurlHttpClient(); + } elseif ($config['http_client_handler'] === 'stream') { + $httpClientHandler = new FacebookStreamHttpClient(); + } elseif ($config['http_client_handler'] === 'guzzle') { + $httpClientHandler = new FacebookGuzzleHttpClient(); + } else { + throw new \InvalidArgumentException('The http_client_handler must be set to "curl", "stream", "guzzle", or be an instance of Facebook\HttpClients\FacebookHttpClientInterface'); + } + } + + $enableBeta = isset($config['enable_beta_mode']) && $config['enable_beta_mode'] === true; + $this->client = new FacebookClient($httpClientHandler, $enableBeta); + + if (isset($config['url_detection_handler'])) { + if ($config['url_detection_handler'] instanceof UrlDetectionInterface) { + $this->urlDetectionHandler = $config['url_detection_handler']; + } else { + throw new \InvalidArgumentException('The url_detection_handler must be an instance of Facebook\Url\UrlDetectionInterface'); + } + } + + if (isset($config['pseudo_random_string_generator'])) { + if ($config['pseudo_random_string_generator'] instanceof PseudoRandomStringGeneratorInterface) { + $this->pseudoRandomStringGenerator = $config['pseudo_random_string_generator']; + } elseif ($config['pseudo_random_string_generator'] === 'mcrypt') { + $this->pseudoRandomStringGenerator = new McryptPseudoRandomStringGenerator(); + } elseif ($config['pseudo_random_string_generator'] === 'openssl') { + $this->pseudoRandomStringGenerator = new OpenSslPseudoRandomStringGenerator(); + } elseif ($config['pseudo_random_string_generator'] === 'urandom') { + $this->pseudoRandomStringGenerator = new UrandomPseudoRandomStringGenerator(); + } else { + throw new \InvalidArgumentException('The pseudo_random_string_generator must be set to "mcrypt", "openssl", or "urandom", or be an instance of Facebook\PseudoRandomString\PseudoRandomStringGeneratorInterface'); + } + } + + if (isset($config['persistent_data_handler'])) { + if ($config['persistent_data_handler'] instanceof PersistentDataInterface) { + $this->persistentDataHandler = $config['persistent_data_handler']; + } elseif ($config['persistent_data_handler'] === 'session') { + $this->persistentDataHandler = new FacebookSessionPersistentDataHandler(); + } elseif ($config['persistent_data_handler'] === 'memory') { + $this->persistentDataHandler = new FacebookMemoryPersistentDataHandler(); + } else { + throw new \InvalidArgumentException('The persistent_data_handler must be set to "session", "memory", or be an instance of Facebook\PersistentData\PersistentDataInterface'); + } + } + + if (isset($config['default_access_token'])) { + $this->setDefaultAccessToken($config['default_access_token']); + } + + if (isset($config['default_graph_version'])) { + $this->defaultGraphVersion = $config['default_graph_version']; + } else { + // @todo v6: Throw an InvalidArgumentException if "default_graph_version" is not set + $this->defaultGraphVersion = static::DEFAULT_GRAPH_VERSION; + } + } + + /** + * Returns the FacebookApp entity. + * + * @return FacebookApp + */ + public function getApp() + { + return $this->app; + } + + /** + * Returns the FacebookClient service. + * + * @return FacebookClient + */ + public function getClient() + { + return $this->client; + } + + /** + * Returns the OAuth 2.0 client service. + * + * @return OAuth2Client + */ + public function getOAuth2Client() + { + if (!$this->oAuth2Client instanceof OAuth2Client) { + $app = $this->getApp(); + $client = $this->getClient(); + $this->oAuth2Client = new OAuth2Client($app, $client, $this->defaultGraphVersion); + } + + return $this->oAuth2Client; + } + + /** + * Returns the last response returned from Graph. + * + * @return FacebookResponse|FacebookBatchResponse|null + */ + public function getLastResponse() + { + return $this->lastResponse; + } + + /** + * Returns the URL detection handler. + * + * @return UrlDetectionInterface + */ + public function getUrlDetectionHandler() + { + if (!$this->urlDetectionHandler instanceof UrlDetectionInterface) { + $this->urlDetectionHandler = new FacebookUrlDetectionHandler(); + } + + return $this->urlDetectionHandler; + } + + /** + * Returns the default AccessToken entity. + * + * @return AccessToken|null + */ + public function getDefaultAccessToken() + { + return $this->defaultAccessToken; + } + + /** + * Sets the default access token to use with requests. + * + * @param AccessToken|string $accessToken The access token to save. + * + * @throws \InvalidArgumentException + */ + public function setDefaultAccessToken($accessToken) + { + if (is_string($accessToken)) { + $this->defaultAccessToken = new AccessToken($accessToken); + + return; + } + + if ($accessToken instanceof AccessToken) { + $this->defaultAccessToken = $accessToken; + + return; + } + + throw new \InvalidArgumentException('The default access token must be of type "string" or Facebook\AccessToken'); + } + + /** + * Returns the default Graph version. + * + * @return string + */ + public function getDefaultGraphVersion() + { + return $this->defaultGraphVersion; + } + + /** + * Returns the redirect login helper. + * + * @return FacebookRedirectLoginHelper + */ + public function getRedirectLoginHelper() + { + return new FacebookRedirectLoginHelper( + $this->getOAuth2Client(), + $this->persistentDataHandler, + $this->urlDetectionHandler, + $this->pseudoRandomStringGenerator + ); + } + + /** + * Returns the JavaScript helper. + * + * @return FacebookJavaScriptHelper + */ + public function getJavaScriptHelper() + { + return new FacebookJavaScriptHelper($this->app, $this->client, $this->defaultGraphVersion); + } + + /** + * Returns the canvas helper. + * + * @return FacebookCanvasHelper + */ + public function getCanvasHelper() + { + return new FacebookCanvasHelper($this->app, $this->client, $this->defaultGraphVersion); + } + + /** + * Returns the page tab helper. + * + * @return FacebookPageTabHelper + */ + public function getPageTabHelper() + { + return new FacebookPageTabHelper($this->app, $this->client, $this->defaultGraphVersion); + } + + /** + * Sends a GET request to Graph and returns the result. + * + * @param string $endpoint + * @param AccessToken|string|null $accessToken + * @param string|null $eTag + * @param string|null $graphVersion + * + * @return FacebookResponse + * + * @throws FacebookSDKException + */ + public function get($endpoint, $accessToken = null, $eTag = null, $graphVersion = null) + { + return $this->sendRequest( + 'GET', + $endpoint, + $params = [], + $accessToken, + $eTag, + $graphVersion + ); + } + + /** + * Sends a POST request to Graph and returns the result. + * + * @param string $endpoint + * @param array $params + * @param AccessToken|string|null $accessToken + * @param string|null $eTag + * @param string|null $graphVersion + * + * @return FacebookResponse + * + * @throws FacebookSDKException + */ + public function post($endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null) + { + return $this->sendRequest( + 'POST', + $endpoint, + $params, + $accessToken, + $eTag, + $graphVersion + ); + } + + /** + * Sends a DELETE request to Graph and returns the result. + * + * @param string $endpoint + * @param array $params + * @param AccessToken|string|null $accessToken + * @param string|null $eTag + * @param string|null $graphVersion + * + * @return FacebookResponse + * + * @throws FacebookSDKException + */ + public function delete($endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null) + { + return $this->sendRequest( + 'DELETE', + $endpoint, + $params, + $accessToken, + $eTag, + $graphVersion + ); + } + + /** + * Sends a request to Graph for the next page of results. + * + * @param GraphEdge $graphEdge The GraphEdge to paginate over. + * + * @return GraphEdge|null + * + * @throws FacebookSDKException + */ + public function next(GraphEdge $graphEdge) + { + return $this->getPaginationResults($graphEdge, 'next'); + } + + /** + * Sends a request to Graph for the previous page of results. + * + * @param GraphEdge $graphEdge The GraphEdge to paginate over. + * + * @return GraphEdge|null + * + * @throws FacebookSDKException + */ + public function previous(GraphEdge $graphEdge) + { + return $this->getPaginationResults($graphEdge, 'previous'); + } + + /** + * Sends a request to Graph for the next page of results. + * + * @param GraphEdge $graphEdge The GraphEdge to paginate over. + * @param string $direction The direction of the pagination: next|previous. + * + * @return GraphEdge|null + * + * @throws FacebookSDKException + */ + public function getPaginationResults(GraphEdge $graphEdge, $direction) + { + $paginationRequest = $graphEdge->getPaginationRequest($direction); + if (!$paginationRequest) { + return null; + } + + $this->lastResponse = $this->client->sendRequest($paginationRequest); + + // Keep the same GraphNode subclass + $subClassName = $graphEdge->getSubClassName(); + $graphEdge = $this->lastResponse->getGraphEdge($subClassName, false); + + return count($graphEdge) > 0 ? $graphEdge : null; + } + + /** + * Sends a request to Graph and returns the result. + * + * @param string $method + * @param string $endpoint + * @param array $params + * @param AccessToken|string|null $accessToken + * @param string|null $eTag + * @param string|null $graphVersion + * + * @return FacebookResponse + * + * @throws FacebookSDKException + */ + public function sendRequest($method, $endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null) + { + $accessToken = $accessToken ?: $this->defaultAccessToken; + $graphVersion = $graphVersion ?: $this->defaultGraphVersion; + $request = $this->request($method, $endpoint, $params, $accessToken, $eTag, $graphVersion); + + return $this->lastResponse = $this->client->sendRequest($request); + } + + /** + * Sends a batched request to Graph and returns the result. + * + * @param array $requests + * @param AccessToken|string|null $accessToken + * @param string|null $graphVersion + * + * @return FacebookBatchResponse + * + * @throws FacebookSDKException + */ + public function sendBatchRequest(array $requests, $accessToken = null, $graphVersion = null) + { + $accessToken = $accessToken ?: $this->defaultAccessToken; + $graphVersion = $graphVersion ?: $this->defaultGraphVersion; + $batchRequest = new FacebookBatchRequest( + $this->app, + $requests, + $accessToken, + $graphVersion + ); + + return $this->lastResponse = $this->client->sendBatchRequest($batchRequest); + } + + /** + * Instantiates a new FacebookRequest entity. + * + * @param string $method + * @param string $endpoint + * @param array $params + * @param AccessToken|string|null $accessToken + * @param string|null $eTag + * @param string|null $graphVersion + * + * @return FacebookRequest + * + * @throws FacebookSDKException + */ + public function request($method, $endpoint, array $params = [], $accessToken = null, $eTag = null, $graphVersion = null) + { + $accessToken = $accessToken ?: $this->defaultAccessToken; + $graphVersion = $graphVersion ?: $this->defaultGraphVersion; + + return new FacebookRequest( + $this->app, + $accessToken, + $method, + $endpoint, + $params, + $eTag, + $graphVersion + ); + } + + /** + * Factory to create FacebookFile's. + * + * @param string $pathToFile + * + * @return FacebookFile + * + * @throws FacebookSDKException + */ + public function fileToUpload($pathToFile) + { + return new FacebookFile($pathToFile); + } + + /** + * Factory to create FacebookVideo's. + * + * @param string $pathToFile + * + * @return FacebookVideo + * + * @throws FacebookSDKException + */ + public function videoToUpload($pathToFile) + { + return new FacebookVideo($pathToFile); + } +} diff --git a/oauth/facebook-sdk-v5/FacebookApp.php b/oauth/facebook-sdk-v5/FacebookApp.php new file mode 100644 index 0000000..84956ce --- /dev/null +++ b/oauth/facebook-sdk-v5/FacebookApp.php @@ -0,0 +1,101 @@ +id = $id; + $this->secret = $secret; + } + + /** + * Returns the app ID. + * + * @return string + */ + public function getId() + { + return $this->id; + } + + /** + * Returns the app secret. + * + * @return string + */ + public function getSecret() + { + return $this->secret; + } + + /** + * Returns an app access token. + * + * @return AccessToken + */ + public function getAccessToken() + { + return new AccessToken($this->id . '|' . $this->secret); + } + + /** + * Serializes the FacebookApp entity as a string. + * + * @return string + */ + public function serialize() + { + return serialize([$this->id, $this->secret]); + } + + /** + * Unserializes a string as a FacebookApp entity. + * + * @param string $serialized + */ + public function unserialize($serialized) + { + list($id, $secret) = unserialize($serialized); + + $this->__construct($id, $secret); + } +} diff --git a/oauth/facebook-sdk-v5/FacebookBatchRequest.php b/oauth/facebook-sdk-v5/FacebookBatchRequest.php new file mode 100644 index 0000000..33c489c --- /dev/null +++ b/oauth/facebook-sdk-v5/FacebookBatchRequest.php @@ -0,0 +1,303 @@ +add($requests); + } + + /** + * A a new request to the array. + * + * @param FacebookRequest|array $request + * @param string|null $name + * + * @return FacebookBatchRequest + * + * @throws \InvalidArgumentException + */ + public function add($request, $name = null) + { + if (is_array($request)) { + foreach ($request as $key => $req) { + $this->add($req, $key); + } + + return $this; + } + + if (!$request instanceof FacebookRequest) { + throw new \InvalidArgumentException('Argument for add() must be of type array or FacebookRequest.'); + } + + $this->addFallbackDefaults($request); + $requestToAdd = [ + 'name' => $name, + 'request' => $request, + ]; + + // File uploads + $attachedFiles = $this->extractFileAttachments($request); + if ($attachedFiles) { + $requestToAdd['attached_files'] = $attachedFiles; + } + $this->requests[] = $requestToAdd; + + return $this; + } + + /** + * Ensures that the FacebookApp and access token fall back when missing. + * + * @param FacebookRequest $request + * + * @throws FacebookSDKException + */ + public function addFallbackDefaults(FacebookRequest $request) + { + if (!$request->getApp()) { + $app = $this->getApp(); + if (!$app) { + throw new FacebookSDKException('Missing FacebookApp on FacebookRequest and no fallback detected on FacebookBatchRequest.'); + } + $request->setApp($app); + } + + if (!$request->getAccessToken()) { + $accessToken = $this->getAccessToken(); + if (!$accessToken) { + throw new FacebookSDKException('Missing access token on FacebookRequest and no fallback detected on FacebookBatchRequest.'); + } + $request->setAccessToken($accessToken); + } + } + + /** + * Extracts the files from a request. + * + * @param FacebookRequest $request + * + * @return string|null + * + * @throws FacebookSDKException + */ + public function extractFileAttachments(FacebookRequest $request) + { + if (!$request->containsFileUploads()) { + return null; + } + + $files = $request->getFiles(); + $fileNames = []; + foreach ($files as $file) { + $fileName = uniqid(); + $this->addFile($fileName, $file); + $fileNames[] = $fileName; + } + + $request->resetFiles(); + + // @TODO Does Graph support multiple uploads on one endpoint? + return implode(',', $fileNames); + } + + /** + * Return the FacebookRequest entities. + * + * @return array + */ + public function getRequests() + { + return $this->requests; + } + + /** + * Prepares the requests to be sent as a batch request. + * + * @return string + */ + public function prepareRequestsForBatch() + { + $this->validateBatchRequestCount(); + + $params = [ + 'batch' => $this->convertRequestsToJson(), + 'include_headers' => true, + ]; + $this->setParams($params); + } + + /** + * Converts the requests into a JSON(P) string. + * + * @return string + */ + public function convertRequestsToJson() + { + $requests = []; + foreach ($this->requests as $request) { + $attachedFiles = isset($request['attached_files']) ? $request['attached_files'] : null; + $requests[] = $this->requestEntityToBatchArray($request['request'], $request['name'], $attachedFiles); + } + + return json_encode($requests); + } + + /** + * Validate the request count before sending them as a batch. + * + * @throws FacebookSDKException + */ + public function validateBatchRequestCount() + { + $batchCount = count($this->requests); + if ($batchCount === 0) { + throw new FacebookSDKException('There are no batch requests to send.'); + } elseif ($batchCount > 50) { + // Per: https://developers.facebook.com/docs/graph-api/making-multiple-requests#limits + throw new FacebookSDKException('You cannot send more than 50 batch requests at a time.'); + } + } + + /** + * Converts a Request entity into an array that is batch-friendly. + * + * @param FacebookRequest $request The request entity to convert. + * @param string|null $requestName The name of the request. + * @param string|null $attachedFiles Names of files associated with the request. + * + * @return array + */ + public function requestEntityToBatchArray(FacebookRequest $request, $requestName = null, $attachedFiles = null) + { + $compiledHeaders = []; + $headers = $request->getHeaders(); + foreach ($headers as $name => $value) { + $compiledHeaders[] = $name . ': ' . $value; + } + + $batch = [ + 'headers' => $compiledHeaders, + 'method' => $request->getMethod(), + 'relative_url' => $request->getUrl(), + ]; + + // Since file uploads are moved to the root request of a batch request, + // the child requests will always be URL-encoded. + $body = $request->getUrlEncodedBody()->getBody(); + if ($body) { + $batch['body'] = $body; + } + + if (isset($requestName)) { + $batch['name'] = $requestName; + } + + if (isset($attachedFiles)) { + $batch['attached_files'] = $attachedFiles; + } + + // @TODO Add support for "omit_response_on_success" + // @TODO Add support for "depends_on" + // @TODO Add support for JSONP with "callback" + + return $batch; + } + + /** + * Get an iterator for the items. + * + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->requests); + } + + /** + * @inheritdoc + */ + public function offsetSet($offset, $value) + { + $this->add($value, $offset); + } + + /** + * @inheritdoc + */ + public function offsetExists($offset) + { + return isset($this->requests[$offset]); + } + + /** + * @inheritdoc + */ + public function offsetUnset($offset) + { + unset($this->requests[$offset]); + } + + /** + * @inheritdoc + */ + public function offsetGet($offset) + { + return isset($this->requests[$offset]) ? $this->requests[$offset] : null; + } +} diff --git a/oauth/facebook-sdk-v5/FacebookBatchResponse.php b/oauth/facebook-sdk-v5/FacebookBatchResponse.php new file mode 100644 index 0000000..5ea765e --- /dev/null +++ b/oauth/facebook-sdk-v5/FacebookBatchResponse.php @@ -0,0 +1,154 @@ +batchRequest = $batchRequest; + + $request = $response->getRequest(); + $body = $response->getBody(); + $httpStatusCode = $response->getHttpStatusCode(); + $headers = $response->getHeaders(); + parent::__construct($request, $body, $httpStatusCode, $headers); + + $responses = $response->getDecodedBody(); + $this->setResponses($responses); + } + + /** + * Returns an array of FacebookResponse entities. + * + * @return array + */ + public function getResponses() + { + return $this->responses; + } + + /** + * The main batch response will be an array of requests so + * we need to iterate over all the responses. + * + * @param array $responses + */ + public function setResponses(array $responses) + { + $this->responses = []; + + foreach ($responses as $key => $graphResponse) { + $this->addResponse($key, $graphResponse); + } + } + + /** + * Add a response to the list. + * + * @param int $key + * @param array|null $response + */ + public function addResponse($key, $response) + { + $originalRequestName = isset($this->batchRequest[$key]['name']) ? $this->batchRequest[$key]['name'] : $key; + $originalRequest = isset($this->batchRequest[$key]['request']) ? $this->batchRequest[$key]['request'] : null; + + $httpResponseBody = isset($response['body']) ? $response['body'] : null; + $httpResponseCode = isset($response['code']) ? $response['code'] : null; + $httpResponseHeaders = isset($response['headers']) ? $response['headers'] : []; + + $this->responses[$originalRequestName] = new FacebookResponse( + $originalRequest, + $httpResponseBody, + $httpResponseCode, + $httpResponseHeaders + ); + } + + /** + * @inheritdoc + */ + public function getIterator() + { + return new ArrayIterator($this->responses); + } + + /** + * @inheritdoc + */ + public function offsetSet($offset, $value) + { + $this->addResponse($offset, $value); + } + + /** + * @inheritdoc + */ + public function offsetExists($offset) + { + return isset($this->responses[$offset]); + } + + /** + * @inheritdoc + */ + public function offsetUnset($offset) + { + unset($this->responses[$offset]); + } + + /** + * @inheritdoc + */ + public function offsetGet($offset) + { + return isset($this->responses[$offset]) ? $this->responses[$offset] : null; + } +} diff --git a/oauth/facebook-sdk-v5/FacebookClient.php b/oauth/facebook-sdk-v5/FacebookClient.php new file mode 100644 index 0000000..b10762f --- /dev/null +++ b/oauth/facebook-sdk-v5/FacebookClient.php @@ -0,0 +1,250 @@ +httpClientHandler = $httpClientHandler ?: $this->detectHttpClientHandler(); + $this->enableBetaMode = $enableBeta; + } + + /** + * Sets the HTTP client handler. + * + * @param FacebookHttpClientInterface $httpClientHandler + */ + public function setHttpClientHandler(FacebookHttpClientInterface $httpClientHandler) + { + $this->httpClientHandler = $httpClientHandler; + } + + /** + * Returns the HTTP client handler. + * + * @return FacebookHttpClientInterface + */ + public function getHttpClientHandler() + { + return $this->httpClientHandler; + } + + /** + * Detects which HTTP client handler to use. + * + * @return FacebookHttpClientInterface + */ + public function detectHttpClientHandler() + { + return function_exists('curl_init') ? new FacebookCurlHttpClient() : new FacebookStreamHttpClient(); + } + + /** + * Toggle beta mode. + * + * @param boolean $betaMode + */ + public function enableBetaMode($betaMode = true) + { + $this->enableBetaMode = $betaMode; + } + + /** + * Returns the base Graph URL. + * + * @param boolean $postToVideoUrl Post to the video API if videos are being uploaded. + * + * @return string + */ + public function getBaseGraphUrl($postToVideoUrl = false) + { + if ($postToVideoUrl) { + return $this->enableBetaMode ? static::BASE_GRAPH_VIDEO_URL_BETA : static::BASE_GRAPH_VIDEO_URL; + } + + return $this->enableBetaMode ? static::BASE_GRAPH_URL_BETA : static::BASE_GRAPH_URL; + } + + /** + * Prepares the request for sending to the client handler. + * + * @param FacebookRequest $request + * + * @return array + */ + public function prepareRequestMessage(FacebookRequest $request) + { + $postToVideoUrl = $request->containsVideoUploads(); + $url = $this->getBaseGraphUrl($postToVideoUrl) . $request->getUrl(); + + // If we're sending files they should be sent as multipart/form-data + if ($request->containsFileUploads()) { + $requestBody = $request->getMultipartBody(); + $request->setHeaders([ + 'Content-Type' => 'multipart/form-data; boundary=' . $requestBody->getBoundary(), + ]); + } else { + $requestBody = $request->getUrlEncodedBody(); + $request->setHeaders([ + 'Content-Type' => 'application/x-www-form-urlencoded', + ]); + } + + return [ + $url, + $request->getMethod(), + $request->getHeaders(), + $requestBody->getBody(), + ]; + } + + /** + * Makes the request to Graph and returns the result. + * + * @param FacebookRequest $request + * + * @return FacebookResponse + * + * @throws FacebookSDKException + */ + public function sendRequest(FacebookRequest $request) + { + if (get_class($request) === 'FacebookRequest') { + $request->validateAccessToken(); + } + + list($url, $method, $headers, $body) = $this->prepareRequestMessage($request); + + // Since file uploads can take a while, we need to give more time for uploads + $timeOut = static::DEFAULT_REQUEST_TIMEOUT; + if ($request->containsFileUploads()) { + $timeOut = static::DEFAULT_FILE_UPLOAD_REQUEST_TIMEOUT; + } elseif ($request->containsVideoUploads()) { + $timeOut = static::DEFAULT_VIDEO_UPLOAD_REQUEST_TIMEOUT; + } + + // Should throw `FacebookSDKException` exception on HTTP client error. + // Don't catch to allow it to bubble up. + $rawResponse = $this->httpClientHandler->send($url, $method, $body, $headers, $timeOut); + + static::$requestCount++; + + $returnResponse = new FacebookResponse( + $request, + $rawResponse->getBody(), + $rawResponse->getHttpResponseCode(), + $rawResponse->getHeaders() + ); + + if ($returnResponse->isError()) { + throw $returnResponse->getThrownException(); + } + + return $returnResponse; + } + + /** + * Makes a batched request to Graph and returns the result. + * + * @param FacebookBatchRequest $request + * + * @return FacebookBatchResponse + * + * @throws FacebookSDKException + */ + public function sendBatchRequest(FacebookBatchRequest $request) + { + $request->prepareRequestsForBatch(); + $facebookResponse = $this->sendRequest($request); + + return new FacebookBatchResponse($request, $facebookResponse); + } +} diff --git a/oauth/facebook-sdk-v5/FacebookRequest.php b/oauth/facebook-sdk-v5/FacebookRequest.php new file mode 100644 index 0000000..5e4083f --- /dev/null +++ b/oauth/facebook-sdk-v5/FacebookRequest.php @@ -0,0 +1,536 @@ +setApp($app); + $this->setAccessToken($accessToken); + $this->setMethod($method); + $this->setEndpoint($endpoint); + $this->setParams($params); + $this->setETag($eTag); + $this->graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION; + } + + /** + * Set the access token for this request. + * + * @param AccessToken|string + * + * @return FacebookRequest + */ + public function setAccessToken($accessToken) + { + $this->accessToken = $accessToken; + if ($accessToken instanceof AccessToken) { + $this->accessToken = $accessToken->getValue(); + } + + return $this; + } + + /** + * Sets the access token with one harvested from a URL or POST params. + * + * @param string $accessToken The access token. + * + * @return FacebookRequest + * + * @throws FacebookSDKException + */ + public function setAccessTokenFromParams($accessToken) + { + $existingAccessToken = $this->getAccessToken(); + if (!$existingAccessToken) { + $this->setAccessToken($accessToken); + } elseif ($accessToken !== $existingAccessToken) { + throw new FacebookSDKException('Access token mismatch. The access token provided in the FacebookRequest and the one provided in the URL or POST params do not match.'); + } + + return $this; + } + + /** + * Return the access token for this request. + * + * @return string|null + */ + public function getAccessToken() + { + return $this->accessToken; + } + + /** + * Return the access token for this request an an AccessToken entity. + * + * @return AccessToken|null + */ + public function getAccessTokenEntity() + { + return $this->accessToken ? new AccessToken($this->accessToken) : null; + } + + /** + * Set the FacebookApp entity used for this request. + * + * @param FacebookApp|null $app + */ + public function setApp(FacebookApp $app = null) + { + $this->app = $app; + } + + /** + * Return the FacebookApp entity used for this request. + * + * @return FacebookApp + */ + public function getApp() + { + return $this->app; + } + + /** + * Generate an app secret proof to sign this request. + * + * @return string|null + */ + public function getAppSecretProof() + { + if (!$accessTokenEntity = $this->getAccessTokenEntity()) { + return null; + } + + return $accessTokenEntity->getAppSecretProof($this->app->getSecret()); + } + + /** + * Validate that an access token exists for this request. + * + * @throws FacebookSDKException + */ + public function validateAccessToken() + { + $accessToken = $this->getAccessToken(); + if (!$accessToken) { + throw new FacebookSDKException('You must provide an access token.'); + } + } + + /** + * Set the HTTP method for this request. + * + * @param string + * + * @return FacebookRequest + */ + public function setMethod($method) + { + $this->method = strtoupper($method); + } + + /** + * Return the HTTP method for this request. + * + * @return string + */ + public function getMethod() + { + return $this->method; + } + + /** + * Validate that the HTTP method is set. + * + * @throws FacebookSDKException + */ + public function validateMethod() + { + if (!$this->method) { + throw new FacebookSDKException('HTTP method not specified.'); + } + + if (!in_array($this->method, ['GET', 'POST', 'DELETE'])) { + throw new FacebookSDKException('Invalid HTTP method specified.'); + } + } + + /** + * Set the endpoint for this request. + * + * @param string + * + * @return FacebookRequest + * + * @throws FacebookSDKException + */ + public function setEndpoint($endpoint) + { + // Harvest the access token from the endpoint to keep things in sync + $params = FacebookUrlManipulator::getParamsAsArray($endpoint); + if (isset($params['access_token'])) { + $this->setAccessTokenFromParams($params['access_token']); + } + + // Clean the token & app secret proof from the endpoint. + $filterParams = ['access_token', 'appsecret_proof']; + $this->endpoint = FacebookUrlManipulator::removeParamsFromUrl($endpoint, $filterParams); + + return $this; + } + + /** + * Return the HTTP method for this request. + * + * @return string + */ + public function getEndpoint() + { + // For batch requests, this will be empty + return $this->endpoint; + } + + /** + * Generate and return the headers for this request. + * + * @return array + */ + public function getHeaders() + { + $headers = static::getDefaultHeaders(); + + if ($this->eTag) { + $headers['If-None-Match'] = $this->eTag; + } + + return array_merge($this->headers, $headers); + } + + /** + * Set the headers for this request. + * + * @param array $headers + */ + public function setHeaders(array $headers) + { + $this->headers = array_merge($this->headers, $headers); + } + + /** + * Sets the eTag value. + * + * @param string $eTag + */ + public function setETag($eTag) + { + $this->eTag = $eTag; + } + + /** + * Set the params for this request. + * + * @param array $params + * + * @return FacebookRequest + * + * @throws FacebookSDKException + */ + public function setParams(array $params = []) + { + if (isset($params['access_token'])) { + $this->setAccessTokenFromParams($params['access_token']); + } + + // Don't let these buggers slip in. + unset($params['access_token'], $params['appsecret_proof']); + + // @TODO Refactor code above with this + //$params = $this->sanitizeAuthenticationParams($params); + $params = $this->sanitizeFileParams($params); + $this->dangerouslySetParams($params); + + return $this; + } + + /** + * Set the params for this request without filtering them first. + * + * @param array $params + * + * @return FacebookRequest + */ + public function dangerouslySetParams(array $params = []) + { + $this->params = array_merge($this->params, $params); + + return $this; + } + + /** + * Iterate over the params and pull out the file uploads. + * + * @param array $params + * + * @return array + */ + public function sanitizeFileParams(array $params) + { + foreach ($params as $key => $value) { + if ($value instanceof FacebookFile) { + $this->addFile($key, $value); + unset($params[$key]); + } + } + + return $params; + } + + /** + * Add a file to be uploaded. + * + * @param string $key + * @param FacebookFile $file + */ + public function addFile($key, FacebookFile $file) + { + $this->files[$key] = $file; + } + + /** + * Removes all the files from the upload queue. + */ + public function resetFiles() + { + $this->files = []; + } + + /** + * Get the list of files to be uploaded. + * + * @return array + */ + public function getFiles() + { + return $this->files; + } + + /** + * Let's us know if there is a file upload with this request. + * + * @return boolean + */ + public function containsFileUploads() + { + return !empty($this->files); + } + + /** + * Let's us know if there is a video upload with this request. + * + * @return boolean + */ + public function containsVideoUploads() + { + foreach ($this->files as $file) { + if ($file instanceof FacebookVideo) { + return true; + } + } + + return false; + } + + /** + * Returns the body of the request as multipart/form-data. + * + * @return RequestBodyMultipart + */ + public function getMultipartBody() + { + $params = $this->getPostParams(); + + return new RequestBodyMultipart($params, $this->files); + } + + /** + * Returns the body of the request as URL-encoded. + * + * @return RequestBodyUrlEncoded + */ + public function getUrlEncodedBody() + { + $params = $this->getPostParams(); + + return new RequestBodyUrlEncoded($params); + } + + /** + * Generate and return the params for this request. + * + * @return array + */ + public function getParams() + { + $params = $this->params; + + $accessToken = $this->getAccessToken(); + if ($accessToken) { + $params['access_token'] = $accessToken; + $params['appsecret_proof'] = $this->getAppSecretProof(); + } + + return $params; + } + + /** + * Only return params on POST requests. + * + * @return array + */ + public function getPostParams() + { + if ($this->getMethod() === 'POST') { + return $this->getParams(); + } + + return []; + } + + /** + * The graph version used for this request. + * + * @return string + */ + public function getGraphVersion() + { + return $this->graphVersion; + } + + /** + * Generate and return the URL for this request. + * + * @return string + */ + public function getUrl() + { + $this->validateMethod(); + + $graphVersion = FacebookUrlManipulator::forceSlashPrefix($this->graphVersion); + $endpoint = FacebookUrlManipulator::forceSlashPrefix($this->getEndpoint()); + + $url = $graphVersion . $endpoint; + + if ($this->getMethod() !== 'POST') { + $params = $this->getParams(); + $url = FacebookUrlManipulator::appendParamsToUrl($url, $params); + } + + return $url; + } + + /** + * Return the default headers that every request should use. + * + * @return array + */ + public static function getDefaultHeaders() + { + return [ + 'User-Agent' => 'fb-php-' . Facebook::VERSION, + 'Accept-Encoding' => '*', + ]; + } +} diff --git a/oauth/facebook-sdk-v5/FacebookResponse.php b/oauth/facebook-sdk-v5/FacebookResponse.php new file mode 100644 index 0000000..ce55b14 --- /dev/null +++ b/oauth/facebook-sdk-v5/FacebookResponse.php @@ -0,0 +1,410 @@ +request = $request; + $this->body = $body; + $this->httpStatusCode = $httpStatusCode; + $this->headers = $headers; + + $this->decodeBody(); + } + + /** + * Return the original request that returned this response. + * + * @return FacebookRequest + */ + public function getRequest() + { + return $this->request; + } + + /** + * Return the FacebookApp entity used for this response. + * + * @return FacebookApp + */ + public function getApp() + { + return $this->request->getApp(); + } + + /** + * Return the access token that was used for this response. + * + * @return string|null + */ + public function getAccessToken() + { + return $this->request->getAccessToken(); + } + + /** + * Return the HTTP status code for this response. + * + * @return int + */ + public function getHttpStatusCode() + { + return $this->httpStatusCode; + } + + /** + * Return the HTTP headers for this response. + * + * @return array + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Return the raw body response. + * + * @return string + */ + public function getBody() + { + return $this->body; + } + + /** + * Return the decoded body response. + * + * @return array + */ + public function getDecodedBody() + { + return $this->decodedBody; + } + + /** + * Get the app secret proof that was used for this response. + * + * @return string|null + */ + public function getAppSecretProof() + { + return $this->request->getAppSecretProof(); + } + + /** + * Get the ETag associated with the response. + * + * @return string|null + */ + public function getETag() + { + return isset($this->headers['ETag']) ? $this->headers['ETag'] : null; + } + + /** + * Get the version of Graph that returned this response. + * + * @return string|null + */ + public function getGraphVersion() + { + return isset($this->headers['Facebook-API-Version']) ? $this->headers['Facebook-API-Version'] : null; + } + + /** + * Returns true if Graph returned an error message. + * + * @return boolean + */ + public function isError() + { + return isset($this->decodedBody['error']); + } + + /** + * Throws the exception. + * + * @throws FacebookSDKException + */ + public function throwException() + { + throw $this->thrownException; + } + + /** + * Instantiates an exception to be thrown later. + */ + public function makeException() + { + $this->thrownException = FacebookResponseException::create($this); + } + + /** + * Returns the exception that was thrown for this request. + * + * @return FacebookSDKException|null + */ + public function getThrownException() + { + return $this->thrownException; + } + + /** + * Convert the raw response into an array if possible. + * + * Graph will return 2 types of responses: + * - JSON(P) + * Most responses from Grpah are JSON(P) + * - application/x-www-form-urlencoded key/value pairs + * Happens on the `/oauth/access_token` endpoint when exchanging + * a short-lived access token for a long-lived access token + * - And sometimes nothing :/ but that'd be a bug. + */ + public function decodeBody() + { + $this->decodedBody = json_decode($this->body, true); + + if ($this->decodedBody === null) { + $this->decodedBody = []; + parse_str($this->body, $this->decodedBody); + } elseif (is_bool($this->decodedBody)) { + // Backwards compatibility for Graph < 2.1. + // Mimics 2.1 responses. + // @TODO Remove this after Graph 2.0 is no longer supported + $this->decodedBody = ['success' => $this->decodedBody]; + } elseif (is_numeric($this->decodedBody)) { + $this->decodedBody = ['id' => $this->decodedBody]; + } + + if (!is_array($this->decodedBody)) { + $this->decodedBody = []; + } + + if ($this->isError()) { + $this->makeException(); + } + } + + /** + * Instantiate a new GraphObject from response. + * + * @param string|null $subclassName The GraphNode sub class to cast to. + * + * @return \Facebook\GraphNodes\GraphObject + * + * @throws FacebookSDKException + * + * @deprecated 5.0.0 getGraphObject() has been renamed to getGraphNode() + * @todo v6: Remove this method + */ + public function getGraphObject($subclassName = null) + { + return $this->getGraphNode($subclassName); + } + + /** + * Instantiate a new GraphNode from response. + * + * @param string|null $subclassName The GraphNode sub class to cast to. + * + * @return \Facebook\GraphNodes\GraphNode + * + * @throws FacebookSDKException + */ + public function getGraphNode($subclassName = null) + { + $factory = new GraphNodeFactory($this); + + return $factory->makeGraphNode($subclassName); + } + + /** + * Convenience method for creating a GraphAlbum collection. + * + * @return \Facebook\GraphNodes\GraphAlbum + * + * @throws FacebookSDKException + */ + public function getGraphAlbum() + { + $factory = new GraphNodeFactory($this); + + return $factory->makeGraphAlbum(); + } + + /** + * Convenience method for creating a GraphPage collection. + * + * @return \Facebook\GraphNodes\GraphPage + * + * @throws FacebookSDKException + */ + public function getGraphPage() + { + $factory = new GraphNodeFactory($this); + + return $factory->makeGraphPage(); + } + + /** + * Convenience method for creating a GraphSessionInfo collection. + * + * @return \Facebook\GraphNodes\GraphSessionInfo + * + * @throws FacebookSDKException + */ + public function getGraphSessionInfo() + { + $factory = new GraphNodeFactory($this); + + return $factory->makeGraphSessionInfo(); + } + + /** + * Convenience method for creating a GraphUser collection. + * + * @return \Facebook\GraphNodes\GraphUser + * + * @throws FacebookSDKException + */ + public function getGraphUser() + { + $factory = new GraphNodeFactory($this); + + return $factory->makeGraphUser(); + } + + /** + * Convenience method for creating a GraphEvent collection. + * + * @return \Facebook\GraphNodes\GraphEvent + * + * @throws FacebookSDKException + */ + public function getGraphEvent() + { + $factory = new GraphNodeFactory($this); + + return $factory->makeGraphEvent(); + } + + /** + * Convenience method for creating a GraphGroup collection. + * + * @return \Facebook\GraphNodes\GraphGroup + * + * @throws FacebookSDKException + */ + public function getGraphGroup() + { + $factory = new GraphNodeFactory($this); + + return $factory->makeGraphGroup(); + } + + /** + * Instantiate a new GraphList from response. + * + * @param string|null $subclassName The GraphNode sub class to cast list items to. + * @param boolean $auto_prefix Toggle to auto-prefix the subclass name. + * + * @return \Facebook\GraphNodes\GraphList + * + * @throws FacebookSDKException + * + * @deprecated 5.0.0 getGraphList() has been renamed to getGraphEdge() + * @todo v6: Remove this method + */ + public function getGraphList($subclassName = null, $auto_prefix = true) + { + return $this->getGraphEdge($subclassName, $auto_prefix); + } + + /** + * Instantiate a new GraphEdge from response. + * + * @param string|null $subclassName The GraphNode sub class to cast list items to. + * @param boolean $auto_prefix Toggle to auto-prefix the subclass name. + * + * @return \Facebook\GraphNodes\GraphEdge + * + * @throws FacebookSDKException + */ + public function getGraphEdge($subclassName = null, $auto_prefix = true) + { + $factory = new GraphNodeFactory($this); + + return $factory->makeGraphEdge($subclassName, $auto_prefix); + } +} diff --git a/oauth/facebook-sdk-v5/FileUpload/FacebookFile.php b/oauth/facebook-sdk-v5/FileUpload/FacebookFile.php new file mode 100644 index 0000000..f8b9905 --- /dev/null +++ b/oauth/facebook-sdk-v5/FileUpload/FacebookFile.php @@ -0,0 +1,135 @@ +path = $filePath; + $this->open(); + } + + /** + * Closes the stream when destructed. + */ + public function __destruct() + { + $this->close(); + } + + /** + * Opens a stream for the file. + * + * @throws FacebookSDKException + */ + public function open() + { + if (!$this->isRemoteFile($this->path) && !is_readable($this->path)) { + throw new FacebookSDKException('Failed to create FacebookFile entity. Unable to read resource: ' . $this->path . '.'); + } + + $this->stream = fopen($this->path, 'r'); + + if (!$this->stream) { + throw new FacebookSDKException('Failed to create FacebookFile entity. Unable to open resource: ' . $this->path . '.'); + } + } + + /** + * Stops the file stream. + */ + public function close() + { + if (is_resource($this->stream)) { + fclose($this->stream); + } + } + + /** + * Return the contents of the file. + * + * @return string + */ + public function getContents() + { + return stream_get_contents($this->stream); + } + + /** + * Return the name of the file. + * + * @return string + */ + public function getFileName() + { + return basename($this->path); + } + + /** + * Return the mimetype of the file. + * + * @return string + */ + public function getMimetype() + { + return Mimetypes::getInstance()->fromFilename($this->path) ?: 'text/plain'; + } + + /** + * Returns true if the path to the file is remote. + * + * @param string $pathToFile + * + * @return boolean + */ + protected function isRemoteFile($pathToFile) + { + return preg_match('/^(https?|ftp):\/\/.*/', $pathToFile) === 1; + } +} diff --git a/oauth/facebook-sdk-v5/FileUpload/FacebookVideo.php b/oauth/facebook-sdk-v5/FileUpload/FacebookVideo.php new file mode 100644 index 0000000..1e8c55a --- /dev/null +++ b/oauth/facebook-sdk-v5/FileUpload/FacebookVideo.php @@ -0,0 +1,33 @@ + 'text/vnd.in3d.3dml', + '3g2' => 'video/3gpp2', + '3gp' => 'video/3gpp', + '7z' => 'application/x-7z-compressed', + 'aab' => 'application/x-authorware-bin', + 'aac' => 'audio/x-aac', + 'aam' => 'application/x-authorware-map', + 'aas' => 'application/x-authorware-seg', + 'abw' => 'application/x-abiword', + 'ac' => 'application/pkix-attr-cert', + 'acc' => 'application/vnd.americandynamics.acc', + 'ace' => 'application/x-ace-compressed', + 'acu' => 'application/vnd.acucobol', + 'acutc' => 'application/vnd.acucorp', + 'adp' => 'audio/adpcm', + 'aep' => 'application/vnd.audiograph', + 'afm' => 'application/x-font-type1', + 'afp' => 'application/vnd.ibm.modcap', + 'ahead' => 'application/vnd.ahead.space', + 'ai' => 'application/postscript', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'air' => 'application/vnd.adobe.air-application-installer-package+zip', + 'ait' => 'application/vnd.dvb.ait', + 'ami' => 'application/vnd.amiga.ami', + 'apk' => 'application/vnd.android.package-archive', + 'application' => 'application/x-ms-application', + 'apr' => 'application/vnd.lotus-approach', + 'asa' => 'text/plain', + 'asax' => 'application/octet-stream', + 'asc' => 'application/pgp-signature', + 'ascx' => 'text/plain', + 'asf' => 'video/x-ms-asf', + 'ashx' => 'text/plain', + 'asm' => 'text/x-asm', + 'asmx' => 'text/plain', + 'aso' => 'application/vnd.accpac.simply.aso', + 'asp' => 'text/plain', + 'aspx' => 'text/plain', + 'asx' => 'video/x-ms-asf', + 'atc' => 'application/vnd.acucorp', + 'atom' => 'application/atom+xml', + 'atomcat' => 'application/atomcat+xml', + 'atomsvc' => 'application/atomsvc+xml', + 'atx' => 'application/vnd.antix.game-component', + 'au' => 'audio/basic', + 'avi' => 'video/x-msvideo', + 'aw' => 'application/applixware', + 'axd' => 'text/plain', + 'azf' => 'application/vnd.airzip.filesecure.azf', + 'azs' => 'application/vnd.airzip.filesecure.azs', + 'azw' => 'application/vnd.amazon.ebook', + 'bat' => 'application/x-msdownload', + 'bcpio' => 'application/x-bcpio', + 'bdf' => 'application/x-font-bdf', + 'bdm' => 'application/vnd.syncml.dm+wbxml', + 'bed' => 'application/vnd.realvnc.bed', + 'bh2' => 'application/vnd.fujitsu.oasysprs', + 'bin' => 'application/octet-stream', + 'bmi' => 'application/vnd.bmi', + 'bmp' => 'image/bmp', + 'book' => 'application/vnd.framemaker', + 'box' => 'application/vnd.previewsystems.box', + 'boz' => 'application/x-bzip2', + 'bpk' => 'application/octet-stream', + 'btif' => 'image/prs.btif', + 'bz' => 'application/x-bzip', + 'bz2' => 'application/x-bzip2', + 'c' => 'text/x-c', + 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', + 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', + 'c4d' => 'application/vnd.clonk.c4group', + 'c4f' => 'application/vnd.clonk.c4group', + 'c4g' => 'application/vnd.clonk.c4group', + 'c4p' => 'application/vnd.clonk.c4group', + 'c4u' => 'application/vnd.clonk.c4group', + 'cab' => 'application/vnd.ms-cab-compressed', + 'car' => 'application/vnd.curl.car', + 'cat' => 'application/vnd.ms-pki.seccat', + 'cc' => 'text/x-c', + 'cct' => 'application/x-director', + 'ccxml' => 'application/ccxml+xml', + 'cdbcmsg' => 'application/vnd.contact.cmsg', + 'cdf' => 'application/x-netcdf', + 'cdkey' => 'application/vnd.mediastation.cdkey', + 'cdmia' => 'application/cdmi-capability', + 'cdmic' => 'application/cdmi-container', + 'cdmid' => 'application/cdmi-domain', + 'cdmio' => 'application/cdmi-object', + 'cdmiq' => 'application/cdmi-queue', + 'cdx' => 'chemical/x-cdx', + 'cdxml' => 'application/vnd.chemdraw+xml', + 'cdy' => 'application/vnd.cinderella', + 'cer' => 'application/pkix-cert', + 'cfc' => 'application/x-coldfusion', + 'cfm' => 'application/x-coldfusion', + 'cgm' => 'image/cgm', + 'chat' => 'application/x-chat', + 'chm' => 'application/vnd.ms-htmlhelp', + 'chrt' => 'application/vnd.kde.kchart', + 'cif' => 'chemical/x-cif', + 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', + 'cil' => 'application/vnd.ms-artgalry', + 'cla' => 'application/vnd.claymore', + 'class' => 'application/java-vm', + 'clkk' => 'application/vnd.crick.clicker.keyboard', + 'clkp' => 'application/vnd.crick.clicker.palette', + 'clkt' => 'application/vnd.crick.clicker.template', + 'clkw' => 'application/vnd.crick.clicker.wordbank', + 'clkx' => 'application/vnd.crick.clicker', + 'clp' => 'application/x-msclip', + 'cmc' => 'application/vnd.cosmocaller', + 'cmdf' => 'chemical/x-cmdf', + 'cml' => 'chemical/x-cml', + 'cmp' => 'application/vnd.yellowriver-custom-menu', + 'cmx' => 'image/x-cmx', + 'cod' => 'application/vnd.rim.cod', + 'com' => 'application/x-msdownload', + 'conf' => 'text/plain', + 'cpio' => 'application/x-cpio', + 'cpp' => 'text/x-c', + 'cpt' => 'application/mac-compactpro', + 'crd' => 'application/x-mscardfile', + 'crl' => 'application/pkix-crl', + 'crt' => 'application/x-x509-ca-cert', + 'cryptonote' => 'application/vnd.rig.cryptonote', + 'cs' => 'text/plain', + 'csh' => 'application/x-csh', + 'csml' => 'chemical/x-csml', + 'csp' => 'application/vnd.commonspace', + 'css' => 'text/css', + 'cst' => 'application/x-director', + 'csv' => 'text/csv', + 'cu' => 'application/cu-seeme', + 'curl' => 'text/vnd.curl', + 'cww' => 'application/prs.cww', + 'cxt' => 'application/x-director', + 'cxx' => 'text/x-c', + 'dae' => 'model/vnd.collada+xml', + 'daf' => 'application/vnd.mobius.daf', + 'dataless' => 'application/vnd.fdsn.seed', + 'davmount' => 'application/davmount+xml', + 'dcr' => 'application/x-director', + 'dcurl' => 'text/vnd.curl.dcurl', + 'dd2' => 'application/vnd.oma.dd2+xml', + 'ddd' => 'application/vnd.fujixerox.ddd', + 'deb' => 'application/x-debian-package', + 'def' => 'text/plain', + 'deploy' => 'application/octet-stream', + 'der' => 'application/x-x509-ca-cert', + 'dfac' => 'application/vnd.dreamfactory', + 'dic' => 'text/x-c', + 'dir' => 'application/x-director', + 'dis' => 'application/vnd.mobius.dis', + 'dist' => 'application/octet-stream', + 'distz' => 'application/octet-stream', + 'djv' => 'image/vnd.djvu', + 'djvu' => 'image/vnd.djvu', + 'dll' => 'application/x-msdownload', + 'dmg' => 'application/octet-stream', + 'dms' => 'application/octet-stream', + 'dna' => 'application/vnd.dna', + 'doc' => 'application/msword', + 'docm' => 'application/vnd.ms-word.document.macroenabled.12', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dot' => 'application/msword', + 'dotm' => 'application/vnd.ms-word.template.macroenabled.12', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dp' => 'application/vnd.osgi.dp', + 'dpg' => 'application/vnd.dpgraph', + 'dra' => 'audio/vnd.dra', + 'dsc' => 'text/prs.lines.tag', + 'dssc' => 'application/dssc+der', + 'dtb' => 'application/x-dtbook+xml', + 'dtd' => 'application/xml-dtd', + 'dts' => 'audio/vnd.dts', + 'dtshd' => 'audio/vnd.dts.hd', + 'dump' => 'application/octet-stream', + 'dvi' => 'application/x-dvi', + 'dwf' => 'model/vnd.dwf', + 'dwg' => 'image/vnd.dwg', + 'dxf' => 'image/vnd.dxf', + 'dxp' => 'application/vnd.spotfire.dxp', + 'dxr' => 'application/x-director', + 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', + 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', + 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', + 'ecma' => 'application/ecmascript', + 'edm' => 'application/vnd.novadigm.edm', + 'edx' => 'application/vnd.novadigm.edx', + 'efif' => 'application/vnd.picsel', + 'ei6' => 'application/vnd.pg.osasli', + 'elc' => 'application/octet-stream', + 'eml' => 'message/rfc822', + 'emma' => 'application/emma+xml', + 'eol' => 'audio/vnd.digital-winds', + 'eot' => 'application/vnd.ms-fontobject', + 'eps' => 'application/postscript', + 'epub' => 'application/epub+zip', + 'es3' => 'application/vnd.eszigno3+xml', + 'esf' => 'application/vnd.epson.esf', + 'et3' => 'application/vnd.eszigno3+xml', + 'etx' => 'text/x-setext', + 'exe' => 'application/x-msdownload', + 'exi' => 'application/exi', + 'ext' => 'application/vnd.novadigm.ext', + 'ez' => 'application/andrew-inset', + 'ez2' => 'application/vnd.ezpix-album', + 'ez3' => 'application/vnd.ezpix-package', + 'f' => 'text/x-fortran', + 'f4v' => 'video/x-f4v', + 'f77' => 'text/x-fortran', + 'f90' => 'text/x-fortran', + 'fbs' => 'image/vnd.fastbidsheet', + 'fcs' => 'application/vnd.isac.fcs', + 'fdf' => 'application/vnd.fdf', + 'fe_launch' => 'application/vnd.denovo.fcselayout-link', + 'fg5' => 'application/vnd.fujitsu.oasysgp', + 'fgd' => 'application/x-director', + 'fh' => 'image/x-freehand', + 'fh4' => 'image/x-freehand', + 'fh5' => 'image/x-freehand', + 'fh7' => 'image/x-freehand', + 'fhc' => 'image/x-freehand', + 'fig' => 'application/x-xfig', + 'fli' => 'video/x-fli', + 'flo' => 'application/vnd.micrografx.flo', + 'flv' => 'video/x-flv', + 'flw' => 'application/vnd.kde.kivio', + 'flx' => 'text/vnd.fmi.flexstor', + 'fly' => 'text/vnd.fly', + 'fm' => 'application/vnd.framemaker', + 'fnc' => 'application/vnd.frogans.fnc', + 'for' => 'text/x-fortran', + 'fpx' => 'image/vnd.fpx', + 'frame' => 'application/vnd.framemaker', + 'fsc' => 'application/vnd.fsc.weblaunch', + 'fst' => 'image/vnd.fst', + 'ftc' => 'application/vnd.fluxtime.clip', + 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', + 'fvt' => 'video/vnd.fvt', + 'fxp' => 'application/vnd.adobe.fxp', + 'fxpl' => 'application/vnd.adobe.fxp', + 'fzs' => 'application/vnd.fuzzysheet', + 'g2w' => 'application/vnd.geoplan', + 'g3' => 'image/g3fax', + 'g3w' => 'application/vnd.geospace', + 'gac' => 'application/vnd.groove-account', + 'gdl' => 'model/vnd.gdl', + 'geo' => 'application/vnd.dynageo', + 'gex' => 'application/vnd.geometry-explorer', + 'ggb' => 'application/vnd.geogebra.file', + 'ggt' => 'application/vnd.geogebra.tool', + 'ghf' => 'application/vnd.groove-help', + 'gif' => 'image/gif', + 'gim' => 'application/vnd.groove-identity-message', + 'gmx' => 'application/vnd.gmx', + 'gnumeric' => 'application/x-gnumeric', + 'gph' => 'application/vnd.flographit', + 'gqf' => 'application/vnd.grafeq', + 'gqs' => 'application/vnd.grafeq', + 'gram' => 'application/srgs', + 'gre' => 'application/vnd.geometry-explorer', + 'grv' => 'application/vnd.groove-injector', + 'grxml' => 'application/srgs+xml', + 'gsf' => 'application/x-font-ghostscript', + 'gtar' => 'application/x-gtar', + 'gtm' => 'application/vnd.groove-tool-message', + 'gtw' => 'model/vnd.gtw', + 'gv' => 'text/vnd.graphviz', + 'gxt' => 'application/vnd.geonext', + 'h' => 'text/x-c', + 'h261' => 'video/h261', + 'h263' => 'video/h263', + 'h264' => 'video/h264', + 'hal' => 'application/vnd.hal+xml', + 'hbci' => 'application/vnd.hbci', + 'hdf' => 'application/x-hdf', + 'hh' => 'text/x-c', + 'hlp' => 'application/winhlp', + 'hpgl' => 'application/vnd.hp-hpgl', + 'hpid' => 'application/vnd.hp-hpid', + 'hps' => 'application/vnd.hp-hps', + 'hqx' => 'application/mac-binhex40', + 'hta' => 'application/octet-stream', + 'htc' => 'text/html', + 'htke' => 'application/vnd.kenameaapp', + 'htm' => 'text/html', + 'html' => 'text/html', + 'hvd' => 'application/vnd.yamaha.hv-dic', + 'hvp' => 'application/vnd.yamaha.hv-voice', + 'hvs' => 'application/vnd.yamaha.hv-script', + 'i2g' => 'application/vnd.intergeo', + 'icc' => 'application/vnd.iccprofile', + 'ice' => 'x-conference/x-cooltalk', + 'icm' => 'application/vnd.iccprofile', + 'ico' => 'image/x-icon', + 'ics' => 'text/calendar', + 'ief' => 'image/ief', + 'ifb' => 'text/calendar', + 'ifm' => 'application/vnd.shana.informed.formdata', + 'iges' => 'model/iges', + 'igl' => 'application/vnd.igloader', + 'igm' => 'application/vnd.insors.igm', + 'igs' => 'model/iges', + 'igx' => 'application/vnd.micrografx.igx', + 'iif' => 'application/vnd.shana.informed.interchange', + 'imp' => 'application/vnd.accpac.simply.imp', + 'ims' => 'application/vnd.ms-ims', + 'in' => 'text/plain', + 'ini' => 'text/plain', + 'ipfix' => 'application/ipfix', + 'ipk' => 'application/vnd.shana.informed.package', + 'irm' => 'application/vnd.ibm.rights-management', + 'irp' => 'application/vnd.irepository.package+xml', + 'iso' => 'application/octet-stream', + 'itp' => 'application/vnd.shana.informed.formtemplate', + 'ivp' => 'application/vnd.immervision-ivp', + 'ivu' => 'application/vnd.immervision-ivu', + 'jad' => 'text/vnd.sun.j2me.app-descriptor', + 'jam' => 'application/vnd.jam', + 'jar' => 'application/java-archive', + 'java' => 'text/x-java-source', + 'jisp' => 'application/vnd.jisp', + 'jlt' => 'application/vnd.hp-jlyt', + 'jnlp' => 'application/x-java-jnlp-file', + 'joda' => 'application/vnd.joost.joda-archive', + 'jpe' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'jpgm' => 'video/jpm', + 'jpgv' => 'video/jpeg', + 'jpm' => 'video/jpm', + 'js' => 'text/javascript', + 'json' => 'application/json', + 'kar' => 'audio/midi', + 'karbon' => 'application/vnd.kde.karbon', + 'kfo' => 'application/vnd.kde.kformula', + 'kia' => 'application/vnd.kidspiration', + 'kml' => 'application/vnd.google-earth.kml+xml', + 'kmz' => 'application/vnd.google-earth.kmz', + 'kne' => 'application/vnd.kinar', + 'knp' => 'application/vnd.kinar', + 'kon' => 'application/vnd.kde.kontour', + 'kpr' => 'application/vnd.kde.kpresenter', + 'kpt' => 'application/vnd.kde.kpresenter', + 'ksp' => 'application/vnd.kde.kspread', + 'ktr' => 'application/vnd.kahootz', + 'ktx' => 'image/ktx', + 'ktz' => 'application/vnd.kahootz', + 'kwd' => 'application/vnd.kde.kword', + 'kwt' => 'application/vnd.kde.kword', + 'lasxml' => 'application/vnd.las.las+xml', + 'latex' => 'application/x-latex', + 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', + 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', + 'les' => 'application/vnd.hhe.lesson-player', + 'lha' => 'application/octet-stream', + 'link66' => 'application/vnd.route66.link66+xml', + 'list' => 'text/plain', + 'list3820' => 'application/vnd.ibm.modcap', + 'listafp' => 'application/vnd.ibm.modcap', + 'log' => 'text/plain', + 'lostxml' => 'application/lost+xml', + 'lrf' => 'application/octet-stream', + 'lrm' => 'application/vnd.ms-lrm', + 'ltf' => 'application/vnd.frogans.ltf', + 'lvp' => 'audio/vnd.lucent.voice', + 'lwp' => 'application/vnd.lotus-wordpro', + 'lzh' => 'application/octet-stream', + 'm13' => 'application/x-msmediaview', + 'm14' => 'application/x-msmediaview', + 'm1v' => 'video/mpeg', + 'm21' => 'application/mp21', + 'm2a' => 'audio/mpeg', + 'm2v' => 'video/mpeg', + 'm3a' => 'audio/mpeg', + 'm3u' => 'audio/x-mpegurl', + 'm3u8' => 'application/vnd.apple.mpegurl', + 'm4a' => 'audio/mp4', + 'm4u' => 'video/vnd.mpegurl', + 'm4v' => 'video/mp4', + 'ma' => 'application/mathematica', + 'mads' => 'application/mads+xml', + 'mag' => 'application/vnd.ecowin.chart', + 'maker' => 'application/vnd.framemaker', + 'man' => 'text/troff', + 'mathml' => 'application/mathml+xml', + 'mb' => 'application/mathematica', + 'mbk' => 'application/vnd.mobius.mbk', + 'mbox' => 'application/mbox', + 'mc1' => 'application/vnd.medcalcdata', + 'mcd' => 'application/vnd.mcd', + 'mcurl' => 'text/vnd.curl.mcurl', + 'mdb' => 'application/x-msaccess', + 'mdi' => 'image/vnd.ms-modi', + 'me' => 'text/troff', + 'mesh' => 'model/mesh', + 'meta4' => 'application/metalink4+xml', + 'mets' => 'application/mets+xml', + 'mfm' => 'application/vnd.mfmp', + 'mgp' => 'application/vnd.osgeo.mapguide.package', + 'mgz' => 'application/vnd.proteus.magazine', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mif' => 'application/vnd.mif', + 'mime' => 'message/rfc822', + 'mj2' => 'video/mj2', + 'mjp2' => 'video/mj2', + 'mlp' => 'application/vnd.dolby.mlp', + 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', + 'mmf' => 'application/vnd.smaf', + 'mmr' => 'image/vnd.fujixerox.edmics-mmr', + 'mny' => 'application/x-msmoney', + 'mobi' => 'application/x-mobipocket-ebook', + 'mods' => 'application/mods+xml', + 'mov' => 'video/quicktime', + 'movie' => 'video/x-sgi-movie', + 'mp2' => 'audio/mpeg', + 'mp21' => 'application/mp21', + 'mp2a' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'mp4a' => 'audio/mp4', + 'mp4s' => 'application/mp4', + 'mp4v' => 'video/mp4', + 'mpc' => 'application/vnd.mophun.certificate', + 'mpe' => 'video/mpeg', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpg4' => 'video/mp4', + 'mpga' => 'audio/mpeg', + 'mpkg' => 'application/vnd.apple.installer+xml', + 'mpm' => 'application/vnd.blueice.multipass', + 'mpn' => 'application/vnd.mophun.application', + 'mpp' => 'application/vnd.ms-project', + 'mpt' => 'application/vnd.ms-project', + 'mpy' => 'application/vnd.ibm.minipay', + 'mqy' => 'application/vnd.mobius.mqy', + 'mrc' => 'application/marc', + 'mrcx' => 'application/marcxml+xml', + 'ms' => 'text/troff', + 'mscml' => 'application/mediaservercontrol+xml', + 'mseed' => 'application/vnd.fdsn.mseed', + 'mseq' => 'application/vnd.mseq', + 'msf' => 'application/vnd.epson.msf', + 'msh' => 'model/mesh', + 'msi' => 'application/x-msdownload', + 'msl' => 'application/vnd.mobius.msl', + 'msty' => 'application/vnd.muvee.style', + 'mts' => 'model/vnd.mts', + 'mus' => 'application/vnd.musician', + 'musicxml' => 'application/vnd.recordare.musicxml+xml', + 'mvb' => 'application/x-msmediaview', + 'mwf' => 'application/vnd.mfer', + 'mxf' => 'application/mxf', + 'mxl' => 'application/vnd.recordare.musicxml', + 'mxml' => 'application/xv+xml', + 'mxs' => 'application/vnd.triscape.mxs', + 'mxu' => 'video/vnd.mpegurl', + 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', + 'n3' => 'text/n3', + 'nb' => 'application/mathematica', + 'nbp' => 'application/vnd.wolfram.player', + 'nc' => 'application/x-netcdf', + 'ncx' => 'application/x-dtbncx+xml', + 'ngdat' => 'application/vnd.nokia.n-gage.data', + 'nlu' => 'application/vnd.neurolanguage.nlu', + 'nml' => 'application/vnd.enliven', + 'nnd' => 'application/vnd.noblenet-directory', + 'nns' => 'application/vnd.noblenet-sealer', + 'nnw' => 'application/vnd.noblenet-web', + 'npx' => 'image/vnd.net-fpx', + 'nsf' => 'application/vnd.lotus-notes', + 'oa2' => 'application/vnd.fujitsu.oasys2', + 'oa3' => 'application/vnd.fujitsu.oasys3', + 'oas' => 'application/vnd.fujitsu.oasys', + 'obd' => 'application/x-msbinder', + 'oda' => 'application/oda', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'odf' => 'application/vnd.oasis.opendocument.formula', + 'odft' => 'application/vnd.oasis.opendocument.formula-template', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'odi' => 'application/vnd.oasis.opendocument.image', + 'odm' => 'application/vnd.oasis.opendocument.text-master', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'oga' => 'audio/ogg', + 'ogg' => 'audio/ogg', + 'ogv' => 'video/ogg', + 'ogx' => 'application/ogg', + 'onepkg' => 'application/onenote', + 'onetmp' => 'application/onenote', + 'onetoc' => 'application/onenote', + 'onetoc2' => 'application/onenote', + 'opf' => 'application/oebps-package+xml', + 'oprc' => 'application/vnd.palm', + 'org' => 'application/vnd.lotus-organizer', + 'osf' => 'application/vnd.yamaha.openscoreformat', + 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', + 'otc' => 'application/vnd.oasis.opendocument.chart-template', + 'otf' => 'application/x-font-otf', + 'otg' => 'application/vnd.oasis.opendocument.graphics-template', + 'oth' => 'application/vnd.oasis.opendocument.text-web', + 'oti' => 'application/vnd.oasis.opendocument.image-template', + 'otp' => 'application/vnd.oasis.opendocument.presentation-template', + 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', + 'ott' => 'application/vnd.oasis.opendocument.text-template', + 'oxt' => 'application/vnd.openofficeorg.extension', + 'p' => 'text/x-pascal', + 'p10' => 'application/pkcs10', + 'p12' => 'application/x-pkcs12', + 'p7b' => 'application/x-pkcs7-certificates', + 'p7c' => 'application/pkcs7-mime', + 'p7m' => 'application/pkcs7-mime', + 'p7r' => 'application/x-pkcs7-certreqresp', + 'p7s' => 'application/pkcs7-signature', + 'p8' => 'application/pkcs8', + 'pas' => 'text/x-pascal', + 'paw' => 'application/vnd.pawaafile', + 'pbd' => 'application/vnd.powerbuilder6', + 'pbm' => 'image/x-portable-bitmap', + 'pcf' => 'application/x-font-pcf', + 'pcl' => 'application/vnd.hp-pcl', + 'pclxl' => 'application/vnd.hp-pclxl', + 'pct' => 'image/x-pict', + 'pcurl' => 'application/vnd.curl.pcurl', + 'pcx' => 'image/x-pcx', + 'pdb' => 'application/vnd.palm', + 'pdf' => 'application/pdf', + 'pfa' => 'application/x-font-type1', + 'pfb' => 'application/x-font-type1', + 'pfm' => 'application/x-font-type1', + 'pfr' => 'application/font-tdpfr', + 'pfx' => 'application/x-pkcs12', + 'pgm' => 'image/x-portable-graymap', + 'pgn' => 'application/x-chess-pgn', + 'pgp' => 'application/pgp-encrypted', + 'php' => 'text/x-php', + 'phps' => 'application/x-httpd-phps', + 'pic' => 'image/x-pict', + 'pkg' => 'application/octet-stream', + 'pki' => 'application/pkixcmp', + 'pkipath' => 'application/pkix-pkipath', + 'plb' => 'application/vnd.3gpp.pic-bw-large', + 'plc' => 'application/vnd.mobius.plc', + 'plf' => 'application/vnd.pocketlearn', + 'pls' => 'application/pls+xml', + 'pml' => 'application/vnd.ctc-posml', + 'png' => 'image/png', + 'pnm' => 'image/x-portable-anymap', + 'portpkg' => 'application/vnd.macports.portpkg', + 'pot' => 'application/vnd.ms-powerpoint', + 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12', + 'ppd' => 'application/vnd.cups-ppd', + 'ppm' => 'image/x-portable-pixmap', + 'pps' => 'application/vnd.ms-powerpoint', + 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'pqa' => 'application/vnd.palm', + 'prc' => 'application/x-mobipocket-ebook', + 'pre' => 'application/vnd.lotus-freelance', + 'prf' => 'application/pics-rules', + 'ps' => 'application/postscript', + 'psb' => 'application/vnd.3gpp.pic-bw-small', + 'psd' => 'image/vnd.adobe.photoshop', + 'psf' => 'application/x-font-linux-psf', + 'pskcxml' => 'application/pskc+xml', + 'ptid' => 'application/vnd.pvi.ptid1', + 'pub' => 'application/x-mspublisher', + 'pvb' => 'application/vnd.3gpp.pic-bw-var', + 'pwn' => 'application/vnd.3m.post-it-notes', + 'pya' => 'audio/vnd.ms-playready.media.pya', + 'pyv' => 'video/vnd.ms-playready.media.pyv', + 'qam' => 'application/vnd.epson.quickanime', + 'qbo' => 'application/vnd.intu.qbo', + 'qfx' => 'application/vnd.intu.qfx', + 'qps' => 'application/vnd.publishare-delta-tree', + 'qt' => 'video/quicktime', + 'qwd' => 'application/vnd.quark.quarkxpress', + 'qwt' => 'application/vnd.quark.quarkxpress', + 'qxb' => 'application/vnd.quark.quarkxpress', + 'qxd' => 'application/vnd.quark.quarkxpress', + 'qxl' => 'application/vnd.quark.quarkxpress', + 'qxt' => 'application/vnd.quark.quarkxpress', + 'ra' => 'audio/x-pn-realaudio', + 'ram' => 'audio/x-pn-realaudio', + 'rar' => 'application/x-rar-compressed', + 'ras' => 'image/x-cmu-raster', + 'rb' => 'text/plain', + 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', + 'rdf' => 'application/rdf+xml', + 'rdz' => 'application/vnd.data-vision.rdz', + 'rep' => 'application/vnd.businessobjects', + 'res' => 'application/x-dtbresource+xml', + 'resx' => 'text/xml', + 'rgb' => 'image/x-rgb', + 'rif' => 'application/reginfo+xml', + 'rip' => 'audio/vnd.rip', + 'rl' => 'application/resource-lists+xml', + 'rlc' => 'image/vnd.fujixerox.edmics-rlc', + 'rld' => 'application/resource-lists-diff+xml', + 'rm' => 'application/vnd.rn-realmedia', + 'rmi' => 'audio/midi', + 'rmp' => 'audio/x-pn-realaudio-plugin', + 'rms' => 'application/vnd.jcp.javame.midlet-rms', + 'rnc' => 'application/relax-ng-compact-syntax', + 'roff' => 'text/troff', + 'rp9' => 'application/vnd.cloanto.rp9', + 'rpss' => 'application/vnd.nokia.radio-presets', + 'rpst' => 'application/vnd.nokia.radio-preset', + 'rq' => 'application/sparql-query', + 'rs' => 'application/rls-services+xml', + 'rsd' => 'application/rsd+xml', + 'rss' => 'application/rss+xml', + 'rtf' => 'application/rtf', + 'rtx' => 'text/richtext', + 's' => 'text/x-asm', + 'saf' => 'application/vnd.yamaha.smaf-audio', + 'sbml' => 'application/sbml+xml', + 'sc' => 'application/vnd.ibm.secure-container', + 'scd' => 'application/x-msschedule', + 'scm' => 'application/vnd.lotus-screencam', + 'scq' => 'application/scvp-cv-request', + 'scs' => 'application/scvp-cv-response', + 'scurl' => 'text/vnd.curl.scurl', + 'sda' => 'application/vnd.stardivision.draw', + 'sdc' => 'application/vnd.stardivision.calc', + 'sdd' => 'application/vnd.stardivision.impress', + 'sdkd' => 'application/vnd.solent.sdkm+xml', + 'sdkm' => 'application/vnd.solent.sdkm+xml', + 'sdp' => 'application/sdp', + 'sdw' => 'application/vnd.stardivision.writer', + 'see' => 'application/vnd.seemail', + 'seed' => 'application/vnd.fdsn.seed', + 'sema' => 'application/vnd.sema', + 'semd' => 'application/vnd.semd', + 'semf' => 'application/vnd.semf', + 'ser' => 'application/java-serialized-object', + 'setpay' => 'application/set-payment-initiation', + 'setreg' => 'application/set-registration-initiation', + 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', + 'sfs' => 'application/vnd.spotfire.sfs', + 'sgl' => 'application/vnd.stardivision.writer-global', + 'sgm' => 'text/sgml', + 'sgml' => 'text/sgml', + 'sh' => 'application/x-sh', + 'shar' => 'application/x-shar', + 'shf' => 'application/shf+xml', + 'sig' => 'application/pgp-signature', + 'silo' => 'model/mesh', + 'sis' => 'application/vnd.symbian.install', + 'sisx' => 'application/vnd.symbian.install', + 'sit' => 'application/x-stuffit', + 'sitx' => 'application/x-stuffitx', + 'skd' => 'application/vnd.koan', + 'skm' => 'application/vnd.koan', + 'skp' => 'application/vnd.koan', + 'skt' => 'application/vnd.koan', + 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', + 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'slt' => 'application/vnd.epson.salt', + 'sm' => 'application/vnd.stepmania.stepchart', + 'smf' => 'application/vnd.stardivision.math', + 'smi' => 'application/smil+xml', + 'smil' => 'application/smil+xml', + 'snd' => 'audio/basic', + 'snf' => 'application/x-font-snf', + 'so' => 'application/octet-stream', + 'spc' => 'application/x-pkcs7-certificates', + 'spf' => 'application/vnd.yamaha.smaf-phrase', + 'spl' => 'application/x-futuresplash', + 'spot' => 'text/vnd.in3d.spot', + 'spp' => 'application/scvp-vp-response', + 'spq' => 'application/scvp-vp-request', + 'spx' => 'audio/ogg', + 'src' => 'application/x-wais-source', + 'sru' => 'application/sru+xml', + 'srx' => 'application/sparql-results+xml', + 'sse' => 'application/vnd.kodak-descriptor', + 'ssf' => 'application/vnd.epson.ssf', + 'ssml' => 'application/ssml+xml', + 'st' => 'application/vnd.sailingtracker.track', + 'stc' => 'application/vnd.sun.xml.calc.template', + 'std' => 'application/vnd.sun.xml.draw.template', + 'stf' => 'application/vnd.wt.stf', + 'sti' => 'application/vnd.sun.xml.impress.template', + 'stk' => 'application/hyperstudio', + 'stl' => 'application/vnd.ms-pki.stl', + 'str' => 'application/vnd.pg.format', + 'stw' => 'application/vnd.sun.xml.writer.template', + 'sub' => 'image/vnd.dvb.subtitle', + 'sus' => 'application/vnd.sus-calendar', + 'susp' => 'application/vnd.sus-calendar', + 'sv4cpio' => 'application/x-sv4cpio', + 'sv4crc' => 'application/x-sv4crc', + 'svc' => 'application/vnd.dvb.service', + 'svd' => 'application/vnd.svd', + 'svg' => 'image/svg+xml', + 'svgz' => 'image/svg+xml', + 'swa' => 'application/x-director', + 'swf' => 'application/x-shockwave-flash', + 'swi' => 'application/vnd.aristanetworks.swi', + 'sxc' => 'application/vnd.sun.xml.calc', + 'sxd' => 'application/vnd.sun.xml.draw', + 'sxg' => 'application/vnd.sun.xml.writer.global', + 'sxi' => 'application/vnd.sun.xml.impress', + 'sxm' => 'application/vnd.sun.xml.math', + 'sxw' => 'application/vnd.sun.xml.writer', + 't' => 'text/troff', + 'tao' => 'application/vnd.tao.intent-module-archive', + 'tar' => 'application/x-tar', + 'tcap' => 'application/vnd.3gpp2.tcap', + 'tcl' => 'application/x-tcl', + 'teacher' => 'application/vnd.smart.teacher', + 'tei' => 'application/tei+xml', + 'teicorpus' => 'application/tei+xml', + 'tex' => 'application/x-tex', + 'texi' => 'application/x-texinfo', + 'texinfo' => 'application/x-texinfo', + 'text' => 'text/plain', + 'tfi' => 'application/thraud+xml', + 'tfm' => 'application/x-tex-tfm', + 'thmx' => 'application/vnd.ms-officetheme', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'tmo' => 'application/vnd.tmobile-livetv', + 'torrent' => 'application/x-bittorrent', + 'tpl' => 'application/vnd.groove-tool-template', + 'tpt' => 'application/vnd.trid.tpt', + 'tr' => 'text/troff', + 'tra' => 'application/vnd.trueapp', + 'trm' => 'application/x-msterminal', + 'tsd' => 'application/timestamped-data', + 'tsv' => 'text/tab-separated-values', + 'ttc' => 'application/x-font-ttf', + 'ttf' => 'application/x-font-ttf', + 'ttl' => 'text/turtle', + 'twd' => 'application/vnd.simtech-mindmapper', + 'twds' => 'application/vnd.simtech-mindmapper', + 'txd' => 'application/vnd.genomatix.tuxedo', + 'txf' => 'application/vnd.mobius.txf', + 'txt' => 'text/plain', + 'u32' => 'application/x-authorware-bin', + 'udeb' => 'application/x-debian-package', + 'ufd' => 'application/vnd.ufdl', + 'ufdl' => 'application/vnd.ufdl', + 'umj' => 'application/vnd.umajin', + 'unityweb' => 'application/vnd.unity', + 'uoml' => 'application/vnd.uoml+xml', + 'uri' => 'text/uri-list', + 'uris' => 'text/uri-list', + 'urls' => 'text/uri-list', + 'ustar' => 'application/x-ustar', + 'utz' => 'application/vnd.uiq.theme', + 'uu' => 'text/x-uuencode', + 'uva' => 'audio/vnd.dece.audio', + 'uvd' => 'application/vnd.dece.data', + 'uvf' => 'application/vnd.dece.data', + 'uvg' => 'image/vnd.dece.graphic', + 'uvh' => 'video/vnd.dece.hd', + 'uvi' => 'image/vnd.dece.graphic', + 'uvm' => 'video/vnd.dece.mobile', + 'uvp' => 'video/vnd.dece.pd', + 'uvs' => 'video/vnd.dece.sd', + 'uvt' => 'application/vnd.dece.ttml+xml', + 'uvu' => 'video/vnd.uvvu.mp4', + 'uvv' => 'video/vnd.dece.video', + 'uvva' => 'audio/vnd.dece.audio', + 'uvvd' => 'application/vnd.dece.data', + 'uvvf' => 'application/vnd.dece.data', + 'uvvg' => 'image/vnd.dece.graphic', + 'uvvh' => 'video/vnd.dece.hd', + 'uvvi' => 'image/vnd.dece.graphic', + 'uvvm' => 'video/vnd.dece.mobile', + 'uvvp' => 'video/vnd.dece.pd', + 'uvvs' => 'video/vnd.dece.sd', + 'uvvt' => 'application/vnd.dece.ttml+xml', + 'uvvu' => 'video/vnd.uvvu.mp4', + 'uvvv' => 'video/vnd.dece.video', + 'uvvx' => 'application/vnd.dece.unspecified', + 'uvx' => 'application/vnd.dece.unspecified', + 'vcd' => 'application/x-cdlink', + 'vcf' => 'text/x-vcard', + 'vcg' => 'application/vnd.groove-vcard', + 'vcs' => 'text/x-vcalendar', + 'vcx' => 'application/vnd.vcx', + 'vis' => 'application/vnd.visionary', + 'viv' => 'video/vnd.vivo', + 'vor' => 'application/vnd.stardivision.writer', + 'vox' => 'application/x-authorware-bin', + 'vrml' => 'model/vrml', + 'vsd' => 'application/vnd.visio', + 'vsf' => 'application/vnd.vsf', + 'vss' => 'application/vnd.visio', + 'vst' => 'application/vnd.visio', + 'vsw' => 'application/vnd.visio', + 'vtu' => 'model/vnd.vtu', + 'vxml' => 'application/voicexml+xml', + 'w3d' => 'application/x-director', + 'wad' => 'application/x-doom', + 'wav' => 'audio/x-wav', + 'wax' => 'audio/x-ms-wax', + 'wbmp' => 'image/vnd.wap.wbmp', + 'wbs' => 'application/vnd.criticaltools.wbs+xml', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wcm' => 'application/vnd.ms-works', + 'wdb' => 'application/vnd.ms-works', + 'weba' => 'audio/webm', + 'webm' => 'video/webm', + 'webp' => 'image/webp', + 'wg' => 'application/vnd.pmi.widget', + 'wgt' => 'application/widget', + 'wks' => 'application/vnd.ms-works', + 'wm' => 'video/x-ms-wm', + 'wma' => 'audio/x-ms-wma', + 'wmd' => 'application/x-ms-wmd', + 'wmf' => 'application/x-msmetafile', + 'wml' => 'text/vnd.wap.wml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'wmls' => 'text/vnd.wap.wmlscript', + 'wmlsc' => 'application/vnd.wap.wmlscriptc', + 'wmv' => 'video/x-ms-wmv', + 'wmx' => 'video/x-ms-wmx', + 'wmz' => 'application/x-ms-wmz', + 'woff' => 'application/x-font-woff', + 'wpd' => 'application/vnd.wordperfect', + 'wpl' => 'application/vnd.ms-wpl', + 'wps' => 'application/vnd.ms-works', + 'wqd' => 'application/vnd.wqd', + 'wri' => 'application/x-mswrite', + 'wrl' => 'model/vrml', + 'wsdl' => 'application/wsdl+xml', + 'wspolicy' => 'application/wspolicy+xml', + 'wtb' => 'application/vnd.webturbo', + 'wvx' => 'video/x-ms-wvx', + 'x32' => 'application/x-authorware-bin', + 'x3d' => 'application/vnd.hzn-3d-crossword', + 'xap' => 'application/x-silverlight-app', + 'xar' => 'application/vnd.xara', + 'xbap' => 'application/x-ms-xbap', + 'xbd' => 'application/vnd.fujixerox.docuworks.binder', + 'xbm' => 'image/x-xbitmap', + 'xdf' => 'application/xcap-diff+xml', + 'xdm' => 'application/vnd.syncml.dm+xml', + 'xdp' => 'application/vnd.adobe.xdp+xml', + 'xdssc' => 'application/dssc+xml', + 'xdw' => 'application/vnd.fujixerox.docuworks', + 'xenc' => 'application/xenc+xml', + 'xer' => 'application/patch-ops-error+xml', + 'xfdf' => 'application/vnd.adobe.xfdf', + 'xfdl' => 'application/vnd.xfdl', + 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', + 'xhvml' => 'application/xv+xml', + 'xif' => 'image/vnd.xiff', + 'xla' => 'application/vnd.ms-excel', + 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12', + 'xlc' => 'application/vnd.ms-excel', + 'xlm' => 'application/vnd.ms-excel', + 'xls' => 'application/vnd.ms-excel', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12', + 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xlt' => 'application/vnd.ms-excel', + 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'xlw' => 'application/vnd.ms-excel', + 'xml' => 'application/xml', + 'xo' => 'application/vnd.olpc-sugar', + 'xop' => 'application/xop+xml', + 'xpi' => 'application/x-xpinstall', + 'xpm' => 'image/x-xpixmap', + 'xpr' => 'application/vnd.is-xpr', + 'xps' => 'application/vnd.ms-xpsdocument', + 'xpw' => 'application/vnd.intercon.formnet', + 'xpx' => 'application/vnd.intercon.formnet', + 'xsl' => 'application/xml', + 'xslt' => 'application/xslt+xml', + 'xsm' => 'application/vnd.syncml+xml', + 'xspf' => 'application/xspf+xml', + 'xul' => 'application/vnd.mozilla.xul+xml', + 'xvm' => 'application/xv+xml', + 'xvml' => 'application/xv+xml', + 'xwd' => 'image/x-xwindowdump', + 'xyz' => 'chemical/x-xyz', + 'yaml' => 'text/yaml', + 'yang' => 'application/yang', + 'yin' => 'application/yin+xml', + 'yml' => 'text/yaml', + 'zaz' => 'application/vnd.zzazz.deck+xml', + 'zip' => 'application/zip', + 'zir' => 'application/vnd.zul', + 'zirz' => 'application/vnd.zul', + 'zmm' => 'application/vnd.handheld-entertainment+xml' + ]; + + /** + * Get a singleton instance of the class + * + * @return self + * @codeCoverageIgnore + */ + public static function getInstance() + { + if (!self::$instance) { + self::$instance = new self(); + } + + return self::$instance; + } + + /** + * Get a mimetype value from a file extension + * + * @param string $extension File extension + * + * @return string|null + */ + public function fromExtension($extension) + { + $extension = strtolower($extension); + + return isset($this->mimetypes[$extension]) ? $this->mimetypes[$extension] : null; + } + + /** + * Get a mimetype from a filename + * + * @param string $filename Filename to generate a mimetype from + * + * @return string|null + */ + public function fromFilename($filename) + { + return $this->fromExtension(pathinfo($filename, PATHINFO_EXTENSION)); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/Collection.php b/oauth/facebook-sdk-v5/GraphNodes/Collection.php new file mode 100644 index 0000000..cac010b --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/Collection.php @@ -0,0 +1,242 @@ +items = $items; + } + + /** + * Gets the value of a field from the Graph node. + * + * @param string $name The field to retrieve. + * @param mixed $default The default to return if the field doesn't exist. + * + * @return mixed + */ + public function getField($name, $default = null) + { + if (isset($this->items[$name])) { + return $this->items[$name]; + } + + return $default ?: null; + } + + /** + * Gets the value of the named property for this graph object. + * + * @param string $name The property to retrieve. + * @param mixed $default The default to return if the property doesn't exist. + * + * @return mixed + * + * @deprecated 5.0.0 getProperty() has been renamed to getField() + * @todo v6: Remove this method + */ + public function getProperty($name, $default = null) + { + return $this->getField($name, $default); + } + + /** + * Returns a list of all fields set on the object. + * + * @return array + */ + public function getFieldNames() + { + return array_keys($this->items); + } + + /** + * Returns a list of all properties set on the object. + * + * @return array + * + * @deprecated 5.0.0 getPropertyNames() has been renamed to getFieldNames() + * @todo v6: Remove this method + */ + public function getPropertyNames() + { + return $this->getFieldNames(); + } + + /** + * Get all of the items in the collection. + * + * @return array + */ + public function all() + { + return $this->items; + } + + /** + * Get the collection of items as a plain array. + * + * @return array + */ + public function asArray() + { + return array_map(function ($value) { + return $value instanceof Collection ? $value->asArray() : $value; + }, $this->items); + } + + /** + * Run a map over each of the items. + * + * @param \Closure $callback + * + * @return static + */ + public function map(\Closure $callback) + { + return new static(array_map($callback, $this->items, array_keys($this->items))); + } + + /** + * Get the collection of items as JSON. + * + * @param int $options + * + * @return string + */ + public function asJson($options = 0) + { + return json_encode($this->asArray(), $options); + } + + /** + * Count the number of items in the collection. + * + * @return int + */ + public function count() + { + return count($this->items); + } + + /** + * Get an iterator for the items. + * + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->items); + } + + /** + * Determine if an item exists at an offset. + * + * @param mixed $key + * + * @return bool + */ + public function offsetExists($key) + { + return array_key_exists($key, $this->items); + } + + /** + * Get an item at a given offset. + * + * @param mixed $key + * + * @return mixed + */ + public function offsetGet($key) + { + return $this->items[$key]; + } + + /** + * Set the item at a given offset. + * + * @param mixed $key + * @param mixed $value + * + * @return void + */ + public function offsetSet($key, $value) + { + if (is_null($key)) { + $this->items[] = $value; + } else { + $this->items[$key] = $value; + } + } + + /** + * Unset the item at a given offset. + * + * @param string $key + * + * @return void + */ + public function offsetUnset($key) + { + unset($this->items[$key]); + } + + /** + * Convert the collection to its string representation. + * + * @return string + */ + public function __toString() + { + return $this->asJson(); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphAchievement.php b/oauth/facebook-sdk-v5/GraphNodes/GraphAchievement.php new file mode 100644 index 0000000..3fba815 --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphAchievement.php @@ -0,0 +1,113 @@ + '\Facebook\GraphNodes\GraphUser', + 'application' => '\Facebook\GraphNodes\GraphApplication', + ]; + + /** + * Returns the ID for the achievement. + * + * @return string|null + */ + public function getId() + { + return $this->getField('id'); + } + + /** + * Returns the user who achieved this. + * + * @return GraphUser|null + */ + public function getFrom() + { + return $this->getField('from'); + } + + /** + * Returns the time at which this was achieved. + * + * @return \DateTime|null + */ + public function getPublishTime() + { + return $this->getField('publish_time'); + } + + /** + * Returns the app in which the user achieved this. + * + * @return GraphApplication|null + */ + public function getApplication() + { + return $this->getField('application'); + } + + /** + * Returns information about the achievement type this instance is connected with. + * + * @return array|null + */ + public function getData() + { + return $this->getField('data'); + } + + /** + * Returns the type of achievement. + * + * @see https://developers.facebook.com/docs/graph-api/reference/v2.2/achievement + * + * @return string + */ + public function getType() + { + return 'game.achievement'; + } + + /** + * Indicates whether gaining the achievement published a feed story for the user. + * + * @return boolean|null + */ + public function isNoFeedStory() + { + return $this->getField('no_feed_story'); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphAlbum.php b/oauth/facebook-sdk-v5/GraphNodes/GraphAlbum.php new file mode 100644 index 0000000..50d1f2c --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphAlbum.php @@ -0,0 +1,183 @@ + '\Facebook\GraphNodes\GraphUser', + 'place' => '\Facebook\GraphNodes\GraphPage', + ]; + + /** + * Returns the ID for the album. + * + * @return string|null + */ + public function getId() + { + return $this->getField('id'); + } + + /** + * Returns whether the viewer can upload photos to this album. + * + * @return boolean|null + */ + public function getCanUpload() + { + return $this->getField('can_upload'); + } + + /** + * Returns the number of photos in this album. + * + * @return int|null + */ + public function getCount() + { + return $this->getField('count'); + } + + /** + * Returns the ID of the album's cover photo. + * + * @return string|null + */ + public function getCoverPhoto() + { + return $this->getField('cover_photo'); + } + + /** + * Returns the time the album was initially created. + * + * @return \DateTime|null + */ + public function getCreatedTime() + { + return $this->getField('created_time'); + } + + /** + * Returns the time the album was updated. + * + * @return \DateTime|null + */ + public function getUpdatedTime() + { + return $this->getField('updated_time'); + } + + /** + * Returns the description of the album. + * + * @return string|null + */ + public function getDescription() + { + return $this->getField('description'); + } + + /** + * Returns profile that created the album. + * + * @return GraphUser|null + */ + public function getFrom() + { + return $this->getField('from'); + } + + /** + * Returns profile that created the album. + * + * @return GraphPage|null + */ + public function getPlace() + { + return $this->getField('place'); + } + + /** + * Returns a link to this album on Facebook. + * + * @return string|null + */ + public function getLink() + { + return $this->getField('link'); + } + + /** + * Returns the textual location of the album. + * + * @return string|null + */ + public function getLocation() + { + return $this->getField('location'); + } + + /** + * Returns the title of the album. + * + * @return string|null + */ + public function getName() + { + return $this->getField('name'); + } + + /** + * Returns the privacy settings for the album. + * + * @return string|null + */ + public function getPrivacy() + { + return $this->getField('privacy'); + } + + /** + * Returns the type of the album. + * + * enum{ profile, mobile, wall, normal, album } + * + * @return string|null + */ + public function getType() + { + return $this->getField('type'); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphApplication.php b/oauth/facebook-sdk-v5/GraphNodes/GraphApplication.php new file mode 100644 index 0000000..69b09bb --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphApplication.php @@ -0,0 +1,43 @@ +getField('id'); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphCoverPhoto.php b/oauth/facebook-sdk-v5/GraphNodes/GraphCoverPhoto.php new file mode 100644 index 0000000..ee60750 --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphCoverPhoto.php @@ -0,0 +1,72 @@ +getField('id'); + } + + /** + * Returns the source of cover if it exists + * + * @return string|null + */ + public function getSource() + { + return $this->getField('source'); + } + + /** + * Returns the offset_x of cover if it exists + * + * @return int|null + */ + public function getOffsetX() + { + return $this->getField('offset_x'); + } + + /** + * Returns the offset_y of cover if it exists + * + * @return int|null + */ + public function getOffsetY() + { + return $this->getField('offset_y'); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphEdge.php b/oauth/facebook-sdk-v5/GraphNodes/GraphEdge.php new file mode 100644 index 0000000..95f3284 --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphEdge.php @@ -0,0 +1,260 @@ +request = $request; + $this->metaData = $metaData; + $this->parentEdgeEndpoint = $parentEdgeEndpoint; + $this->subclassName = $subclassName; + + parent::__construct($data); + } + + /** + * Gets the parent Graph edge endpoint that generated the list. + * + * @return string|null + */ + public function getParentGraphEdge() + { + return $this->parentEdgeEndpoint; + } + + /** + * Gets the subclass name that the child GraphNode's are cast as. + * + * @return string|null + */ + public function getSubClassName() + { + return $this->subclassName; + } + + /** + * Returns the raw meta data associated with this GraphEdge. + * + * @return array + */ + public function getMetaData() + { + return $this->metaData; + } + + /** + * Returns the next cursor if it exists. + * + * @return string|null + */ + public function getNextCursor() + { + return $this->getCursor('after'); + } + + /** + * Returns the previous cursor if it exists. + * + * @return string|null + */ + public function getPreviousCursor() + { + return $this->getCursor('before'); + } + + /** + * Returns the cursor for a specific direction if it exists. + * + * @param string $direction The direction of the page: after|before + * + * @return string|null + */ + public function getCursor($direction) + { + if (isset($this->metaData['paging']['cursors'][$direction])) { + return $this->metaData['paging']['cursors'][$direction]; + } + + return null; + } + + /** + * Generates a pagination URL based on a cursor. + * + * @param string $direction The direction of the page: next|previous + * + * @return string|null + * + * @throws FacebookSDKException + */ + public function getPaginationUrl($direction) + { + $this->validateForPagination(); + + // Do we have a paging URL? + if (isset($this->metaData['paging'][$direction])) { + // Graph returns the full URL with all the original params. + // We just want the endpoint though. + $pageUrl = $this->metaData['paging'][$direction]; + + return FacebookUrlManipulator::baseGraphUrlEndpoint($pageUrl); + } + + // Do we have a cursor to work with? + $cursorDirection = $direction === 'next' ? 'after' : 'before'; + $cursor = $this->getCursor($cursorDirection); + if (!$cursor) { + return null; + } + + // If we don't know the ID of the parent node, this ain't gonna work. + if (!$this->parentEdgeEndpoint) { + return null; + } + + // We have the parent node ID, paging cursor & original request. + // These were the ingredients chosen to create the perfect little URL. + $pageUrl = $this->parentEdgeEndpoint . '?' . $cursorDirection . '=' . urlencode($cursor); + + // Pull in the original params + $originalUrl = $this->request->getUrl(); + $pageUrl = FacebookUrlManipulator::mergeUrlParams($originalUrl, $pageUrl); + + return FacebookUrlManipulator::forceSlashPrefix($pageUrl); + } + + /** + * Validates whether or not we can paginate on this request. + * + * @throws FacebookSDKException + */ + public function validateForPagination() + { + if ($this->request->getMethod() !== 'GET') { + throw new FacebookSDKException('You can only paginate on a GET request.', 720); + } + } + + /** + * Gets the request object needed to make a next|previous page request. + * + * @param string $direction The direction of the page: next|previous + * + * @return FacebookRequest|null + * + * @throws FacebookSDKException + */ + public function getPaginationRequest($direction) + { + $pageUrl = $this->getPaginationUrl($direction); + if (!$pageUrl) { + return null; + } + + $newRequest = clone $this->request; + $newRequest->setEndpoint($pageUrl); + + return $newRequest; + } + + /** + * Gets the request object needed to make a "next" page request. + * + * @return FacebookRequest|null + * + * @throws FacebookSDKException + */ + public function getNextPageRequest() + { + return $this->getPaginationRequest('next'); + } + + /** + * Gets the request object needed to make a "previous" page request. + * + * @return FacebookRequest|null + * + * @throws FacebookSDKException + */ + public function getPreviousPageRequest() + { + return $this->getPaginationRequest('previous'); + } + + /** + * The total number of results according to Graph if it exists. + * + * This will be returned if the summary=true modifier is present in the request. + * + * @return int|null + */ + public function getTotalCount() + { + if (isset($this->metaData['summary']['total_count'])) { + return $this->metaData['summary']['total_count']; + } + + return null; + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphEvent.php b/oauth/facebook-sdk-v5/GraphNodes/GraphEvent.php new file mode 100644 index 0000000..19ff2fb --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphEvent.php @@ -0,0 +1,242 @@ + '\Facebook\GraphNodes\GraphCoverPhoto', + 'place' => '\Facebook\GraphNodes\GraphPage', + 'picture' => '\Facebook\GraphNodes\GraphPicture', + 'parent_group' => '\Facebook\GraphNodes\GraphGroup', + ]; + + /** + * Returns the `id` (The event ID) as string if present. + * + * @return string|null + */ + public function getId() + { + return $this->getField('id'); + } + + /** + * Returns the `cover` (Cover picture) as GraphCoverPhoto if present. + * + * @return GraphCoverPhoto|null + */ + public function getCover() + { + return $this->getField('cover'); + } + + /** + * Returns the `description` (Long-form description) as string if present. + * + * @return string|null + */ + public function getDescription() + { + return $this->getField('description'); + } + + /** + * Returns the `end_time` (End time, if one has been set) as DateTime if present. + * + * @return \DateTime|null + */ + public function getEndTime() + { + return $this->getField('end_time'); + } + + /** + * Returns the `is_date_only` (Whether the event only has a date specified, but no time) as bool if present. + * + * @return bool|null + */ + public function getIsDateOnly() + { + return $this->getField('is_date_only'); + } + + /** + * Returns the `name` (Event name) as string if present. + * + * @return string|null + */ + public function getName() + { + return $this->getField('name'); + } + + /** + * Returns the `owner` (The profile that created the event) as GraphNode if present. + * + * @return GraphNode|null + */ + public function getOwner() + { + return $this->getField('owner'); + } + + /** + * Returns the `parent_group` (The group the event belongs to) as GraphGroup if present. + * + * @return GraphGroup|null + */ + public function getParentGroup() + { + return $this->getField('parent_group'); + } + + /** + * Returns the `place` (Event Place information) as GraphPage if present. + * + * @return GraphPage|null + */ + public function getPlace() + { + return $this->getField('place'); + } + + /** + * Returns the `privacy` (Who can see the event) as string if present. + * + * @return string|null + */ + public function getPrivacy() + { + return $this->getField('privacy'); + } + + /** + * Returns the `start_time` (Start time) as DateTime if present. + * + * @return \DateTime|null + */ + public function getStartTime() + { + return $this->getField('start_time'); + } + + /** + * Returns the `ticket_uri` (The link users can visit to buy a ticket to this event) as string if present. + * + * @return string|null + */ + public function getTicketUri() + { + return $this->getField('ticket_uri'); + } + + /** + * Returns the `timezone` (Timezone) as string if present. + * + * @return string|null + */ + public function getTimezone() + { + return $this->getField('timezone'); + } + + /** + * Returns the `updated_time` (Last update time) as DateTime if present. + * + * @return \DateTime|null + */ + public function getUpdatedTime() + { + return $this->getField('updated_time'); + } + + /** + * Returns the `picture` (Event picture) as GraphPicture if present. + * + * @return GraphPicture|null + */ + public function getPicture() + { + return $this->getField('picture'); + } + + /** + * Returns the `attending_count` (Number of people attending the event) as int if present. + * + * @return int|null + */ + public function getAttendingCount() + { + return $this->getField('attending_count'); + } + + /** + * Returns the `declined_count` (Number of people who declined the event) as int if present. + * + * @return int|null + */ + public function getDeclinedCount() + { + return $this->getField('declined_count'); + } + + /** + * Returns the `maybe_count` (Number of people who maybe going to the event) as int if present. + * + * @return int|null + */ + public function getMaybeCount() + { + return $this->getField('maybe_count'); + } + + /** + * Returns the `noreply_count` (Number of people who did not reply to the event) as int if present. + * + * @return int|null + */ + public function getNoreplyCount() + { + return $this->getField('noreply_count'); + } + + /** + * Returns the `invited_count` (Number of people invited to the event) as int if present. + * + * @return int|null + */ + public function getInvitedCount() + { + return $this->getField('invited_count'); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphGroup.php b/oauth/facebook-sdk-v5/GraphNodes/GraphGroup.php new file mode 100644 index 0000000..07a4dbd --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphGroup.php @@ -0,0 +1,171 @@ + '\Facebook\GraphNodes\GraphCoverPhoto', + 'venue' => '\Facebook\GraphNodes\GraphLocation', + ]; + + /** + * Returns the `id` (The Group ID) as string if present. + * + * @return string|null + */ + public function getId() + { + return $this->getField('id'); + } + + /** + * Returns the `cover` (The cover photo of the Group) as GraphCoverPhoto if present. + * + * @return GraphCoverPhoto|null + */ + public function getCover() + { + return $this->getField('cover'); + } + + /** + * Returns the `description` (A brief description of the Group) as string if present. + * + * @return string|null + */ + public function getDescription() + { + return $this->getField('description'); + } + + /** + * Returns the `email` (The email address to upload content to the Group. Only current members of the Group can use this) as string if present. + * + * @return string|null + */ + public function getEmail() + { + return $this->getField('email'); + } + + /** + * Returns the `icon` (The URL for the Group's icon) as string if present. + * + * @return string|null + */ + public function getIcon() + { + return $this->getField('icon'); + } + + /** + * Returns the `link` (The Group's website) as string if present. + * + * @return string|null + */ + public function getLink() + { + return $this->getField('link'); + } + + /** + * Returns the `name` (The name of the Group) as string if present. + * + * @return string|null + */ + public function getName() + { + return $this->getField('name'); + } + + /** + * Returns the `member_request_count` (Number of people asking to join the group.) as int if present. + * + * @return int|null + */ + public function getMemberRequestCount() + { + return $this->getField('member_request_count'); + } + + /** + * Returns the `owner` (The profile that created this Group) as GraphNode if present. + * + * @return GraphNode|null + */ + public function getOwner() + { + return $this->getField('owner'); + } + + /** + * Returns the `parent` (The parent Group of this Group, if it exists) as GraphNode if present. + * + * @return GraphNode|null + */ + public function getParent() + { + return $this->getField('parent'); + } + + /** + * Returns the `privacy` (The privacy setting of the Group) as string if present. + * + * @return string|null + */ + public function getPrivacy() + { + return $this->getField('privacy'); + } + + /** + * Returns the `updated_time` (The last time the Group was updated (this includes changes in the Group's properties and changes in posts and comments if user can see them)) as \DateTime if present. + * + * @return \DateTime|null + */ + public function getUpdatedTime() + { + return $this->getField('updated_time'); + } + + /** + * Returns the `venue` (The location for the Group) as GraphLocation if present. + * + * @return GraphLocation|null + */ + public function getVenue() + { + return $this->getField('venue'); + } + +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphList.php b/oauth/facebook-sdk-v5/GraphNodes/GraphList.php new file mode 100644 index 0000000..a60a07a --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphList.php @@ -0,0 +1,36 @@ +getField('street'); + } + + /** + * Returns the city component of the location + * + * @return string|null + */ + public function getCity() + { + return $this->getField('city'); + } + + /** + * Returns the state component of the location + * + * @return string|null + */ + public function getState() + { + return $this->getField('state'); + } + + /** + * Returns the country component of the location + * + * @return string|null + */ + public function getCountry() + { + return $this->getField('country'); + } + + /** + * Returns the zipcode component of the location + * + * @return string|null + */ + public function getZip() + { + return $this->getField('zip'); + } + + /** + * Returns the latitude component of the location + * + * @return float|null + */ + public function getLatitude() + { + return $this->getField('latitude'); + } + + /** + * Returns the street component of the location + * + * @return float|null + */ + public function getLongitude() + { + return $this->getField('longitude'); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphNode.php b/oauth/facebook-sdk-v5/GraphNodes/GraphNode.php new file mode 100644 index 0000000..0d2f504 --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphNode.php @@ -0,0 +1,185 @@ +castItems($data)); + } + + /** + * Iterates over an array and detects the types each node + * should be cast to and returns all the items as an array. + * + * @TODO Add auto-casting to AccessToken entities. + * + * @param array $data The array to iterate over. + * + * @return array + */ + public function castItems(array $data) + { + $items = []; + + foreach ($data as $k => $v) { + if ($this->shouldCastAsDateTime($k) + && (is_numeric($v) + || $k === 'birthday' + || $this->isIso8601DateString($v)) + ) { + $items[$k] = $this->castToDateTime($v); + } else { + $items[$k] = $v; + } + } + + return $items; + } + + /** + * Uncasts any auto-casted datatypes. + * Basically the reverse of castItems(). + * + * @return array + */ + public function uncastItems() + { + $items = $this->asArray(); + + return array_map(function ($v) { + if ($v instanceof \DateTime) { + return $v->format(\DateTime::ISO8601); + } + + return $v; + }, $items); + } + + /** + * Get the collection of items as JSON. + * + * @param int $options + * + * @return string + */ + public function asJson($options = 0) + { + return json_encode($this->uncastItems(), $options); + } + + /** + * Detects an ISO 8601 formatted string. + * + * @param string $string + * + * @return boolean + * + * @see https://developers.facebook.com/docs/graph-api/using-graph-api/#readmodifiers + * @see http://www.cl.cam.ac.uk/~mgk25/iso-time.html + * @see http://en.wikipedia.org/wiki/ISO_8601 + */ + public function isIso8601DateString($string) + { + // This insane regex was yoinked from here: + // http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/ + // ...and I'm all like: + // http://thecodinglove.com/post/95378251969/when-code-works-and-i-dont-know-why + $crazyInsaneRegexThatSomehowDetectsIso8601 = '/^([\+-]?\d{4}(?!\d{2}\b))' + . '((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?' + . '|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d' + . '|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])' + . '((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d' + . '([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/'; + + return preg_match($crazyInsaneRegexThatSomehowDetectsIso8601, $string) === 1; + } + + /** + * Determines if a value from Graph should be cast to DateTime. + * + * @param string $key + * + * @return boolean + */ + public function shouldCastAsDateTime($key) + { + return in_array($key, [ + 'created_time', + 'updated_time', + 'start_time', + 'end_time', + 'backdated_time', + 'issued_at', + 'expires_at', + 'birthday', + 'publish_time' + ], true); + } + + /** + * Casts a date value from Graph to DateTime. + * + * @param int|string $value + * + * @return \DateTime + */ + public function castToDateTime($value) + { + if (is_int($value)) { + $dt = new \DateTime(); + $dt->setTimestamp($value); + } else { + $dt = new \DateTime($value); + } + + return $dt; + } + + /** + * Getter for $graphObjectMap. + * + * @return array + */ + public static function getObjectMap() + { + return static::$graphObjectMap; + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphNodeFactory.php b/oauth/facebook-sdk-v5/GraphNodes/GraphNodeFactory.php new file mode 100644 index 0000000..e1bedd9 --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphNodeFactory.php @@ -0,0 +1,392 @@ +response = $response; + $this->decodedBody = $response->getDecodedBody(); + } + + /** + * Tries to convert a FacebookResponse entity into a GraphNode. + * + * @param string|null $subclassName The GraphNode sub class to cast to. + * + * @return GraphNode + * + * @throws FacebookSDKException + */ + public function makeGraphNode($subclassName = null) + { + $this->validateResponseAsArray(); + $this->validateResponseCastableAsGraphNode(); + + return $this->castAsGraphNodeOrGraphEdge($this->decodedBody, $subclassName); + } + + /** + * Convenience method for creating a GraphAchievement collection. + * + * @return GraphAchievement + * + * @throws FacebookSDKException + */ + public function makeGraphAchievement() + { + return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphAchievement'); + } + + /** + * Convenience method for creating a GraphAlbum collection. + * + * @return GraphAlbum + * + * @throws FacebookSDKException + */ + public function makeGraphAlbum() + { + return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphAlbum'); + } + + /** + * Convenience method for creating a GraphPage collection. + * + * @return GraphPage + * + * @throws FacebookSDKException + */ + public function makeGraphPage() + { + return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphPage'); + } + + /** + * Convenience method for creating a GraphSessionInfo collection. + * + * @return GraphSessionInfo + * + * @throws FacebookSDKException + */ + public function makeGraphSessionInfo() + { + return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphSessionInfo'); + } + + /** + * Convenience method for creating a GraphUser collection. + * + * @return GraphUser + * + * @throws FacebookSDKException + */ + public function makeGraphUser() + { + return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphUser'); + } + + /** + * Convenience method for creating a GraphEvent collection. + * + * @return GraphEvent + * + * @throws FacebookSDKException + */ + public function makeGraphEvent() + { + return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphEvent'); + } + + /** + * Convenience method for creating a GraphGroup collection. + * + * @return GraphGroup + * + * @throws FacebookSDKException + */ + public function makeGraphGroup() + { + return $this->makeGraphNode(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphGroup'); + } + + /** + * Tries to convert a FacebookResponse entity into a GraphEdge. + * + * @param string|null $subclassName The GraphNode sub class to cast the list items to. + * @param boolean $auto_prefix Toggle to auto-prefix the subclass name. + * + * @return GraphEdge + * + * @throws FacebookSDKException + */ + public function makeGraphEdge($subclassName = null, $auto_prefix = true) + { + $this->validateResponseAsArray(); + $this->validateResponseCastableAsGraphEdge(); + + if ($subclassName && $auto_prefix) { + $subclassName = static::BASE_GRAPH_OBJECT_PREFIX . $subclassName; + } + + return $this->castAsGraphNodeOrGraphEdge($this->decodedBody, $subclassName); + } + + /** + * Validates the decoded body. + * + * @throws FacebookSDKException + */ + public function validateResponseAsArray() + { + if (!is_array($this->decodedBody)) { + throw new FacebookSDKException('Unable to get response from Graph as array.', 620); + } + } + + /** + * Validates that the return data can be cast as a GraphNode. + * + * @throws FacebookSDKException + */ + public function validateResponseCastableAsGraphNode() + { + if (isset($this->decodedBody['data']) && static::isCastableAsGraphEdge($this->decodedBody['data'])) { + throw new FacebookSDKException( + 'Unable to convert response from Graph to a GraphNode because the response looks like a GraphEdge. Try using GraphNodeFactory::makeGraphEdge() instead.', + 620 + ); + } + } + + /** + * Validates that the return data can be cast as a GraphEdge. + * + * @throws FacebookSDKException + */ + public function validateResponseCastableAsGraphEdge() + { + if (!(isset($this->decodedBody['data']) && static::isCastableAsGraphEdge($this->decodedBody['data']))) { + throw new FacebookSDKException( + 'Unable to convert response from Graph to a GraphEdge because the response does not look like a GraphEdge. Try using GraphNodeFactory::makeGraphNode() instead.', + 620 + ); + } + } + + /** + * Safely instantiates a GraphNode of $subclassName. + * + * @param array $data The array of data to iterate over. + * @param string|null $subclassName The subclass to cast this collection to. + * + * @return GraphNode + * + * @throws FacebookSDKException + */ + public function safelyMakeGraphNode(array $data, $subclassName = null) + { + $subclassName = $subclassName ?: static::BASE_GRAPH_NODE_CLASS; + static::validateSubclass($subclassName); + + // Remember the parent node ID + $parentNodeId = isset($data['id']) ? $data['id'] : null; + + $items = []; + + foreach ($data as $k => $v) { + // Array means could be recurable + if (is_array($v)) { + // Detect any smart-casting from the $graphObjectMap array. + // This is always empty on the GraphNode collection, but subclasses can define + // their own array of smart-casting types. + $graphObjectMap = $subclassName::getObjectMap(); + $objectSubClass = isset($graphObjectMap[$k]) + ? $graphObjectMap[$k] + : null; + + // Could be a GraphEdge or GraphNode + $items[$k] = $this->castAsGraphNodeOrGraphEdge($v, $objectSubClass, $k, $parentNodeId); + } else { + $items[$k] = $v; + } + } + + return new $subclassName($items); + } + + /** + * Takes an array of values and determines how to cast each node. + * + * @param array $data The array of data to iterate over. + * @param string|null $subclassName The subclass to cast this collection to. + * @param string|null $parentKey The key of this data (Graph edge). + * @param string|null $parentNodeId The parent Graph node ID. + * + * @return GraphNode|GraphEdge + * + * @throws FacebookSDKException + */ + public function castAsGraphNodeOrGraphEdge(array $data, $subclassName = null, $parentKey = null, $parentNodeId = null) + { + if (isset($data['data'])) { + // Create GraphEdge + if (static::isCastableAsGraphEdge($data['data'])) { + return $this->safelyMakeGraphEdge($data, $subclassName, $parentKey, $parentNodeId); + } + // Sometimes Graph is a weirdo and returns a GraphNode under the "data" key + $data = $data['data']; + } + + // Create GraphNode + return $this->safelyMakeGraphNode($data, $subclassName); + } + + /** + * Return an array of GraphNode's. + * + * @param array $data The array of data to iterate over. + * @param string|null $subclassName The GraphNode subclass to cast each item in the list to. + * @param string|null $parentKey The key of this data (Graph edge). + * @param string|null $parentNodeId The parent Graph node ID. + * + * @return GraphEdge + * + * @throws FacebookSDKException + */ + public function safelyMakeGraphEdge(array $data, $subclassName = null, $parentKey = null, $parentNodeId = null) + { + if (!isset($data['data'])) { + throw new FacebookSDKException('Cannot cast data to GraphEdge. Expected a "data" key.', 620); + } + + $dataList = []; + foreach ($data['data'] as $graphNode) { + $dataList[] = $this->safelyMakeGraphNode($graphNode, $subclassName, $parentKey, $parentNodeId); + } + + $metaData = $this->getMetaData($data); + + // We'll need to make an edge endpoint for this in case it's a GraphEdge (for cursor pagination) + $parentGraphEdgeEndpoint = $parentNodeId && $parentKey ? '/' . $parentNodeId . '/' . $parentKey : null; + $className = static::BASE_GRAPH_EDGE_CLASS; + + return new $className($this->response->getRequest(), $dataList, $metaData, $parentGraphEdgeEndpoint, $subclassName); + } + + /** + * Get the meta data from a list in a Graph response. + * + * @param array $data The Graph response. + * + * @return array + */ + public function getMetaData(array $data) + { + unset($data['data']); + + return $data; + } + + /** + * Determines whether or not the data should be cast as a GraphEdge. + * + * @param array $data + * + * @return boolean + */ + public static function isCastableAsGraphEdge(array $data) + { + if ($data === []) { + return true; + } + + // Checks for a sequential numeric array which would be a GraphEdge + return array_keys($data) === range(0, count($data) - 1); + } + + /** + * Ensures that the subclass in question is valid. + * + * @param string $subclassName The GraphNode subclass to validate. + * + * @throws FacebookSDKException + */ + public static function validateSubclass($subclassName) + { + if ($subclassName == static::BASE_GRAPH_NODE_CLASS || is_subclass_of($subclassName, static::BASE_GRAPH_NODE_CLASS)) { + return; + } + + throw new FacebookSDKException('The given subclass "' . $subclassName . '" is not valid. Cannot cast to an object that is not a GraphNode subclass.', 620); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphObject.php b/oauth/facebook-sdk-v5/GraphNodes/GraphObject.php new file mode 100644 index 0000000..bb8f8e4 --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphObject.php @@ -0,0 +1,36 @@ +makeGraphNode($subclassName); + } + + /** + * Convenience method for creating a GraphEvent collection. + * + * @return GraphEvent + * + * @throws FacebookSDKException + */ + public function makeGraphEvent() + { + return $this->makeGraphObject(static::BASE_GRAPH_OBJECT_PREFIX . 'GraphEvent'); + } + + /** + * Tries to convert a FacebookResponse entity into a GraphEdge. + * + * @param string|null $subclassName The GraphNode sub class to cast the list items to. + * @param boolean $auto_prefix Toggle to auto-prefix the subclass name. + * + * @return GraphEdge + * + * @deprecated 5.0.0 GraphObjectFactory has been renamed to GraphNodeFactory + */ + public function makeGraphList($subclassName = null, $auto_prefix = true) + { + return $this->makeGraphEdge($subclassName, $auto_prefix); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphPage.php b/oauth/facebook-sdk-v5/GraphNodes/GraphPage.php new file mode 100644 index 0000000..ab8e31a --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphPage.php @@ -0,0 +1,125 @@ + '\Facebook\GraphNodes\GraphPage', + 'global_brand_parent_page' => '\Facebook\GraphNodes\GraphPage', + 'location' => '\Facebook\GraphNodes\GraphLocation', + ]; + + /** + * Returns the ID for the user's page as a string if present. + * + * @return string|null + */ + public function getId() + { + return $this->getField('id'); + } + + /** + * Returns the Category for the user's page as a string if present. + * + * @return string|null + */ + public function getCategory() + { + return $this->getField('category'); + } + + /** + * Returns the Name of the user's page as a string if present. + * + * @return string|null + */ + public function getName() + { + return $this->getField('name'); + } + + /** + * Returns the best available Page on Facebook. + * + * @return GraphPage|null + */ + public function getBestPage() + { + return $this->getField('best_page'); + } + + /** + * Returns the brand's global (parent) Page. + * + * @return GraphPage|null + */ + public function getGlobalBrandParentPage() + { + return $this->getField('global_brand_parent_page'); + } + + /** + * Returns the location of this place. + * + * @return GraphLocation|null + */ + public function getLocation() + { + return $this->getField('location'); + } + + /** + * Returns the page access token for the admin user. + * + * Only available in the `/me/accounts` context. + * + * @return string|null + */ + public function getAccessToken() + { + return $this->getField('access_token'); + } + + /** + * Returns the roles of the page admin user. + * + * Only available in the `/me/accounts` context. + * + * @return array|null + */ + public function getPerms() + { + return $this->getField('perms'); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphPicture.php b/oauth/facebook-sdk-v5/GraphNodes/GraphPicture.php new file mode 100644 index 0000000..bfd37fa --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphPicture.php @@ -0,0 +1,72 @@ +getField('is_silhouette'); + } + + /** + * Returns the url of user picture if it exists + * + * @return string|null + */ + public function getUrl() + { + return $this->getField('url'); + } + + /** + * Returns the width of user picture if it exists + * + * @return int|null + */ + public function getWidth() + { + return $this->getField('width'); + } + + /** + * Returns the height of user picture if it exists + * + * @return int|null + */ + public function getHeight() + { + return $this->getField('height'); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphSessionInfo.php b/oauth/facebook-sdk-v5/GraphNodes/GraphSessionInfo.php new file mode 100644 index 0000000..3c9e2ff --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphSessionInfo.php @@ -0,0 +1,102 @@ +getField('app_id'); + } + + /** + * Returns the application name the token was issued for. + * + * @return string|null + */ + public function getApplication() + { + return $this->getField('application'); + } + + /** + * Returns the date & time that the token expires. + * + * @return \DateTime|null + */ + public function getExpiresAt() + { + return $this->getField('expires_at'); + } + + /** + * Returns whether the token is valid. + * + * @return boolean + */ + public function getIsValid() + { + return $this->getField('is_valid'); + } + + /** + * Returns the date & time the token was issued at. + * + * @return \DateTime|null + */ + public function getIssuedAt() + { + return $this->getField('issued_at'); + } + + /** + * Returns the scope permissions associated with the token. + * + * @return array + */ + public function getScopes() + { + return $this->getField('scopes'); + } + + /** + * Returns the login id of the user associated with the token. + * + * @return string|null + */ + public function getUserId() + { + return $this->getField('user_id'); + } +} diff --git a/oauth/facebook-sdk-v5/GraphNodes/GraphUser.php b/oauth/facebook-sdk-v5/GraphNodes/GraphUser.php new file mode 100644 index 0000000..cb9ddbb --- /dev/null +++ b/oauth/facebook-sdk-v5/GraphNodes/GraphUser.php @@ -0,0 +1,162 @@ + '\Facebook\GraphNodes\GraphPage', + 'location' => '\Facebook\GraphNodes\GraphPage', + 'significant_other' => '\Facebook\GraphNodes\GraphUser', + 'picture' => '\Facebook\GraphNodes\GraphPicture', + ]; + + /** + * Returns the ID for the user as a string if present. + * + * @return string|null + */ + public function getId() + { + return $this->getField('id'); + } + + /** + * Returns the name for the user as a string if present. + * + * @return string|null + */ + public function getName() + { + return $this->getField('name'); + } + + /** + * Returns the first name for the user as a string if present. + * + * @return string|null + */ + public function getFirstName() + { + return $this->getField('first_name'); + } + + /** + * Returns the middle name for the user as a string if present. + * + * @return string|null + */ + public function getMiddleName() + { + return $this->getField('middle_name'); + } + + /** + * Returns the last name for the user as a string if present. + * + * @return string|null + */ + public function getLastName() + { + return $this->getField('last_name'); + } + + /** + * Returns the gender for the user as a string if present. + * + * @return string|null + */ + public function getGender() + { + return $this->getField('gender'); + } + + /** + * Returns the Facebook URL for the user as a string if available. + * + * @return string|null + */ + public function getLink() + { + return $this->getField('link'); + } + + /** + * Returns the users birthday, if available. + * + * @return \DateTime|null + */ + public function getBirthday() + { + return $this->getField('birthday'); + } + + /** + * Returns the current location of the user as a GraphPage. + * + * @return GraphPage|null + */ + public function getLocation() + { + return $this->getField('location'); + } + + /** + * Returns the current location of the user as a GraphPage. + * + * @return GraphPage|null + */ + public function getHometown() + { + return $this->getField('hometown'); + } + + /** + * Returns the current location of the user as a GraphUser. + * + * @return GraphUser|null + */ + public function getSignificantOther() + { + return $this->getField('significant_other'); + } + + /** + * Returns the picture of the user as a GraphPicture + * + * @return GraphPicture|null + */ + public function getPicture() + { + return $this->getField('picture'); + } +} diff --git a/oauth/facebook-sdk-v5/Helpers/FacebookCanvasHelper.php b/oauth/facebook-sdk-v5/Helpers/FacebookCanvasHelper.php new file mode 100644 index 0000000..8068526 --- /dev/null +++ b/oauth/facebook-sdk-v5/Helpers/FacebookCanvasHelper.php @@ -0,0 +1,52 @@ +signedRequest ? $this->signedRequest->get('app_data') : null; + } + + /** + * Get raw signed request from POST. + * + * @return string|null + */ + public function getRawSignedRequest() + { + return $this->getRawSignedRequestFromPost() ?: null; + } +} diff --git a/oauth/facebook-sdk-v5/Helpers/FacebookJavaScriptHelper.php b/oauth/facebook-sdk-v5/Helpers/FacebookJavaScriptHelper.php new file mode 100644 index 0000000..5d406b5 --- /dev/null +++ b/oauth/facebook-sdk-v5/Helpers/FacebookJavaScriptHelper.php @@ -0,0 +1,42 @@ +getRawSignedRequestFromCookie(); + } +} diff --git a/oauth/facebook-sdk-v5/Helpers/FacebookPageTabHelper.php b/oauth/facebook-sdk-v5/Helpers/FacebookPageTabHelper.php new file mode 100644 index 0000000..ee43f5e --- /dev/null +++ b/oauth/facebook-sdk-v5/Helpers/FacebookPageTabHelper.php @@ -0,0 +1,95 @@ +signedRequest) { + return; + } + + $this->pageData = $this->signedRequest->get('page'); + } + + /** + * Returns a value from the page data. + * + * @param string $key + * @param mixed|null $default + * + * @return mixed|null + */ + public function getPageData($key, $default = null) + { + if (isset($this->pageData[$key])) { + return $this->pageData[$key]; + } + + return $default; + } + + /** + * Returns true if the user is an admin. + * + * @return boolean + */ + public function isAdmin() + { + return $this->getPageData('admin') === true; + } + + /** + * Returns the page id if available. + * + * @return string|null + */ + public function getPageId() + { + return $this->getPageData('id'); + } +} diff --git a/oauth/facebook-sdk-v5/Helpers/FacebookRedirectLoginHelper.php b/oauth/facebook-sdk-v5/Helpers/FacebookRedirectLoginHelper.php new file mode 100644 index 0000000..144a5b4 --- /dev/null +++ b/oauth/facebook-sdk-v5/Helpers/FacebookRedirectLoginHelper.php @@ -0,0 +1,360 @@ +oAuth2Client = $oAuth2Client; + $this->persistentDataHandler = $persistentDataHandler ?: new FacebookSessionPersistentDataHandler(); + $this->urlDetectionHandler = $urlHandler ?: new FacebookUrlDetectionHandler(); + $this->pseudoRandomStringGenerator = $prsg ?: $this->detectPseudoRandomStringGenerator(); + } + + /** + * Returns the persistent data handler. + * + * @return PersistentDataInterface + */ + public function getPersistentDataHandler() + { + return $this->persistentDataHandler; + } + + /** + * Returns the URL detection handler. + * + * @return UrlDetectionInterface + */ + public function getUrlDetectionHandler() + { + return $this->urlDetectionHandler; + } + + /** + * Returns the cryptographically secure pseudo-random string generator. + * + * @return PseudoRandomStringGeneratorInterface + */ + public function getPseudoRandomStringGenerator() + { + return $this->pseudoRandomStringGenerator; + } + + /** + * Detects which pseudo-random string generator to use. + * + * @return PseudoRandomStringGeneratorInterface + * + * @throws FacebookSDKException + */ + public function detectPseudoRandomStringGenerator() + { + // Since openssl_random_pseudo_bytes() can sometimes return non-cryptographically + // secure pseudo-random strings (in rare cases), we check for mcrypt_create_iv() first. + if (function_exists('mcrypt_create_iv')) { + return new McryptPseudoRandomStringGenerator(); + } + + if (function_exists('openssl_random_pseudo_bytes')) { + return new OpenSslPseudoRandomStringGenerator(); + } + + if (!ini_get('open_basedir') && is_readable('/dev/urandom')) { + return new UrandomPseudoRandomStringGenerator(); + } + + throw new FacebookSDKException('Unable to detect a cryptographically secure pseudo-random string generator.'); + } + + /** + * Stores CSRF state and returns a URL to which the user should be sent to in order to continue the login process with Facebook. + * + * @param string $redirectUrl The URL Facebook should redirect users to after login. + * @param array $scope List of permissions to request during login. + * @param array $params An array of parameters to generate URL. + * @param string $separator The separator to use in http_build_query(). + * + * @return string + */ + private function makeUrl($redirectUrl, array $scope, array $params = [], $separator = '&') + { + $state = $this->pseudoRandomStringGenerator->getPseudoRandomString(static::CSRF_LENGTH); + $this->persistentDataHandler->set('state', $state); + + return $this->oAuth2Client->getAuthorizationUrl($redirectUrl, $state, $scope, $params, $separator); + } + + /** + * Returns the URL to send the user in order to login to Facebook. + * + * @param string $redirectUrl The URL Facebook should redirect users to after login. + * @param array $scope List of permissions to request during login. + * @param string $separator The separator to use in http_build_query(). + * + * @return string + */ + public function getLoginUrl($redirectUrl, array $scope = [], $separator = '&') + { + return $this->makeUrl($redirectUrl, $scope, [], $separator); + } + + /** + * Returns the URL to send the user in order to log out of Facebook. + * + * @param AccessToken|string $accessToken The access token that will be logged out. + * @param string $next The url Facebook should redirect the user to after a successful logout. + * @param string $separator The separator to use in http_build_query(). + * + * @return string + * + * @throws FacebookSDKException + */ + public function getLogoutUrl($accessToken, $next, $separator = '&') + { + if (!$accessToken instanceof AccessToken) { + $accessToken = new AccessToken($accessToken); + } + + if ($accessToken->isAppAccessToken()) { + throw new FacebookSDKException('Cannot generate a logout URL with an app access token.', 722); + } + + $params = [ + 'next' => $next, + 'access_token' => $accessToken->getValue(), + ]; + + return 'https://www.facebook.com/logout.php?' . http_build_query($params, null, $separator); + } + + /** + * Returns the URL to send the user in order to login to Facebook with permission(s) to be re-asked. + * + * @param string $redirectUrl The URL Facebook should redirect users to after login. + * @param array $scope List of permissions to request during login. + * @param string $separator The separator to use in http_build_query(). + * + * @return string + */ + public function getReRequestUrl($redirectUrl, array $scope = [], $separator = '&') + { + $params = ['auth_type' => 'rerequest']; + + return $this->makeUrl($redirectUrl, $scope, $params, $separator); + } + + /** + * Returns the URL to send the user in order to login to Facebook with user to be re-authenticated. + * + * @param string $redirectUrl The URL Facebook should redirect users to after login. + * @param array $scope List of permissions to request during login. + * @param string $separator The separator to use in http_build_query(). + * + * @return string + */ + public function getReAuthenticationUrl($redirectUrl, array $scope = [], $separator = '&') + { + $params = ['auth_type' => 'reauthenticate']; + + return $this->makeUrl($redirectUrl, $scope, $params, $separator); + } + + /** + * Takes a valid code from a login redirect, and returns an AccessToken entity. + * + * @param string|null $redirectUrl The redirect URL. + * + * @return AccessToken|null + * + * @throws FacebookSDKException + */ + public function getAccessToken($redirectUrl = null) + { + if (!$code = $this->getCode()) { + return null; + } + + $this->validateCsrf(); + + $redirectUrl = $redirectUrl ?: $this->urlDetectionHandler->getCurrentUrl(); + // At minimum we need to remove the state param + $redirectUrl = FacebookUrlManipulator::removeParamsFromUrl($redirectUrl, ['state']); + + return $this->oAuth2Client->getAccessTokenFromCode($code, $redirectUrl); + } + + /** + * Validate the request against a cross-site request forgery. + * + * @throws FacebookSDKException + */ + protected function validateCsrf() + { + $state = $this->getState(); + $savedState = $this->persistentDataHandler->get('state'); + + if (!$state || !$savedState) { + throw new FacebookSDKException('Cross-site request forgery validation failed. Required param "state" missing.'); + } + + $savedLen = strlen($savedState); + $givenLen = strlen($state); + + if ($savedLen !== $givenLen) { + throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.'); + } + + $result = 0; + for ($i = 0; $i < $savedLen; $i++) { + $result |= ord($state[$i]) ^ ord($savedState[$i]); + } + + if ($result !== 0) { + throw new FacebookSDKException('Cross-site request forgery validation failed. The "state" param from the URL and session do not match.'); + } + } + + /** + * Return the code. + * + * @return string|null + */ + protected function getCode() + { + return $this->getInput('code'); + } + + /** + * Return the state. + * + * @return string|null + */ + protected function getState() + { + return $this->getInput('state'); + } + + /** + * Return the error code. + * + * @return string|null + */ + public function getErrorCode() + { + return $this->getInput('error_code'); + } + + /** + * Returns the error. + * + * @return string|null + */ + public function getError() + { + return $this->getInput('error'); + } + + /** + * Returns the error reason. + * + * @return string|null + */ + public function getErrorReason() + { + return $this->getInput('error_reason'); + } + + /** + * Returns the error description. + * + * @return string|null + */ + public function getErrorDescription() + { + return $this->getInput('error_description'); + } + + /** + * Returns a value from a GET param. + * + * @param string $key + * + * @return string|null + */ + private function getInput($key) + { + return isset($_GET[$key]) ? $_GET[$key] : null; + } +} diff --git a/oauth/facebook-sdk-v5/Helpers/FacebookSignedRequestFromInputHelper.php b/oauth/facebook-sdk-v5/Helpers/FacebookSignedRequestFromInputHelper.php new file mode 100644 index 0000000..aafa246 --- /dev/null +++ b/oauth/facebook-sdk-v5/Helpers/FacebookSignedRequestFromInputHelper.php @@ -0,0 +1,166 @@ +app = $app; + $graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION; + $this->oAuth2Client = new OAuth2Client($this->app, $client, $graphVersion); + + $this->instantiateSignedRequest(); + } + + /** + * Instantiates a new SignedRequest entity. + * + * @param string|null + */ + public function instantiateSignedRequest($rawSignedRequest = null) + { + $rawSignedRequest = $rawSignedRequest ?: $this->getRawSignedRequest(); + + if (!$rawSignedRequest) { + return; + } + + $this->signedRequest = new SignedRequest($this->app, $rawSignedRequest); + } + + /** + * Returns an AccessToken entity from the signed request. + * + * @return AccessToken|null + * + * @throws \Facebook\Exceptions\FacebookSDKException + */ + public function getAccessToken() + { + if ($this->signedRequest && $this->signedRequest->hasOAuthData()) { + $code = $this->signedRequest->get('code'); + $accessToken = $this->signedRequest->get('oauth_token'); + + if ($code && !$accessToken) { + return $this->oAuth2Client->getAccessTokenFromCode($code); + } + + $expiresAt = $this->signedRequest->get('expires', 0); + + return new AccessToken($accessToken, $expiresAt); + } + + return null; + } + + /** + * Returns the SignedRequest entity. + * + * @return SignedRequest|null + */ + public function getSignedRequest() + { + return $this->signedRequest; + } + + /** + * Returns the user_id if available. + * + * @return string|null + */ + public function getUserId() + { + return $this->signedRequest ? $this->signedRequest->getUserId() : null; + } + + /** + * Get raw signed request from input. + * + * @return string|null + */ + abstract public function getRawSignedRequest(); + + /** + * Get raw signed request from POST input. + * + * @return string|null + */ + public function getRawSignedRequestFromPost() + { + if (isset($_POST['signed_request'])) { + return $_POST['signed_request']; + } + + return null; + } + + /** + * Get raw signed request from cookie set from the Javascript SDK. + * + * @return string|null + */ + public function getRawSignedRequestFromCookie() + { + if (isset($_COOKIE['fbsr_' . $this->app->getId()])) { + return $_COOKIE['fbsr_' . $this->app->getId()]; + } + + return null; + } +} diff --git a/oauth/facebook-sdk-v5/Http/GraphRawResponse.php b/oauth/facebook-sdk-v5/Http/GraphRawResponse.php new file mode 100644 index 0000000..583d303 --- /dev/null +++ b/oauth/facebook-sdk-v5/Http/GraphRawResponse.php @@ -0,0 +1,137 @@ +httpResponseCode = (int)$httpStatusCode; + } + + if (is_array($headers)) { + $this->headers = $headers; + } else { + $this->setHeadersFromString($headers); + } + + $this->body = $body; + } + + /** + * Return the response headers. + * + * @return array + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Return the body of the response. + * + * @return string + */ + public function getBody() + { + return $this->body; + } + + /** + * Return the HTTP response code. + * + * @return int + */ + public function getHttpResponseCode() + { + return $this->httpResponseCode; + } + + /** + * Sets the HTTP response code from a raw header. + * + * @param string $rawResponseHeader + */ + public function setHttpResponseCodeFromHeader($rawResponseHeader) + { + preg_match('|HTTP/\d\.\d\s+(\d+)\s+.*|', $rawResponseHeader, $match); + $this->httpResponseCode = (int)$match[1]; + } + + /** + * Parse the raw headers and set as an array. + * + * @param string $rawHeaders The raw headers from the response. + */ + protected function setHeadersFromString($rawHeaders) + { + // Normalize line breaks + $rawHeaders = str_replace("\r\n", "\n", $rawHeaders); + + // There will be multiple headers if a 301 was followed + // or a proxy was followed, etc + $headerCollection = explode("\n\n", trim($rawHeaders)); + // We just want the last response (at the end) + $rawHeader = array_pop($headerCollection); + + $headerComponents = explode("\n", $rawHeader); + foreach ($headerComponents as $line) { + if (strpos($line, ': ') === false) { + $this->setHttpResponseCodeFromHeader($line); + } else { + list($key, $value) = explode(': ', $line); + $this->headers[$key] = $value; + } + } + } +} diff --git a/oauth/facebook-sdk-v5/Http/RequestBodyInterface.php b/oauth/facebook-sdk-v5/Http/RequestBodyInterface.php new file mode 100644 index 0000000..97e0a2e --- /dev/null +++ b/oauth/facebook-sdk-v5/Http/RequestBodyInterface.php @@ -0,0 +1,39 @@ +params = $params; + $this->files = $files; + $this->boundary = $boundary ?: uniqid(); + } + + /** + * @inheritdoc + */ + public function getBody() + { + $body = ''; + + // Compile normal params + $params = $this->getNestedParams($this->params); + foreach ($params as $k => $v) { + $body .= $this->getParamString($k, $v); + } + + // Compile files + foreach ($this->files as $k => $v) { + $body .= $this->getFileString($k, $v); + } + + // Peace out + $body .= "--{$this->boundary}--\r\n"; + + return $body; + } + + /** + * Get the boundary + * + * @return string + */ + public function getBoundary() + { + return $this->boundary; + } + + /** + * Get the string needed to transfer a file. + * + * @param string $name + * @param FacebookFile $file + * + * @return string + */ + private function getFileString($name, FacebookFile $file) + { + return sprintf( + "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"%s\r\n\r\n%s\r\n", + $this->boundary, + $name, + $file->getFileName(), + $this->getFileHeaders($file), + $file->getContents() + ); + } + + /** + * Get the string needed to transfer a POST field. + * + * @param string $name + * @param string $value + * + * @return string + */ + private function getParamString($name, $value) + { + return sprintf( + "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n", + $this->boundary, + $name, + $value + ); + } + + /** + * Returns the params as an array of nested params. + * + * @param array $params + * + * @return array + */ + private function getNestedParams(array $params) + { + $query = http_build_query($params, null, '&'); + $params = explode('&', $query); + $result = []; + + foreach ($params as $param) { + list($key, $value) = explode('=', $param, 2); + $result[urldecode($key)] = urldecode($value); + } + + return $result; + } + + /** + * Get the headers needed before transferring the content of a POST file. + * + * @param FacebookFile $file + * + * @return string + */ + protected function getFileHeaders(FacebookFile $file) + { + return "\r\nContent-Type: {$file->getMimetype()}"; + } +} diff --git a/oauth/facebook-sdk-v5/Http/RequestBodyUrlEncoded.php b/oauth/facebook-sdk-v5/Http/RequestBodyUrlEncoded.php new file mode 100644 index 0000000..77c2b64 --- /dev/null +++ b/oauth/facebook-sdk-v5/Http/RequestBodyUrlEncoded.php @@ -0,0 +1,55 @@ +params = $params; + } + + /** + * @inheritdoc + */ + public function getBody() + { + return http_build_query($this->params, null, '&'); + } +} diff --git a/oauth/facebook-sdk-v5/HttpClients/FacebookCurl.php b/oauth/facebook-sdk-v5/HttpClients/FacebookCurl.php new file mode 100644 index 0000000..e5d124a --- /dev/null +++ b/oauth/facebook-sdk-v5/HttpClients/FacebookCurl.php @@ -0,0 +1,129 @@ +curl = curl_init(); + } + + /** + * Set a curl option + * + * @param $key + * @param $value + */ + public function setopt($key, $value) + { + curl_setopt($this->curl, $key, $value); + } + + /** + * Set an array of options to a curl resource + * + * @param array $options + */ + public function setoptArray(array $options) + { + curl_setopt_array($this->curl, $options); + } + + /** + * Send a curl request + * + * @return mixed + */ + public function exec() + { + return curl_exec($this->curl); + } + + /** + * Return the curl error number + * + * @return int + */ + public function errno() + { + return curl_errno($this->curl); + } + + /** + * Return the curl error message + * + * @return string + */ + public function error() + { + return curl_error($this->curl); + } + + /** + * Get info from a curl reference + * + * @param $type + * + * @return mixed + */ + public function getinfo($type) + { + return curl_getinfo($this->curl, $type); + } + + /** + * Get the currently installed curl version + * + * @return array + */ + public function version() + { + return curl_version(); + } + + /** + * Close the resource connection to curl + */ + public function close() + { + curl_close($this->curl); + } +} diff --git a/oauth/facebook-sdk-v5/HttpClients/FacebookCurlHttpClient.php b/oauth/facebook-sdk-v5/HttpClients/FacebookCurlHttpClient.php new file mode 100644 index 0000000..955ac06 --- /dev/null +++ b/oauth/facebook-sdk-v5/HttpClients/FacebookCurlHttpClient.php @@ -0,0 +1,210 @@ +facebookCurl = $facebookCurl ?: new FacebookCurl(); + } + + /** + * @inheritdoc + */ + public function send($url, $method, $body, array $headers, $timeOut) + { + $this->openConnection($url, $method, $body, $headers, $timeOut); + $this->sendRequest(); + + if ($curlErrorCode = $this->facebookCurl->errno()) { + throw new FacebookSDKException($this->facebookCurl->error(), $curlErrorCode); + } + + // Separate the raw headers from the raw body + list($rawHeaders, $rawBody) = $this->extractResponseHeadersAndBody(); + + $this->closeConnection(); + + return new GraphRawResponse($rawHeaders, $rawBody); + } + + /** + * Opens a new curl connection. + * + * @param string $url The endpoint to send the request to. + * @param string $method The request method. + * @param string $body The body of the request. + * @param array $headers The request headers. + * @param int $timeOut The timeout in seconds for the request. + */ + public function openConnection($url, $method, $body, array $headers, $timeOut) + { + $options = [ + CURLOPT_CUSTOMREQUEST => $method, + CURLOPT_HTTPHEADER => $this->compileRequestHeaders($headers), + CURLOPT_URL => $url, + CURLOPT_CONNECTTIMEOUT => 10, + CURLOPT_TIMEOUT => $timeOut, + CURLOPT_RETURNTRANSFER => true, // Follow 301 redirects + CURLOPT_HEADER => true, // Enable header processing + CURLOPT_SSL_VERIFYHOST => 2, + CURLOPT_SSL_VERIFYPEER => true, + CURLOPT_CAINFO => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem', + ]; + + if ($method !== "GET") { + $options[CURLOPT_POSTFIELDS] = $body; + } + + $this->facebookCurl->init(); + $this->facebookCurl->setoptArray($options); + } + + /** + * Closes an existing curl connection + */ + public function closeConnection() + { + $this->facebookCurl->close(); + } + + /** + * Send the request and get the raw response from curl + */ + public function sendRequest() + { + $this->rawResponse = $this->facebookCurl->exec(); + } + + /** + * Compiles the request headers into a curl-friendly format. + * + * @param array $headers The request headers. + * + * @return array + */ + public function compileRequestHeaders(array $headers) + { + $return = []; + + foreach ($headers as $key => $value) { + $return[] = $key . ': ' . $value; + } + + return $return; + } + + /** + * Extracts the headers and the body into a two-part array + * + * @return array + */ + public function extractResponseHeadersAndBody() + { + $headerSize = $this->getHeaderSize(); + + $rawHeaders = mb_substr($this->rawResponse, 0, $headerSize); + $rawBody = mb_substr($this->rawResponse, $headerSize); + + return [trim($rawHeaders), trim($rawBody)]; + } + + /** + * Return proper header size + * + * @return integer + */ + private function getHeaderSize() + { + $headerSize = $this->facebookCurl->getinfo(CURLINFO_HEADER_SIZE); + // This corrects a Curl bug where header size does not account + // for additional Proxy headers. + if ($this->needsCurlProxyFix()) { + // Additional way to calculate the request body size. + if (preg_match('/Content-Length: (\d+)/', $this->rawResponse, $m)) { + $headerSize = mb_strlen($this->rawResponse) - $m[1]; + } elseif (stripos($this->rawResponse, self::CONNECTION_ESTABLISHED) !== false) { + $headerSize += mb_strlen(self::CONNECTION_ESTABLISHED); + } + } + + return $headerSize; + } + + /** + * Detect versions of Curl which report incorrect header lengths when + * using Proxies. + * + * @return boolean + */ + private function needsCurlProxyFix() + { + $ver = $this->facebookCurl->version(); + $version = $ver['version_number']; + + return $version < self::CURL_PROXY_QUIRK_VER; + } +} diff --git a/oauth/facebook-sdk-v5/HttpClients/FacebookGuzzleHttpClient.php b/oauth/facebook-sdk-v5/HttpClients/FacebookGuzzleHttpClient.php new file mode 100644 index 0000000..6f2a1c6 --- /dev/null +++ b/oauth/facebook-sdk-v5/HttpClients/FacebookGuzzleHttpClient.php @@ -0,0 +1,97 @@ +guzzleClient = $guzzleClient ?: new Client(); + } + + /** + * @inheritdoc + */ + public function send($url, $method, $body, array $headers, $timeOut) + { + $options = [ + 'headers' => $headers, + 'body' => $body, + 'timeout' => $timeOut, + 'connect_timeout' => 10, + 'verify' => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem', + ]; + $request = $this->guzzleClient->createRequest($method, $url, $options); + + try { + $rawResponse = $this->guzzleClient->send($request); + } catch (RequestException $e) { + $rawResponse = $e->getResponse(); + + if ($e->getPrevious() instanceof RingException || !$rawResponse instanceof ResponseInterface) { + throw new FacebookSDKException($e->getMessage(), $e->getCode()); + } + } + + $rawHeaders = $this->getHeadersAsString($rawResponse); + $rawBody = $rawResponse->getBody(); + $httpStatusCode = $rawResponse->getStatusCode(); + + return new GraphRawResponse($rawHeaders, $rawBody, $httpStatusCode); + } + + /** + * Returns the Guzzle array of headers as a string. + * + * @param ResponseInterface $response The Guzzle response. + * + * @return string + */ + public function getHeadersAsString(ResponseInterface $response) + { + $headers = $response->getHeaders(); + $rawHeaders = []; + foreach ($headers as $name => $values) { + $rawHeaders[] = $name . ": " . implode(", ", $values); + } + + return implode("\r\n", $rawHeaders); + } +} diff --git a/oauth/facebook-sdk-v5/HttpClients/FacebookHttpClientInterface.php b/oauth/facebook-sdk-v5/HttpClients/FacebookHttpClientInterface.php new file mode 100644 index 0000000..0029bc0 --- /dev/null +++ b/oauth/facebook-sdk-v5/HttpClients/FacebookHttpClientInterface.php @@ -0,0 +1,47 @@ +stream = stream_context_create($options); + } + + /** + * The response headers from the stream wrapper + * + * @return array|null + */ + public function getResponseHeaders() + { + return $this->responseHeaders; + } + + /** + * Send a stream wrapped request + * + * @param string $url + * + * @return mixed + */ + public function fileGetContents($url) + { + $rawResponse = file_get_contents($url, false, $this->stream); + $this->responseHeaders = $http_response_header; + + return $rawResponse; + } +} diff --git a/oauth/facebook-sdk-v5/HttpClients/FacebookStreamHttpClient.php b/oauth/facebook-sdk-v5/HttpClients/FacebookStreamHttpClient.php new file mode 100644 index 0000000..b157514 --- /dev/null +++ b/oauth/facebook-sdk-v5/HttpClients/FacebookStreamHttpClient.php @@ -0,0 +1,94 @@ +facebookStream = $facebookStream ?: new FacebookStream(); + } + + /** + * @inheritdoc + */ + public function send($url, $method, $body, array $headers, $timeOut) + { + $options = [ + 'http' => [ + 'method' => $method, + 'header' => $this->compileHeader($headers), + 'content' => $body, + 'timeout' => $timeOut, + 'ignore_errors' => true + ], + 'ssl' => [ + 'verify_peer' => true, + 'verify_peer_name' => true, + 'allow_self_signed' => true, // All root certificates are self-signed + 'cafile' => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem', + ], + ]; + + $this->facebookStream->streamContextCreate($options); + $rawBody = $this->facebookStream->fileGetContents($url); + $rawHeaders = $this->facebookStream->getResponseHeaders(); + + if ($rawBody === false || !$rawHeaders) { + throw new FacebookSDKException('Stream returned an empty response', 660); + } + + $rawHeaders = implode("\r\n", $rawHeaders); + + return new GraphRawResponse($rawHeaders, $rawBody); + } + + /** + * Formats the headers for use in the stream wrapper. + * + * @param array $headers The request headers. + * + * @return string + */ + public function compileHeader(array $headers) + { + $header = []; + foreach ($headers as $k => $v) { + $header[] = $k . ': ' . $v; + } + + return implode("\r\n", $header); + } +} diff --git a/oauth/facebook-sdk-v5/HttpClients/certs/DigiCertHighAssuranceEVRootCA.pem b/oauth/facebook-sdk-v5/HttpClients/certs/DigiCertHighAssuranceEVRootCA.pem new file mode 100644 index 0000000..9e6810a --- /dev/null +++ b/oauth/facebook-sdk-v5/HttpClients/certs/DigiCertHighAssuranceEVRootCA.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- diff --git a/oauth/facebook-sdk-v5/PersistentData/FacebookMemoryPersistentDataHandler.php b/oauth/facebook-sdk-v5/PersistentData/FacebookMemoryPersistentDataHandler.php new file mode 100644 index 0000000..93a6686 --- /dev/null +++ b/oauth/facebook-sdk-v5/PersistentData/FacebookMemoryPersistentDataHandler.php @@ -0,0 +1,53 @@ +sessionData[$key]) ? $this->sessionData[$key] : null; + } + + /** + * @inheritdoc + */ + public function set($key, $value) + { + $this->sessionData[$key] = $value; + } +} diff --git a/oauth/facebook-sdk-v5/PersistentData/FacebookSessionPersistentDataHandler.php b/oauth/facebook-sdk-v5/PersistentData/FacebookSessionPersistentDataHandler.php new file mode 100644 index 0000000..698bfd0 --- /dev/null +++ b/oauth/facebook-sdk-v5/PersistentData/FacebookSessionPersistentDataHandler.php @@ -0,0 +1,76 @@ +sessionPrefix . $key])) { + return $_SESSION[$this->sessionPrefix . $key]; + } + + return null; + } + + /** + * @inheritdoc + */ + public function set($key, $value) + { + $_SESSION[$this->sessionPrefix . $key] = $value; + } +} diff --git a/oauth/facebook-sdk-v5/PersistentData/PersistentDataInterface.php b/oauth/facebook-sdk-v5/PersistentData/PersistentDataInterface.php new file mode 100644 index 0000000..bd7e072 --- /dev/null +++ b/oauth/facebook-sdk-v5/PersistentData/PersistentDataInterface.php @@ -0,0 +1,49 @@ +validateLength($length); + + $binaryString = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); + + if ($binaryString === false) { + throw new FacebookSDKException( + static::ERROR_MESSAGE . + 'mcrypt_create_iv() returned an error.' + ); + } + + return $this->binToHex($binaryString, $length); + } +} diff --git a/oauth/facebook-sdk-v5/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php b/oauth/facebook-sdk-v5/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php new file mode 100644 index 0000000..f4ea6b8 --- /dev/null +++ b/oauth/facebook-sdk-v5/PseudoRandomString/OpenSslPseudoRandomStringGenerator.php @@ -0,0 +1,67 @@ +validateLength($length); + + $wasCryptographicallyStrong = false; + $binaryString = openssl_random_pseudo_bytes($length, $wasCryptographicallyStrong); + + if ($binaryString === false) { + throw new FacebookSDKException(static::ERROR_MESSAGE . 'openssl_random_pseudo_bytes() returned an unknown error.'); + } + + if ($wasCryptographicallyStrong !== true) { + throw new FacebookSDKException(static::ERROR_MESSAGE . 'openssl_random_pseudo_bytes() returned a pseudo-random string but it was not cryptographically secure and cannot be used.'); + } + + return $this->binToHex($binaryString, $length); + } +} diff --git a/oauth/facebook-sdk-v5/PseudoRandomString/PseudoRandomStringGeneratorInterface.php b/oauth/facebook-sdk-v5/PseudoRandomString/PseudoRandomStringGeneratorInterface.php new file mode 100644 index 0000000..970330c --- /dev/null +++ b/oauth/facebook-sdk-v5/PseudoRandomString/PseudoRandomStringGeneratorInterface.php @@ -0,0 +1,45 @@ +validateLength($length); + + $stream = fopen('/dev/urandom', 'rb'); + if (!is_resource($stream)) { + throw new FacebookSDKException( + static::ERROR_MESSAGE . + 'Unable to open stream to /dev/urandom.' + ); + } + + if (!defined('HHVM_VERSION')) { + stream_set_read_buffer($stream, 0); + } + + $binaryString = fread($stream, $length); + fclose($stream); + + if (!$binaryString) { + throw new FacebookSDKException( + static::ERROR_MESSAGE . + 'Stream to /dev/urandom returned no data.' + ); + } + + return $this->binToHex($binaryString, $length); + } +} diff --git a/oauth/facebook-sdk-v5/SignedRequest.php b/oauth/facebook-sdk-v5/SignedRequest.php new file mode 100644 index 0000000..77099a3 --- /dev/null +++ b/oauth/facebook-sdk-v5/SignedRequest.php @@ -0,0 +1,332 @@ +app = $facebookApp; + + if (!$rawSignedRequest) { + return; + } + + $this->rawSignedRequest = $rawSignedRequest; + + $this->parse(); + } + + /** + * Returns the raw signed request data. + * + * @return string|null + */ + public function getRawSignedRequest() + { + return $this->rawSignedRequest; + } + + /** + * Returns the parsed signed request data. + * + * @return array|null + */ + public function getPayload() + { + return $this->payload; + } + + /** + * Returns a property from the signed request data if available. + * + * @param string $key + * @param mixed|null $default + * + * @return mixed|null + */ + public function get($key, $default = null) + { + if (isset($this->payload[$key])) { + return $this->payload[$key]; + } + + return $default; + } + + /** + * Returns user_id from signed request data if available. + * + * @return string|null + */ + public function getUserId() + { + return $this->get('user_id'); + } + + /** + * Checks for OAuth data in the payload. + * + * @return boolean + */ + public function hasOAuthData() + { + return $this->get('oauth_token') || $this->get('code'); + } + + /** + * Creates a signed request from an array of data. + * + * @param array $payload + * + * @return string + */ + public function make(array $payload) + { + $payload['algorithm'] = isset($payload['algorithm']) ? $payload['algorithm'] : 'HMAC-SHA256'; + $payload['issued_at'] = isset($payload['issued_at']) ? $payload['issued_at'] : time(); + $encodedPayload = $this->base64UrlEncode(json_encode($payload)); + + $hashedSig = $this->hashSignature($encodedPayload); + $encodedSig = $this->base64UrlEncode($hashedSig); + + return $encodedSig . '.' . $encodedPayload; + } + + /** + * Validates and decodes a signed request and saves + * the payload to an array. + */ + protected function parse() + { + list($encodedSig, $encodedPayload) = $this->split(); + + // Signature validation + $sig = $this->decodeSignature($encodedSig); + $hashedSig = $this->hashSignature($encodedPayload); + $this->validateSignature($hashedSig, $sig); + + $this->payload = $this->decodePayload($encodedPayload); + + // Payload validation + $this->validateAlgorithm(); + } + + /** + * Splits a raw signed request into signature and payload. + * + * @returns array + * + * @throws FacebookSDKException + */ + protected function split() + { + if (strpos($this->rawSignedRequest, '.') === false) { + throw new FacebookSDKException('Malformed signed request.', 606); + } + + return explode('.', $this->rawSignedRequest, 2); + } + + /** + * Decodes the raw signature from a signed request. + * + * @param string $encodedSig + * + * @returns string + * + * @throws FacebookSDKException + */ + protected function decodeSignature($encodedSig) + { + $sig = $this->base64UrlDecode($encodedSig); + + if (!$sig) { + throw new FacebookSDKException('Signed request has malformed encoded signature data.', 607); + } + + return $sig; + } + + /** + * Decodes the raw payload from a signed request. + * + * @param string $encodedPayload + * + * @returns array + * + * @throws FacebookSDKException + */ + protected function decodePayload($encodedPayload) + { + $payload = $this->base64UrlDecode($encodedPayload); + + if ($payload) { + $payload = json_decode($payload, true); + } + + if (!is_array($payload)) { + throw new FacebookSDKException('Signed request has malformed encoded payload data.', 607); + } + + return $payload; + } + + /** + * Validates the algorithm used in a signed request. + * + * @throws FacebookSDKException + */ + protected function validateAlgorithm() + { + if ($this->get('algorithm') !== 'HMAC-SHA256') { + throw new FacebookSDKException('Signed request is using the wrong algorithm.', 605); + } + } + + /** + * Hashes the signature used in a signed request. + * + * @param string $encodedData + * + * @return string + * + * @throws FacebookSDKException + */ + protected function hashSignature($encodedData) + { + $hashedSig = hash_hmac( + 'sha256', + $encodedData, + $this->app->getSecret(), + $raw_output = true + ); + + if (!$hashedSig) { + throw new FacebookSDKException('Unable to hash signature from encoded payload data.', 602); + } + + return $hashedSig; + } + + /** + * Validates the signature used in a signed request. + * + * @param string $hashedSig + * @param string $sig + * + * @throws FacebookSDKException + */ + protected function validateSignature($hashedSig, $sig) + { + if (mb_strlen($hashedSig) === mb_strlen($sig)) { + $validate = 0; + for ($i = 0; $i < mb_strlen($sig); $i++) { + $validate |= ord($hashedSig[$i]) ^ ord($sig[$i]); + } + if ($validate === 0) { + return; + } + } + + throw new FacebookSDKException('Signed request has an invalid signature.', 602); + } + + /** + * Base64 decoding which replaces characters: + * + instead of - + * / instead of _ + * + * @link http://en.wikipedia.org/wiki/Base64#URL_applications + * + * @param string $input base64 url encoded input + * + * @return string decoded string + */ + public function base64UrlDecode($input) + { + $urlDecodedBase64 = strtr($input, '-_', '+/'); + $this->validateBase64($urlDecodedBase64); + + return base64_decode($urlDecodedBase64); + } + + /** + * Base64 encoding which replaces characters: + * + instead of - + * / instead of _ + * + * @link http://en.wikipedia.org/wiki/Base64#URL_applications + * + * @param string $input string to encode + * + * @return string base64 url encoded input + */ + public function base64UrlEncode($input) + { + return strtr(base64_encode($input), '+/', '-_'); + } + + /** + * Validates a base64 string. + * + * @param string $input base64 value to validate + * + * @throws FacebookSDKException + */ + protected function validateBase64($input) + { + if (!preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $input)) { + throw new FacebookSDKException('Signed request contains malformed base64 encoding.', 608); + } + } +} diff --git a/oauth/facebook-sdk-v5/Url/FacebookUrlDetectionHandler.php b/oauth/facebook-sdk-v5/Url/FacebookUrlDetectionHandler.php new file mode 100644 index 0000000..5fbb9ce --- /dev/null +++ b/oauth/facebook-sdk-v5/Url/FacebookUrlDetectionHandler.php @@ -0,0 +1,163 @@ +getHttpScheme() . '://' . $this->getHostName() . $this->getServerVar('REQUEST_URI'); + } + + /** + * Get the currently active URL scheme. + * + * @return string + */ + protected function getHttpScheme() + { + return $this->isBehindSsl() ? 'https' : 'http'; + } + + /** + * Tries to detect if the server is running behind an SSL. + * + * @return boolean + */ + protected function isBehindSsl() + { + // Check for proxy first + $protocol = $this->getHeader('X_FORWARDED_PROTO'); + if ($protocol) { + return $this->protocolWithActiveSsl($protocol); + } + + $protocol = $this->getServerVar('HTTPS'); + if ($protocol) { + return $this->protocolWithActiveSsl($protocol); + } + + return (string)$this->getServerVar('SERVER_PORT') === '443'; + } + + /** + * Detects an active SSL protocol value. + * + * @param string $protocol + * + * @return boolean + */ + protected function protocolWithActiveSsl($protocol) + { + $protocol = strtolower((string)$protocol); + + return in_array($protocol, ['on', '1', 'https', 'ssl'], true); + } + + /** + * Tries to detect the host name of the server. + * + * Some elements adapted from + * + * @see https://github.com/symfony/HttpFoundation/blob/master/Request.php + * + * @return string + */ + protected function getHostName() + { + // Check for proxy first + if ($host = $this->getHeader('X_FORWARDED_HOST')) { + $elements = explode(',', $host); + $host = $elements[count($elements) - 1]; + } elseif (!$host = $this->getHeader('HOST')) { + if (!$host = $this->getServerVar('SERVER_NAME')) { + $host = $this->getServerVar('SERVER_ADDR'); + } + } + + // trim and remove port number from host + // host is lowercase as per RFC 952/2181 + $host = strtolower(preg_replace('/:\d+$/', '', trim($host))); + + // Port number + $scheme = $this->getHttpScheme(); + $port = $this->getCurrentPort(); + $appendPort = ':' . $port; + + // Don't append port number if a normal port. + if (($scheme == 'http' && $port == '80') || ($scheme == 'https' && $port == '443')) { + $appendPort = ''; + } + + return $host . $appendPort; + } + + protected function getCurrentPort() + { + // Check for proxy first + $port = $this->getHeader('X_FORWARDED_PORT'); + if ($port) { + return (string)$port; + } + + $protocol = (string)$this->getHeader('X_FORWARDED_PROTO'); + if ($protocol === 'https') { + return '443'; + } + + return (string)$this->getServerVar('SERVER_PORT'); + } + + /** + * Returns the a value from the $_SERVER super global. + * + * @param string $key + * + * @return string + */ + protected function getServerVar($key) + { + return isset($_SERVER[$key]) ? $_SERVER[$key] : ''; + } + + /** + * Gets a value from the HTTP request headers. + * + * @param string $key + * + * @return string + */ + protected function getHeader($key) + { + return $this->getServerVar('HTTP_' . $key); + } +} diff --git a/oauth/facebook-sdk-v5/Url/FacebookUrlManipulator.php b/oauth/facebook-sdk-v5/Url/FacebookUrlManipulator.php new file mode 100644 index 0000000..20a0299 --- /dev/null +++ b/oauth/facebook-sdk-v5/Url/FacebookUrlManipulator.php @@ -0,0 +1,167 @@ + 0) { + $query = '?' . http_build_query($params, null, '&'); + } + } + + $scheme = isset($parts['scheme']) ? $parts['scheme'] . '://' : ''; + $host = isset($parts['host']) ? $parts['host'] : ''; + $port = isset($parts['port']) ? ':' . $parts['port'] : ''; + $path = isset($parts['path']) ? $parts['path'] : ''; + $fragment = isset($parts['fragment']) ? '#' . $parts['fragment'] : ''; + + return $scheme . $host . $port . $path . $query . $fragment; + } + + /** + * Gracefully appends params to the URL. + * + * @param string $url The URL that will receive the params. + * @param array $newParams The params to append to the URL. + * + * @return string + */ + public static function appendParamsToUrl($url, array $newParams = []) + { + if (!$newParams) { + return $url; + } + + if (strpos($url, '?') === false) { + return $url . '?' . http_build_query($newParams, null, '&'); + } + + list($path, $query) = explode('?', $url, 2); + $existingParams = []; + parse_str($query, $existingParams); + + // Favor params from the original URL over $newParams + $newParams = array_merge($newParams, $existingParams); + + // Sort for a predicable order + ksort($newParams); + + return $path . '?' . http_build_query($newParams, null, '&'); + } + + /** + * Returns the params from a URL in the form of an array. + * + * @param string $url The URL to parse the params from. + * + * @return array + */ + public static function getParamsAsArray($url) + { + $query = parse_url($url, PHP_URL_QUERY); + if (!$query) { + return []; + } + $params = []; + parse_str($query, $params); + + return $params; + } + + /** + * Adds the params of the first URL to the second URL. + * + * Any params that already exist in the second URL will go untouched. + * + * @param string $urlToStealFrom The URL harvest the params from. + * @param string $urlToAddTo The URL that will receive the new params. + * + * @return string The $urlToAddTo with any new params from $urlToStealFrom. + */ + public static function mergeUrlParams($urlToStealFrom, $urlToAddTo) + { + $newParams = static::getParamsAsArray($urlToStealFrom); + // Nothing new to add, return as-is + if (!$newParams) { + return $urlToAddTo; + } + + return static::appendParamsToUrl($urlToAddTo, $newParams); + } + + /** + * Check for a "/" prefix and prepend it if not exists. + * + * @param string|null $string + * + * @return string|null + */ + public static function forceSlashPrefix($string) + { + if (!$string) { + return $string; + } + + return strpos($string, '/') === 0 ? $string : '/' . $string; + } + + /** + * Trims off the hostname and Graph version from a URL. + * + * @param string $urlToTrim The URL the needs the surgery. + * + * @return string The $urlToTrim with the hostname and Graph version removed. + */ + public static function baseGraphUrlEndpoint($urlToTrim) + { + return '/' . preg_replace('/^https:\/\/.+\.facebook\.com(\/v.+?)?\//', '', $urlToTrim); + } +} diff --git a/oauth/facebook-sdk-v5/Url/UrlDetectionInterface.php b/oauth/facebook-sdk-v5/Url/UrlDetectionInterface.php new file mode 100644 index 0000000..764a606 --- /dev/null +++ b/oauth/facebook-sdk-v5/Url/UrlDetectionInterface.php @@ -0,0 +1,39 @@ +_id); + } + + protected function _init() + { + $this->setRenderPanel(false); + $this->setFormClass('form-horizontal dash-window-form'); + } + + protected function _render() + { + $html = $this->open(); + + $html .= $this->input(Locale::tm('Facebook App ID','oauth'), 'oauth_fb_app_id'); + $html .= $this->input(Locale::tm('Facebook App Secret','oauth'), 'oauth_fb_app_secret'); + $html .= $this->checkbox(Locale::tm('Enable Facebook authentication','oauth'), 'oauth_fb_on', null, false); + $html .= $this->input(Locale::tm('Facebook Page URL','oauth'), 'oauth_fb_page_url'); + + $html .= $this->input(Locale::tm('Vkontakte App ID','oauth'), 'oauth_vk_app_id'); + $html .= $this->input(Locale::tm('Vkontakte App Secret','oauth'), 'oauth_vk_app_secret'); + $html .= $this->checkbox(Locale::tm('Enable Vkontakte authentication','oauth'), 'oauth_vk_on', null, false); + $html .= $this->input(Locale::tm('Vkontakte Group ID','oauth'), 'oauth_vk_group_id'); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + + $validator->registerString('oauth_fb_app_id',null,255,false,Locale::t('Invalid value "%s"',Locale::tm('Facebook App ID','oauth'))); + $validator->registerNoTags('oauth_fb_app_id',Locale::t('Invalid value "%s"',Locale::tm('Facebook App ID','oauth'))); + $validator->registerString('oauth_fb_app_secret',null,255,false,Locale::t('Invalid value "%s"',Locale::tm('Facebook App Secret','oauth'))); + $validator->registerNoTags('oauth_fb_app_secret',Locale::t('Invalid value "%s"',Locale::tm('Facebook App Secret','oauth'))); + $validator->registerString('oauth_fb_page_url',null,255,false,Locale::t('Invalid value "%s"',Locale::tm('Facebook Page URL','oauth'))); + $validator->registerNoTags('oauth_fb_page_url',Locale::t('Invalid value "%s"',Locale::tm('Facebook Page URL','oauth'))); + + $validator->registerString('oauth_vk_app_id',null,255,false,Locale::t('Invalid value "%s"',Locale::tm('Vkontakte App ID','oauth'))); + $validator->registerNoTags('oauth_vk_app_id',Locale::t('Invalid value "%s"',Locale::tm('Vkontakte App ID','oauth'))); + $validator->registerString('oauth_vk_app_secret',null,255,false,Locale::t('Invalid value "%s"',Locale::tm('Vkontakte App Secret','oauth'))); + $validator->registerNoTags('oauth_vk_app_secret',Locale::t('Invalid value "%s"',Locale::tm('Vkontakte App Secret','oauth'))); + $validator->registerString('oauth_vk_group_id',null,255,false,Locale::t('Invalid value "%s"',Locale::tm('Vkontakte Group ID','oauth'))); + $validator->registerNoTags('oauth_vk_group_id',Locale::t('Invalid value "%s"',Locale::tm('Vkontakte Group ID','oauth'))); + + } +} \ No newline at end of file diff --git a/oauth/install/fbuser.php b/oauth/install/fbuser.php new file mode 100644 index 0000000..b8624e2 --- /dev/null +++ b/oauth/install/fbuser.php @@ -0,0 +1,48 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'user_id' => Field::int(true, true), + 'fb_id' => Field::string(true), + 'email' => Field::string(true), + 'profile_name' => Field::string(true), + 'date_created' => Field::datetime(true) + ); + } + + public function getKeys() { + return array( + + ); + } + + public function getUnique() { + return array( + 'fb_id' => array('fb_id') + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/oauth/install/vkuser.php b/oauth/install/vkuser.php new file mode 100644 index 0000000..68c581e --- /dev/null +++ b/oauth/install/vkuser.php @@ -0,0 +1,48 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'user_id' => Field::int(true, true), + 'vk_id' => Field::string(true), + 'email' => Field::string(true), + 'profile_name' => Field::string(true), + 'date_created' => Field::datetime(true) + ); + } + + public function getKeys() { + return array( + + ); + } + + public function getUnique() { + return array( + 'vk_id' => array('vk_id') + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/oauth/models/fbuser.php b/oauth/models/fbuser.php new file mode 100644 index 0000000..5a36d26 --- /dev/null +++ b/oauth/models/fbuser.php @@ -0,0 +1,35 @@ +where('email','=',$email) + ->get(0); + } + + public static function isUserActive($user, $trust_email) { + $_user = User::findAuthUser($user->email); + if (!$_user) return false; + if ($trust_email && $_user->verified != Zira\Models\User::STATUS_VERIFIED) { + User::getCollection() + ->update(array( + 'verified' => Zira\Models\User::STATUS_VERIFIED + )) + ->where('id','=',$user->id) + ->execute(); + } + Zira\User::setCurrent($_user); + return true; + } + + public static function registerUser($username, $email, $firstname, $secondname, $trust_email) { + $user = new Zira\Models\User(); + $user->firstname = $firstname; + $user->secondname = $secondname; + $user->email = $email; + $user->username = $username; + $password = Zira\User::generateUserToken(); + $user->password = Zira\User::getHashedUserToken($password); + $user->group_id = Zira\User::GROUP_USER; + $user->date_created = date('Y-m-d H:i:s'); + $user->date_logged = date('Y-m-d H:i:s'); + $user->verified = $trust_email ? Zira\Models\User::STATUS_VERIFIED : Zira\Models\User::STATUS_NOT_VERIFIED; + $user->active = Zira\Models\User::STATUS_ACTIVE; + $user->code = Zira\User::generateRememberCode($user->username, $user->email); + $user->save(); + + if ($trust_email) { + try { + self::sendInformEmail($email, $firstname . ' ' . $secondname, $password); + } catch(\Exception $e) { + // ignore + } + } + + Zira\User::setCurrent($user); + return $user; + } + + public static function sendInformEmail($email, $username, $password) { + $message = Zira\Locale::t('Hello %s !', '$user')."\r\n\r\n"; + $message .= Zira\Locale::t('We created an account for you on %s.','$site')."\r\n"; + $message .= Zira\Locale::t('Your new password: %s', '$password')."\r\n\r\n"; + $message .= Zira\Locale::t('You recieved this message, because you logged in to %s first time, using your social network account.','$site'); + + $message = str_replace('$user', $username, $message); + $message = str_replace('$password', $password, $message); + $message = str_replace('$site', Zira\Helper::url('/',true, true), $message); + + Zira\Mail::send($email, Zira\Locale::t('Your new account'), Zira\Helper::html($message)); + } +} \ No newline at end of file diff --git a/oauth/models/settings.php b/oauth/models/settings.php new file mode 100644 index 0000000..2eb02f2 --- /dev/null +++ b/oauth/models/settings.php @@ -0,0 +1,62 @@ + Zira\Locale::t('Permission denied')); + } + + $form = new \Oauth\Forms\Settings(); + if ($form->isValid()) { + $options = array( + 'oauth_fb_app_id'=>'string', + 'oauth_fb_app_secret'=>'string', + 'oauth_fb_on'=>'int', + 'oauth_fb_page_url'=>'string', + 'oauth_vk_app_id'=>'string', + 'oauth_vk_app_secret'=>'string', + 'oauth_vk_on'=>'int', + 'oauth_vk_group_id'=>'string' + ); + + $config_ids = array(); + $user_configs = Zira\Models\Option::getCollection()->get(); + foreach($user_configs as $user_config) { + $config_ids[$user_config->name] = $user_config->id; + } + + foreach($options as $option=>$type) { + if (!array_key_exists($option, $config_ids)) { + $optionObj = new Zira\Models\Option(); + } else { + $optionObj = new Zira\Models\Option($config_ids[$option]); + } + $optionObj->name = $option; + $value = $form->getValue($option); + + if ($type=='int') $value=intval($value); + + $optionObj->value = $value; + $optionObj->module = 'oauth'; + $optionObj->save(); + } + + Zira\Cache::clear(true); + + return array('message'=>Zira\Locale::t('Successfully saved')); + } else { + return array('error'=>$form->getError()); + } + } +} \ No newline at end of file diff --git a/oauth/models/vkuser.php b/oauth/models/vkuser.php new file mode 100644 index 0000000..edbef35 --- /dev/null +++ b/oauth/models/vkuser.php @@ -0,0 +1,35 @@ +isPanelEnabled() && Zira\Permission::check(Zira\Permission::TO_ACCESS_DASHBOARD) && Zira\Permission::check(Zira\Permission::TO_CHANGE_OPTIONS)) { + \Dash\Dash::getInstance()->addPanelModulesGroupItem('glyphicon glyphicon-log-in', Zira\Locale::tm('Social networks', 'oauth'), null, 'oauthSettingsWindow()'); + \Dash\Dash::getInstance()->registerModuleWindowClass('oauthSettingsWindow', 'Oauth\Windows\Settings', 'Oauth\Models\Settings'); + } + } + + public static function getFacebookJsSdkUrl() { + if (Zira\Locale::getLanguage()=='ru') + return Models\Oauth::FACEBOOK_JS_SDK_RU; + else + return Models\Oauth::FACEBOOK_JS_SDK; + } + + public static function getFacebookLoginBtn() { + //return Zira\Helper::tag('fb:login-button', null, array('scope'=>'public_profile,email','onlogin'=>'oauth_fb_login();')); + return Zira\Helper::tag('a', null, array('href'=>'javascript:void(0)','onclick'=>'oauth_fb_btn();','class'=>'oauth-btn social-btn fb','title'=>Zira\Locale::tm('Login with: %s', 'oauth', Zira\Locale::t('Facebook')))); + } + + public static function addFacebookJsSdk($app_id) { + if (self::$_facebook_js_sdk_added) return; + $js = Zira\Helper::tag_open('script', array('type'=>'text/javascript'))."\r\n"; + $js .='window.fbAsyncInit = function() {'."\r\n". + "\t".'FB.init({'."\r\n". + "\t\t".'appId : \''.Zira\Helper::html($app_id).'\','."\r\n". + "\t\t".'cookie : true, // enable cookies'."\r\n". + "\t\t".'xfbml : true, // parse social plugins on this page'."\r\n". + "\t\t".'version : \'v2.2\' // use version 2.2'."\r\n". + "\t".'});'."\r\n". + "\t".'if (typeof(oauth_fb_btn)!="undefined") oauth_fb_btn.activated = true;'."\r\n". + '};'."\r\n"; + $js .='(function(d, s, id) {'."\r\n". + "\t".'var js, fjs = d.getElementsByTagName(s)[0];'."\r\n". + "\t".'if (d.getElementById(id)) return;'."\r\n". + "\t".'js = d.createElement(s); js.id = id;'."\r\n". + "\t".'js.src = "'.self::getFacebookJsSdkUrl().'";'."\r\n". + "\t".'fjs.parentNode.insertBefore(js, fjs);'."\r\n". + '}(document, \'script\', \'facebook-jssdk\'));'."\r\n"; + $js .= Zira\Helper::tag_close('script')."\r\n"; + Zira\View::addHTML($js, Zira\View::VAR_BODY_BOTTOM); + self::$_facebook_js_sdk_added = true; + } + + public static function addFacebookJSView() { + if (self::$_facebook_js_view_added) return; + self::addFacebookJsSdk(Zira\Config::get('oauth_fb_app_id')); + Zira\View::addPlaceholderView(Zira\View::VAR_BODY_BOTTOM, array( + 'app_id' => Zira\Config::get('oauth_fb_app_id'), + 'app_secret' => Zira\Config::get('oauth_fb_app_secret') + ), 'oauth/fb-login'); + self::$_facebook_js_view_added = true; + } + + public static function fb_login_form_hook() { + self::addFacebookJSView(); + return self::getFacebookLoginBtn(); + } + + public static function includeFacebookSdk() { + require_once(ROOT_DIR . DIRECTORY_SEPARATOR . 'oauth' . DIRECTORY_SEPARATOR . Models\Oauth::FACEBOOK_SDK_FOLDER . DIRECTORY_SEPARATOR . 'autoload.php'); + } + + public static function getVkontakteAuthUrl() { + return Models\Oauth::VKONTAKTE_AUTH_URL . '?client_id='.Zira\Config::get('oauth_vk_app_id').'&redirect_uri='.Zira\Helper::url('oauth/login/vkresponse', true, true).'&display=popup&scope=email&response_type=code&v=5.50'; + } + + public static function getVkontakteAccessTokenUrl($code) { + return Models\Oauth::VKONTAKTE_ACCESS_TOKEN_URL . '?client_id='.Zira\Config::get('oauth_vk_app_id').'&client_secret='.Zira\Config::get('oauth_vk_app_secret').'&redirect_uri='.Zira\Helper::url('oauth/login/vkresponse', true, true).'&code='.$code; + } + + public static function getVkontakteUserApiUrl($access_token, $user_id) { + return Models\Oauth::VKONTAKTE_USER_API_URL . '?user_id='.$user_id.'&access_token='.$access_token.'&v=5.50'; + } + + public static function getVkontakteLoginBtn() { + return Zira\Helper::tag('a', null, array('href'=>'javascript:void(0)','onclick'=>'oauth_vk_login();','class'=>'oauth-btn social-btn vk','title'=>Zira\Locale::tm('Login with: %s', 'oauth', Zira\Locale::t('Vkontakte')))); + } + + public static function addVkontakteJSView() { + if (self::$_vkontakte_js_view_added) return; + Zira\View::addPlaceholderView(Zira\View::VAR_BODY_BOTTOM, array( + 'app_id' => Zira\Config::get('oauth_vk_app_id'), + 'app_secret' => Zira\Config::get('oauth_vk_app_secret') + ), 'oauth/vk-login'); + self::$_vkontakte_js_view_added = true; + } + + public static function addVkontakteOpenApi($app_id) { + if (self::$_vkontakte_js_open_api_added) return; + $js = Zira\Helper::tag('div', null, array('id'=>'vk_api_transport'))."\r\n"; + $js .= Zira\Helper::tag_open('script', array('type'=>'text/javascript'))."\r\n"; + $js .= 'if (typeof(vk_open_api_init_callbacks)=="undefined") vk_open_api_init_callbacks = [];'."\r\n"; + $js .= 'window.vkAsyncInit = function() {'."\r\n". + "\t".'VK.init({apiId: '.$app_id.', onlyWidgets: true});'."\r\n". + "\t".'for(var i=0; iname; + return $redirect_url ? $redirect_url : ''; + } + } +} \ No newline at end of file diff --git a/oauth/widgets/buttons.php b/oauth/widgets/buttons.php new file mode 100644 index 0000000..5069636 --- /dev/null +++ b/oauth/widgets/buttons.php @@ -0,0 +1,69 @@ +setEditable(true); + $this->setCaching(false); + $this->setPlaceholder(View::VAR_HEADER); + } + + protected function _render() { + if (Zira\User::isAuthorized()) return; + + $fb_on = false; + $vk_on = false; + + $fb_enabled = Zira\Config::get('oauth_fb_on'); + $fb_app_id = Zira\Config::get('oauth_fb_app_id'); + $fb_app_secret = Zira\Config::get('oauth_fb_app_secret'); + + if ($fb_enabled && $fb_app_id && $fb_app_secret) { + $fb_on = true; + } + + $vk_enabled = Zira\Config::get('oauth_vk_on'); + $vk_app_id = Zira\Config::get('oauth_vk_app_id'); + $vk_app_secret = Zira\Config::get('oauth_vk_app_secret'); + + if ($vk_enabled && $vk_app_id && $vk_app_secret) { + $vk_on = true; + } + + if ($fb_on || $vk_on) { + echo Zira\Helper::tag_open('div', array('class'=>'header-top-item header-top-buttons')); + echo Zira\Helper::tag('div', Zira\Locale::tm('Login with: %s', 'oauth', ''), array('class'=>'header-top-button-text')); + } + + if ($fb_on) { + Oauth\Oauth::addFacebookJSView(); + echo Zira\Helper::tag_open('div', array('class'=>'header-top-button')). + Oauth\Oauth::getFacebookLoginBtn(). + Zira\Helper::tag_close('div'); + } + + if ($vk_on) { + Oauth\Oauth::addVkontakteJSView(); + echo Zira\Helper::tag_open('div', array('class'=>'header-top-button')). + Oauth\Oauth::getVkontakteLoginBtn(). + Zira\Helper::tag_close('div'); + } + + if ($fb_on || $vk_on) { + echo Zira\Helper::tag_close('div'); + } + } +} \ No newline at end of file diff --git a/oauth/widgets/fbcomments.php b/oauth/widgets/fbcomments.php new file mode 100644 index 0000000..b5cf61c --- /dev/null +++ b/oauth/widgets/fbcomments.php @@ -0,0 +1,37 @@ +setEditable(true); + $this->setCaching(false); + $this->setPlaceholder(View::VAR_CONTENT_BOTTOM); + } + + protected function _render() { + $record_url = Zira\Page::getRecordUrl(); + if (!$record_url || $record_url==Zira\Config::get('home_record_name')) return; + + $fb_app_id = Zira\Config::get('oauth_fb_app_id'); + + if ($fb_app_id) { + Oauth\Oauth::addFacebookJsSdk($fb_app_id); + Zira\View::renderView(array( + 'page_url' => Zira\Helper::url($record_url, true, true) + ),'oauth/fb-comments'); + } + } +} \ No newline at end of file diff --git a/oauth/widgets/fbpage.php b/oauth/widgets/fbpage.php new file mode 100644 index 0000000..c840541 --- /dev/null +++ b/oauth/widgets/fbpage.php @@ -0,0 +1,35 @@ +setEditable(true); + $this->setCaching(false); + $this->setPlaceholder(View::VAR_SIDEBAR_RIGHT); + } + + protected function _render() { + $fb_app_id = Zira\Config::get('oauth_fb_app_id'); + $fb_page_url = Zira\Config::get('oauth_fb_page_url'); + + if ($fb_app_id && $fb_page_url) { + Oauth\Oauth::addFacebookJsSdk($fb_app_id); + Zira\View::renderView(array( + 'page_url' => $fb_page_url + ),'oauth/fb-page'); + } + } +} \ No newline at end of file diff --git a/oauth/widgets/vkcomments.php b/oauth/widgets/vkcomments.php new file mode 100644 index 0000000..382ffa4 --- /dev/null +++ b/oauth/widgets/vkcomments.php @@ -0,0 +1,35 @@ +setEditable(true); + $this->setCaching(false); + $this->setPlaceholder(View::VAR_CONTENT_BOTTOM); + } + + protected function _render() { + $record_url = Zira\Page::getRecordUrl(); + if (!$record_url || $record_url==Zira\Config::get('home_record_name')) return; + + $vk_app_id = Zira\Config::get('oauth_vk_app_id'); + + if ($vk_app_id) { + Oauth\Oauth::addVkontakteOpenApi($vk_app_id); + Zira\View::renderView(array(),'oauth/vk-comments'); + } + } +} \ No newline at end of file diff --git a/oauth/widgets/vkgroup.php b/oauth/widgets/vkgroup.php new file mode 100644 index 0000000..5ee528f --- /dev/null +++ b/oauth/widgets/vkgroup.php @@ -0,0 +1,35 @@ +setEditable(true); + $this->setCaching(false); + $this->setPlaceholder(View::VAR_SIDEBAR_RIGHT); + } + + protected function _render() { + $vk_app_id = Zira\Config::get('oauth_vk_app_id'); + $vk_group_id = Zira\Config::get('oauth_vk_group_id'); + + if ($vk_app_id && $vk_group_id) { + Oauth\Oauth::addVkontakteOpenApi($vk_app_id); + Zira\View::renderView(array( + 'group_id' => $vk_group_id + ),'oauth/vk-group'); + } + } +} \ No newline at end of file diff --git a/oauth/windows/settings.php b/oauth/windows/settings.php new file mode 100644 index 0000000..915d814 --- /dev/null +++ b/oauth/windows/settings.php @@ -0,0 +1,48 @@ +setIconClass(self::$_icon_class); + $this->setTitle(Zira\Locale::t(self::$_title)); + $this->setSidebarEnabled(false); + + $this->setSaveActionEnabled(true); + } + + public function create() { + $this->setOnLoadJSCallback( + $this->createJSCallback( + 'desk_window_form_init(this);' + ) + ); + } + + public function load() { + if (!Permission::check(Permission::TO_CHANGE_OPTIONS)) { + return array('error' => Zira\Locale::t('Permission denied')); + } + + $configs = Zira\Config::getArray(); + + $form = new \Oauth\Forms\Settings(); + $form->setValues($configs); + + $this->setBodyContent($form); + } +} \ No newline at end of file diff --git a/robots.src.txt b/robots.src.txt new file mode 100644 index 0000000..4cf7983 --- /dev/null +++ b/robots.src.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +#Sitemap: http://domain.com/sitemap.xml \ No newline at end of file diff --git a/themes/bulaksu/assets/css/editor.css b/themes/bulaksu/assets/css/editor.css new file mode 100644 index 0000000..997f43b --- /dev/null +++ b/themes/bulaksu/assets/css/editor.css @@ -0,0 +1,72 @@ +body { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 16px; +} +h1 { + font-size: 30px; +} +h2 { + font-size: 26px; +} +h3 { + font-size: 22px; +} +h4 { + font-size: 18px; +} +h5 { + font-size: 14px; +} +h6 { + font-size: 10px; +} +p { + margin: 0px; +} +a:link, +a:visited { + color: #1b6d85; + text-decoration: none; +} +a:hover, +a:active, +a.active { + text-decoration: underline; +} +.image { + max-width:100%; + height:auto; + display: inline-block; + vertical-align: top; + margin: 0px 20px 20px 0px; +} +blockquote { + background-color: #e5e4fe; + margin: 0px 0px 10px 0px; + padding: 10px; +} +pre { + color: #BABABA; + background: #2B2B2B none repeat scroll 0% 0%; + padding: 10px; + margin: 0px 0px 10px 0px; +} +code { + padding: 0px; + display: block; + padding: 2px 0px 2px 10px; + margin: 0px; + border-left: 3px solid #D5C5CA; + border-radius: 0px; + color: #c7254e; + background-color: #f9f2f4; +} +q { + display: block; + color: #858D93; + padding: 2px 0px 2px 10px; + margin: 0px; + border-left: 3px solid #C5D0D8; + background-color: #F8F8F8; + border-radius: 0px; +} \ No newline at end of file diff --git a/themes/bulaksu/assets/css/main.css b/themes/bulaksu/assets/css/main.css new file mode 100644 index 0000000..1a7779f --- /dev/null +++ b/themes/bulaksu/assets/css/main.css @@ -0,0 +1,1445 @@ +html, body { + height: 100%; +} +body { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 14px; +} +h1 { + font-size: 28px; +} +h2 { + font-size: 26px; +} +h3 { + font-size: 22px; +} +h4 { + font-size: 18px; +} +h5 { + font-size: 14px; +} +h6 { + font-size: 10px; +} +p { + margin: 0px; +} +a:link, +a:visited { + color: #24669E; + text-decoration: none; +} +a:hover, +a:active, +a.active { + text-decoration: underline; + color: #337AB7; +} +a.external-url { + color: #337AB7 !important; +} +a.btn-primary { + color: #FFF; +} +#main-container-wrapper { + background: #ffffff url(../images/gradient.jpg) repeat-x 0 0; + height: 100%; +} +#main-container { + background: url(../images/bg.jpg) no-repeat 50% 0%; + min-height: 100%; +} +/** bootstrap **/ +.container { + +} +.breadcrumb { + padding: 10px 15px; + background-color: #fafafa; + background-color: rgba(250, 250, 250, 0.9); +} +.page-header { + border-bottom: 1px solid #DBDCEA; +} +.navbar-default { + background-image: -webkit-linear-gradient(top, #fff 0, #F0EDF5 100%); + background-image: -o-linear-gradient(top, #fff 0, #F0EDF5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#F0EDF5)); + background-image: linear-gradient(to bottom, #fff 0, #F0EDF5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffF0EDF5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} +.navbar-default .navbar-nav li a { + color: #555; +} +.btn-default { + text-shadow:0 1px 0 #fff; + background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%); + background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%); + background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0)); + background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); + filter:progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat:repeat-x; + border-color:#dbdbdb; + border-color:#ccc +} +.btn-primary { + background-color: #5E7987; + background-image:-webkit-linear-gradient(top,#5E7987 0, #3D475C 100%); + background-image:-o-linear-gradient(top,#5E7987 0,#3D475C 100%); + background-image:-webkit-gradient(linear,left top,left bottom,from(#5E7987),to(#3D475C)); + background-image:linear-gradient(to bottom,#5E7987 0,#3D475C 100%); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5E7987', endColorstr='#ff3D475C', GradientType=0); + filter:progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat:repeat-x; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn-primary:hover, .btn-primary:focus { + background-color: #3D475C; +} +.btn-primary.active, .btn-primary:active, .open > .dropdown-toggle.btn-primary { + color: #FFF; + background-color: #3D475C; + border-color: #324465; +} +.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover { + color:#fff; + background-color: rgb(60, 67, 78); + border-color: #1b2e40 +} +.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover { + background-color: #3D475C; + border-color: #324465; +} +.zira-confirm-modal .modal-content { + background-color: #959C89; +} +.zira-confirm-modal .modal-header { + background-color: #778A75; + border-bottom: 1px solid #626B5A; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + color: #FFFFFF; +} +.zira-confirm-modal .modal-body { + border-bottom: 1px solid #DED8BA; + border-top: 1px solid #ffffff; + background-color: #F9F7EB; +} +.zira-confirm-modal .modal-footer { + border-top: 1px solid #ffffff; + background-color: #F9F7EB; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; +} +.zira-error-modal .modal-content { + background-color: #8C6781; +} +.zira-error-modal .modal-header { + background-color: #AA4372; + border-bottom: 1px solid #7E1166; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + color: #fff; +} +.zira-error-modal .modal-body { + border-bottom: 1px solid #E9D7E4; + border-top: 1px solid #ffffff; + background-color: #FBF7FA; +} +.zira-error-modal .modal-footer { + border-top: 1px solid #ffffff; + background-color: #FBF7FA; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; +} +.zira-message-modal .modal-content { + background-color: #5B7EA1; +} +.zira-message-modal .modal-header { + background-color: #357BA1; + border-bottom: 1px solid #064480; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + color: #fff; +} +.zira-message-modal .modal-body { + border-bottom: 1px solid #CBD7DA; + border-top: 1px solid #ffffff; + background-color: #F6F7F8; +} +.zira-message-modal .modal-footer { + border-top: 1px solid #ffffff; + background-color: #F6F7F8; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; +} +.zira-prompt-modal .modal-content { + background-color: #899C9C; +} +.zira-prompt-modal .modal-header { + background-color: #7D8892; + border-bottom: 1px solid #5A656B; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + color: #FFFFFF; +} +.zira-prompt-modal .modal-body { + border-bottom: 1px solid #DED8BA; + border-top: 1px solid #ffffff; + background-color: #F9F7EB; +} +.zira-prompt-modal .modal-footer { + border-top: 1px solid #ffffff; + background-color: #F9F7EB; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; +} +/** user profile **/ +.user-profile-photo { + float: left; + border: 5px solid #CCCCCC; + padding: 5px; + margin-right: 10px; + overflow: hidden; + border-radius: 3px; + box-shadow: 0px 0px 2px #cccccc; + background-color: #FFFFFF; +} +.user-head { + margin-bottom: 10px; +} +.user-profile h1 { + margin: 0px 0px 5px; +} +.user-profile h2 { + margin: 60px 0px 10px; + padding: 10px 0px; + border-bottom: 1px solid #E4E4E4; +} +.user-button .user-profile-links { + float: right; + margin-top: -40px; +} +.user-black-list-link .if-blocked { + display: none; +} +.user-black-list-link.blocked .if-blocked { + display: inline; +} +.user-black-list-link.blocked .if-not-blocked { + display: none; +} +#dashpanel-fixed-button:link, +#dashpanel-fixed-button:visited { + display: block; + position: fixed; + height: 42px; + top: 0px; + left: 8px; + z-index: 999; + font-size: 18px; + color: #444444; + text-decoration: none; + background-image: -webkit-linear-gradient(top, #fff 0, #F0EDF5 100%); + background-image: -o-linear-gradient(top, #fff 0, #F0EDF5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#F0EDF5)); + background-image: linear-gradient(to bottom, #fff 0, #F0EDF5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffF0EDF5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + padding: 8px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + box-shadow: 0px 0px 4px #e3e3e3; +} +#dashpanel-fixed-button:hover { + color: #000000; + box-shadow: 0px 0px 4px #d3d3d3; +} +#dashpanel-fixed-button img { + display: block; + float: left; + margin-top: 4px; + margin-right: 2px; +} +/** header **/ +header { + min-height: 210px; + position: relative; + margin-bottom: 40px; +} +header .header-top-item { + float: right; + margin: 0px 15px 0px 50px; +} +header .header-top-buttons { + padding: 8px 0px 0px; + font-size: 14px; +} +header .header-top-buttons .header-top-button-text, +header .header-top-buttons .header-top-button { + float: left; + margin-right: 10px; +} +header .header-top-buttons .header-top-button { + margin-right: 5px; +} +header .header-top-buttons .header-top-button .social-btn { + box-shadow: none; + margin-top: -5px; +} +ul#user-menu { + list-style-type: none; + display: block; + margin: 0px 15px 0px 50px; + padding: 0px; + height: 30px; + float: right; +} +ul#user-menu.authorized { + +} +ul#user-menu li.menu-item { + display: block; + float: left; + position: relative; + margin: 0px; + color: #575262; +} +ul#user-menu li.menu-item.open { + box-shadow: 0px -1px 8px rgba(209, 209, 209, 0.8) inset; + background-color: #E2E1E4; +} +ul#user-menu li.menu-item-separator { + margin: 0px 0px; + padding: 8px 0px; +} +ul#user-menu li.menu-item-separator:after { + content: '\2022'; +} +ul#user-menu li.menu-item a.menu-link:link, +ul#user-menu li.menu-item a.menu-link:visited { + display: block; + padding: 8px 14px; + color: #333; +} +ul#user-menu li.menu-item a.menu-link:hover, +ul#user-menu li.menu-item a.menu-link.active, +ul#user-menu li.menu-item.open a.menu-link { + color: #000; + text-decoration: none; +} +ul#language-switcher { + list-style-type: none; + display: block; + padding: 0px; + margin: 0px 15px 0px 50px; + height: 30px; + float: right; +} +ul#language-switcher li { + float: left; + margin: 0px 0px 0px 1px; +} +ul#language-switcher li a:link, +ul#language-switcher li a:visited { + display: block; + font-size: 12px; + color: #777777; + padding: 5px 10px; +} +ul#language-switcher li a:hover, +ul#language-switcher li a.active { + background-color: #ECE2FF; + background-color: rgba(236, 226, 255, 0.5); + color: #000000; + text-decoration: none; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + box-shadow: 0px 0px 1px #92B4C5; +} +ul#language-switcher li a.active { + background-color: #A4B4BC; + color: #FFF; + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.12) inset; +} +#site-logo-wrapper { + position: relative; + clear: both; + margin-left: 15px; + margin-bottom: 30px; +} +#site-logo-wrapper a#site-logo:link, +#site-logo-wrapper a#site-logo:visited { + display: inline-block; + color: #3C4045; + margin: 0px; + text-decoration: none; + height: 80px; +} +#site-logo-wrapper a#site-logo:hover { + color: #1B6D85; +} +#site-logo-wrapper a#site-logo img { + border: none; + vertical-align: middle; + margin-right: 10px; + max-width: 200px; + max-height: 80px; +} +#site-logo-wrapper a#site-logo span { + font-size: 30px; + vertical-align: middle; +} +#site-logo-wrapper #site-slogan { + display: inline-block; + font-style: italic; + white-space: nowrap; + text-shadow: 0px 0px 8px #fff; + vertical-align: bottom; +} +#top-menu-wrapper { + margin: 20px 15px 0px; + clear: both; +} +/** content **/ +.image { + max-width:100%; + height:auto; + display: inline-block; + vertical-align: top; + margin: 0px 18px 18px 0px; + border: 1px solid #EEEEEE; + border-radius: 3px; + box-shadow: 0px 0px 2px #eeeeee; +} +.image-wrapper { + max-width:100%; + display: inline-block; + vertical-align: top; + margin: 0px 18px 18px 0px; + background: #DDE0E4; + border: 1px solid #EEEEEE; + box-shadow: 0px 0px 2px #eeeeee; +} +.image-wrapper .image { + border: none; + box-shadow: none; + border-radius: 0; + margin: 0; +} +.image-wrapper .image-description { + color: #5d5b6b; + font-size: 12px; + text-align: center; + padding: 10px 0px; +} +.lightbox-image { + cursor: pointer; +} +.block { + margin-bottom: 20px; +} +.block h1, +.block h2, +.block h3, +.block h4, +.block h5, +.block h6 { + margin-top: 0px; +} +.block-image { + max-width:100%; + height:auto; + display: block; + margin: 0px auto 20px; +} +article .datetime { + font-style: italic; + color: #888888; + float: left; + margin-right: 20px; +} +article .author { + font-style: italic; + color: #888888; + float: right; + margin-left: 20px; +} +article .article-info { + overflow: hidden; + margin-bottom: 10px; +} +article .article { + margin: 30px 0px; +} +article .article p { + line-height: 26px; + font-size: 16px; +} +article .rating { + color: #888888; + overflow: hidden; + margin-bottom: 30px; +} +article .rating a.like:link, +article .rating a.like:visited { + position: relative; + z-index: 2; + font-size: 14px; + height: 30px; + line-height: 30px; + background-color: #2F5F87; + background-color: #337AB7; + display: inline-block; + padding: 0px 25px; + color: #FFF; + border-radius: 3px; +} +article .rating a.like:hover { + text-decoration: none; + background-color: #3A67A2; + box-shadow: inset 0px 0px 1px #ffffff; +} +article .rating a.like.active { + text-decoration: none; + background-color: #2C7E72; +} +article .rating a span.glyphicon { + font-size: 20px; + vertical-align: middle; + margin-right: 5px; +} +article .rating .share-wrapper { + position: relative; + z-index: 1; + left: -999px; + display: inline-block; + vertical-align: top; + margin-left: 10px; + transition: left .5s ease; +} +.share-btn-wrapper, +.social-btn-wrapper { + overflow: hidden; +} +.share-btn, +.social-btn { + display: block; + float: left; + width: 28px; + height: 28px; + background-image: url(../images/share-buttons.jpg); + background-repeat: no-repeat; + margin-right: 4px; + border-radius: 3px; + box-shadow: 0px 0px 2px #eeeeee; + text-decoration: none; +} +.share-btn:hover, +.social-btn:hover { + box-shadow: 0px 0px 2px #aaaaaa; +} +article .rating .share-wrapper .share-btn { + margin-top: 1px; +} +.share-btn.gp, +.social-btn.gp { + background-position: 0px 0px; +} +.share-btn.vk, +.social-btn.vk { + background-position: -28px 0px; +} +.share-btn.fb, +.social-btn.fb { + background-position: -56px 0px; +} +.share-btn.tw, +.social-btn.tw { + background-position: -84px 0px; +} +.share-btn.ok, +.social-btn.ok { + background-position: -112px 0px; +} +.oauth-btn { + float: left; + margin-right: 10px; +} +.oauth-btn.social-btn { + margin-top: -6px; + margin-right: 5px; +} +.user-login-form-extra-items { + float: left; +} +.user-login-form-extra-item { + float: left; +} +.gallery-wrapper { + margin: 30px 0px 20px; +} +.gallery { + display: block; + margin: 0px; + padding: 2px; + list-style-type: none; + border: 1px solid #eeeeee; + border-radius: 3px; + color: #ffffff; + overflow: hidden; + box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.15) inset, 0px 1px 5px rgba(0, 0, 0, 0.075); + background-color: #fafafa; + background-color: rgba(250, 250, 250, 0.9); +} +.gallery li { + display: block; + float: left; + margin: 0px; +} +.gallery li a:link, +.gallery li a:visited { + display: block; + margin: 1px; + border: 1px solid #eeeeee; + transition: border .2s; +} +.gallery li a:hover { + border: 1px solid #337AB7; +} +.gallery li img { + display: block; + border: none; +} +.slider { + display: block; + margin: 0px; + padding: 0px; + list-style-type: none; +} +.list { + list-style-type: none; + margin: 20px 0px; + padding: 0px; +} +.list .list-item { + margin-bottom: 20px; + overflow: hidden; + border: 1px solid #eeeeee; + background-color: #FAFAFA; + background-color: rgba(250, 250, 250, 0.9); + border-radius: 3px; + box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.15) inset, 0px 1px 5px rgba(0, 0, 0, 0.075); +} +.list .list-item .list-title-wrapper { + background-color: #F5F5F5; + border-bottom: 1px solid #eeeeee; + padding: 10px 14px; + margin: 0px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} +.list .list-item a.list-title:link, +.list .list-item a.list-title:visited { + font-size: 18px; + margin: 0px 0px 5px; + text-shadow: 1px 1px 0px #ffffff; +} +.list .list-item .list-content-wrapper { + padding: 10px 14px 0px; +} +.list .list-item a.list-thumb:link, +.list .list-item a.list-thumb:visited { + display: block; + text-decoration: none; + float: left; + margin: 0px 10px 10px 0px; + border: 1px solid #EEEEEE; + background-color: #EBE6F0; + padding: 2px; +} +.list .list-item a.list-thumb:hover { + box-shadow: 0px 0px 2px #eeeeee; +} +.list .list-item a.list-thumb img { + border: none; + max-width: 100%; + max-width: none\9; /** ie8 hack **/ + height: auto; +} +.list .list-item .list-info-wrapper { + clear: left; + margin: 10px 0px 0px; + padding: 0px 14px 10px; + font-style: italic; +} +.list .list-item .list-info { + margin-right: 10px; + color: #3F3F3F; +} +.list .list-item .list-info a:link, +.list .list-item .list-info a:visited { + color: #3F3F3F; +} +.list-view-more-wrapper { + margin: 20px 0px; +} +.widget-category-wrapper, +.widget-top-wrapper { + margin-bottom: 20px; +} +/** comments **/ +.comments-wrapper { + margin: 40px 0px; +} +.comment-btn:link, +.comment-btn:visited { + display: block; + float: right; + color: #ffffff; +} +.comments { + list-style-type: none; + margin: 40px 0px; + padding: 0px; +} +.comments .comments-item { + margin-bottom: 20px; + overflow: hidden; +} +.comments .comments-item-nested-1 { + margin-left: 60px; +} +.comments .comments-item-nested-2 { + margin-left: 120px; +} +.comments .comments-item-nested-3 { + margin-left: 180px; +} +.comments .comments-item-nested-4 { + margin-left: 240px; +} +.comments .comments-item-nested-5 { + margin-left: 300px; +} +.comments .comments-item-nested-6 { + margin-left: 360px; +} +.comments .comments-item-nested-7 { + margin-left: 420px; +} +.comments .comments-item-nested-8 { + margin-left: 480px; +} +.comments .comments-item-nested-9 { + margin-left: 540px; +} +.comments .comments-item-nested-10 { + margin-left: 600px; +} +.comments .comments-item.disabled { + color: #777777; +} +.comments .comments-item .comment-avatar { + max-width: 50px; + height: auto; + display: block; + float: left; + border-radius: 5px; +} +.comments .comments-item .comment-head { + display: block; + font-weight: bold; + margin-left: 60px; +} +.comments .comments-item .comment-text { + display: block; + margin: 5px 0px 5px 60px; + background-color: #F5F5F5; + padding: 10px; + border-radius: 10px; +} +.comments .comments-item.disabled .comment-text { + background-color: #E3E3E3; +} +.comments .comments-item .comment-info { + display: block; + margin: 5px 0px 5px 60px; +} +.comments .comments-item .comment-info a:link, +.comments .comments-item .comment-info a:visited { + color: #000000; + text-decoration: none; +} +.comments .comments-item .comment-info a:hover { + color: #474855; + text-decoration: none; +} +.comments .comments-item .comment-info a.comment-like:link, +.comments .comments-item .comment-info a.comment-like:visited { + color: #1d7690; +} +.comments .comments-item .comment-info a.comment-like:hover, +.comments .comments-item .comment-info a.comment-like.active { + color: #114150; +} +.comments .comments-item .comment-info a.comment-dislike:link, +.comments .comments-item .comment-info a.comment-dislike:visited { + color: #a41748; +} +.comments .comments-item .comment-info a.comment-dislike:hover, +.comments .comments-item .comment-info a.comment-dislike.active { + color: #550e2a; +} +.comments-view-more-wrapper { + margin-bottom: 40px; +} +.parse-content code { + padding: 0px; + display: block; + padding: 2px 0px 2px 10px; + margin: 0px; + border-left: 3px solid #D5C5CA; + border-radius: 0px; +} +.parse-content q { + display: block; + color: #858D93; + padding: 2px 0px 2px 10px; + margin: 0px; + border-left: 3px solid #C5D0D8; + background-color: #FBFBFB; + border-radius: 0px; +} +blockquote { + color: #757D93; + font-size: 100%; + background-color: #FEFEFE; + margin: 0px 0px 18px 0px; +} +pre { + background-color: #FEFEFE; + border: 1px solid #eee; +} +/** sidebar **/ +.sidebar .page-header { + margin: 0px; + padding-bottom: 4px; +} +.sidebar .widget-category-title { + font-size: 20px; + margin-top: 0px; + text-shadow: 1px 1px 0px #fff; +} +.sidebar .list { + margin: 4px 0px 20px; +} +.sidebar .list .list-item { + margin-bottom: 10px; + overflow: hidden; + border: none; + background: none; + border-radius: 0px; + border-bottom: 1px dashed #eeeeee; + box-shadow: none; +} +.sidebar .list .list-item .list-title-wrapper { + background: none; + border-bottom: none; + padding: 4px 0px; + margin: 0px; + text-overflow: clip; + white-space: normal; + overflow: hidden; +} +.sidebar .list .list-item a.list-title:link, +.sidebar .list .list-item a.list-title:visited { + font-size: 14px; +} +.sidebar .list .list-item .list-content-wrapper { + padding: 4px 0px 0px; + margin-bottom: 10px; +} +.sidebar .list .list-item a.list-thumb:link, +.sidebar .list .list-item a.list-thumb:visited { + /*float: none;*/ + /*display: inline-block;*/ + max-width: 50%; +} +.sidebar .list .list-item a.list-thumb img { + width: 100%\9; /** ie8 hack **/ +} +.sidebar .list .list-item .list-info-wrapper { + padding: 4px 0px; +} +.sidebar .list .list-item .list-info { + display: block; +} +/** secondary menu **/ +#secondary-menu-wrapper { + margin-bottom: 20px; +} +#secondary-menu-wrapper ul li a:link, +#secondary-menu-wrapper ul li a:visited { + background-color: #fafafa; + color: #333333; +} +#secondary-menu-wrapper ul li a:hover { + background-color: #f5f5f5; + color: #337AB7; +} +#secondary-menu-wrapper ul li.active a { + background-color: #337AB7; + color: #ffffff; +} +#secondary-menu-wrapper ul li.parent { + margin-bottom: 10px; +} +#secondary-menu-wrapper ul li.parent a.menu-link { + color: #333333; + background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%); + background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%); + background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2)); + background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); + background-repeat:repeat-x; + -webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075); + box-shadow:inset 0 3px 9px rgba(0,0,0,.075) +} +#secondary-menu-wrapper .secondary-child ul { + margin-top: 2px; +} +#secondary-menu-wrapper .secondary-child ul .menu-link-ico { + margin-right: 2px; +} +#secondary-menu-wrapper .secondary-child ul .menu-link-ico:after { + content: '\203A'; +} +/** search **/ +.search-form-wrapper { + overflow: hidden; +} +.search-form-description { + margin-top: 0px; + margin-bottom: 100px; + font-style: italic; +} +.search-form-wrapper .col-sm-3 { + padding-left: 0px; + padding-right: 0px; +} +.search-simple-form { + display: none; + position: relative; +} +.search-simple-form .search-text-clear { + position: absolute; + top: 11px; + right: 59px; + z-index: 9; + cursor: pointer; +} +.search-simple-form input[type=text] { + padding-right: 20px; +} +.search-simple-form.loading button[type=submit] .glyphicon { + visibility: hidden; +} +#top-menu-container .zira-search-preview-wnd { + position: absolute; + width: 450px; + right: 30px; + top: 52px; + z-index: 99; + background-color: #f9f9f9; + box-shadow: 0px 5px 10px rgba(113, 113, 113, 0.52); +} +.zira-search-preview-wnd .list { + margin: 0px; +} +.zira-search-preview-wnd .list .list-item { + border: none; + border-top: 1px solid #f4f4f4; + border-left: 1px solid #eeeeee; + border-right: 1px solid #eeeeee; + border-bottom: 1px solid #eeeeee; + box-shadow: none; + background-color: #fafafa; + margin-bottom: 0px; + border-radius: 0; + cursor: pointer; +} +.zira-search-preview-wnd .list .list-item:first-child { + border-top: none; +} +.zira-search-preview-wnd .list .list-item:last-child { + border-bottom: 1px solid #dddddd; +} +.zira-search-preview-wnd .list .list-item:hover { + background-color: #fff; + border-left: 1px solid #C9D3F2; + border-right: 1px solid #C9D3F2; + border-bottom: 1px solid #C9D3F2; +} +.zira-search-preview-wnd .list .list-item .list-title-wrapper { + /**background-color: #EAEAEA;**/ + background-color: #F3F3F3; + padding: 6px 10px; +} +.zira-search-preview-wnd .list .list-item:hover .list-title-wrapper { + background-color: #DAE1E6; + color: #3B4350; +} +.zira-search-preview-wnd .list .list-item a.list-title:link, +.zira-search-preview-wnd .list .list-item a.list-title:visited { + font-size: 14px; + color: #656587; + text-shadow: none; +} +.zira-search-preview-wnd .list .list-item:hover a.list-title:link, +.zira-search-preview-wnd .list .list-item:hover a.list-title:visited { + color: #3B4350; +} +.zira-search-preview-wnd .list .list-item a.list-title:hover { + text-decoration: none; +} +.zira-search-preview-wnd .list .list-item a.list-thumb:link, +.zira-search-preview-wnd .list .list-item a.list-thumb:visited { + margin-bottom: 6px; + padding: 0px; +} +.zira-search-preview-wnd .list .list-item a.list-thumb img { + max-height: 60px; + width: auto; +} +.zira-search-preview-wnd .list .list-item .list-content-wrapper { + padding: 6px 10px; +} +.zira-search-preview-wnd .list .list-item .list-content-wrapper p { + max-height: 60px; + overflow: hidden; +} +/** footer **/ +footer { + min-height: 50px; + position: relative; + margin-top: 40px; + margin-right: 15px; + margin-left: 15px; + border: 1px solid #e7e7e7; + background: #f5f5f5; + background: -moz-linear-gradient(top, #f8f8f8 0%, #f5f5f5 100%); + background: -webkit-linear-gradient(top, #f8f8f8 0%,#f5f5f5 100%); + background: linear-gradient(to bottom, #f8f8f8 0%,#f5f5f5 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f8f8f8', endColorstr='#f5f5f5',GradientType=0 ); + box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.15) inset, 0px 1px 5px rgba(0, 0, 0, 0.075); + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +footer p { + line-height: 50px; + padding: 0px 15px; +} +#footer-menu-wrapper { + margin: 15px 0px 0px; +} +#footer-menu-wrapper ul.menu { + list-style-type: none; + margin: 0px 3px; + padding: 0px; +} +#footer-menu-wrapper ul.menu li.menu-item { + display: inline-block; + margin: 0px 8px; +} +#footer-menu-wrapper ul.menu li.menu-item-separator { + display: inline-block; + margin: 0px; + font-size: 90%; + vertical-align: top; +} +#footer-menu-wrapper ul.menu li.menu-item-separator:after { + /*content: '\22c5';*/ + content: '|'; +} +#footer-menu-wrapper ul.menu li.menu-item a.menu-link:link, +#footer-menu-wrapper ul.menu li.menu-item a.menu-link:visited { + text-decoration: none; + color: #333333; + padding: 2px 4px; + border-radius: 2px; +} +#footer-menu-wrapper ul.menu li.menu-item a.menu-link:hover, +#footer-menu-wrapper ul.menu li.menu-item a.menu-link.active, +#footer-menu-wrapper ul.menu li.menu-item.active a.menu-link { + text-decoration: none; + color: #337AB7; +} +footer a.rss-link:link, +footer a.rss-link:visited { + position: absolute; + bottom: 14px; + right: 14px; + display: block; + width: 20px; + height: 20px; + background: url(../images/rss.png) no-repeat 0 0; + outline: none; +} +.zira-loader-wrapper { + font-style: italic; + display: inline-block; + vertical-align: middle; + margin-left: 10px; +} +.zira-loader { + display: inline-block; + vertical-align: top; + width: 16px; + height: 16px; + background: url(../images/zira-loader.gif) no-repeat 0 0; +} +.search-simple-form .zira-loader { + position: absolute; + top: 9px; + right: 28px; + z-index: 9; +} +a.scroll-top:link, +a.scroll-top:visited { + display: block; + position: fixed; + bottom: 100px; + right: 30px; + width: 32px; + height: 32px; + background: url(../images/up.png) no-repeat 0 0; + opacity: 0; + filter: alpha(opacity=0); + transition: opacity 1s ease; + outline: none; +} +a.scroll-top:hover { + opacity: 1 !important; + filter: alpha(opacity=100); +} +a.scroll-top.visible:link, +a.scroll-top.visible:visited { + opacity: .6; + filter: alpha(opacity=60); +} + +/** home page **/ +.home-category-wrapper { + margin: 40px 0px; +} +.home-category-wrapper .home-category-title, +.home-category-wrapper .home-category-title a:link, +.home-category-wrapper .home-category-title a:visited { + color: #222222; +} +.home-category-wrapper .home-category-title a:hover { + color: #1B6D85; + text-decoration: none; +} +.grid-category-wrapper .list .list-item { + width: 49%; + display: inline-block; + vertical-align: top; + margin-right: 1%; +} +.grid-category-wrapper .list .list-item:nth-child(2) { + margin-right: 0px; +} + +.caret-right { + border-bottom: 4px solid transparent; + border-top: 4px solid transparent; + border-left: 4px solid; + display: inline-block; + width: 0; + height: 0; + vertical-align: middle; + margin-right: 2px; +} +.menu-default { + background: #777 !important; + color: #ffffff !important; +} +.menu-primary { + background: #337AB7 !important; + color: #ffffff !important; +} +.menu-success { + background: #5CB85C !important; + color: #ffffff !important; +} +.menu-info { + background: #5BC0DE !important; + color: #ffffff !important; +} +.menu-warning { + background: #F0AD4E !important; + color: #ffffff !important; +} +.menu-danger { + background: #D9534F !important; + color: #ffffff !important; +} +.menu-default a, +.menu-primary a, +.menu-success a, +.menu-info a, +.menu-warning a, +.menu-danger a { + color: #ffffff !important; + background: none !important; +} + +#sitemap-wrapper { + margin-bottom: 40px; +} +#sitemap-wrapper ul { + list-style-type: none; + margin: 0px; + padding: 0px; + box-shadow: 0px 0px 2px #ececec; + border: 1px solid #eee; + border-radius: 3px; +} +#sitemap-wrapper ul li { + padding: 10px; + margin: 0px; + border-top: 1px solid #fff; + border-bottom: 1px solid #EDEDED; +} +#sitemap-wrapper ul li:first-child { + border-top: none; +} +#sitemap-wrapper ul li:last-child { + border-bottom: none; +} +#sitemap-wrapper ul li.even { + background-color: #FAFAFA; + background-color: rgba(250, 250, 250, 0.2); +} +#sitemap-wrapper ul li.odd { + background-color: #FFFFFF; + background-color: rgba(255, 255, 255, 0.4); +} +#sitemap-wrapper ul li.menu-item-offset { + padding-left: 310px; +} +#sitemap-wrapper ul li.menu-item-offset-1 { + padding-left: 40px; +} +#sitemap-wrapper ul li.menu-item-offset-2 { + padding-left: 70px; +} +#sitemap-wrapper ul li.menu-item-offset-3 { + padding-left: 100px; +} +#sitemap-wrapper ul li.menu-item-offset-4 { + padding-left: 130px; +} +#sitemap-wrapper ul li.menu-item-offset-5 { + padding-left: 160px; +} +#sitemap-wrapper ul li.menu-item-offset-6 { + padding-left: 190px; +} +#sitemap-wrapper ul li.menu-item-offset-7 { + padding-left: 220px; +} +#sitemap-wrapper ul li.menu-item-offset-8 { + padding-left: 250px; +} +#sitemap-wrapper ul li.menu-item-offset-9 { + padding-left: 280px; +} +#sitemap-wrapper ul li a:link, +#sitemap-wrapper ul li a:visited { + color: #333; +} + +.contacts-wrapper { + overflow: hidden; + margin-bottom: 40px; +} +.contact-image { + max-width: 50%; + height: auto; + float: left; + margin: 0px 20px 0px 0px; + border: 5px solid #CCCCCC; + padding: 5px; + border-radius: 3px; + background-color: #FFFFFF; +} +.contact-name { + margin: 0px 0px 20px; + font-size: 22px; +} +.contact-details { + float: left; +} +.contact-address { + margin: 0px; +} +.contact-info { + margin: 10px 0px 0px; + font-style: italic; +} +.social-contacts { + margin: 10px 0px 0px; +} +#yandex-map, +#google-map { + margin-bottom: 40px; + border: 5px solid #EEEEEE; + box-shadow: 0px 0px 2px #cccccc; + border-radius: 3px; +} +.messages-panel { + overflow: hidden; +} +.messages-panel .navbar { + margin-bottom: 0px; + border-radius: 0; + background: #fefefe; +} +.messages-list li { + border-bottom: 1px solid #ffffff; + border-top: 1px solid #eeeeee; + padding: 10px; + overflow: hidden; +} +.messages-list li.even { + background-color: #fefefe; +} +.messages-list li.odd { + background-color: #fafafa; +} +.messages-list li a:link, +.messages-list li a:visited { + color: #333; +} +.messages-list li.highlight a:link, +.messages-list li.highlight a:visited { + color: #000; + font-weight: bold; +} +.messages-list .message-head { + padding-bottom: 10px; + margin-bottom: 10px; + border-bottom: 1px solid #EEEEEE; +} +.messages-list .message-head .message-date { + float: right; +} +.messages-list .message-avatar { + float: left; +} +.messages-list .message-avatar a img { + display: block; + max-width: 100px; + height: auto; + border-radius: 5px; +} +.messages-list .message-content { + margin-left: 120px; +} +.no-messages-message { + font-style: italic; + margin: 20px 0px 100px; +} +.compose-message-btn { + float: right; +} +.user-messages-resipients-list { + list-style-type: none; + margin: 0px 0px 20px; + padding: 0px; +} +.user-messages-resipients-list li { + display: inline-block; +} +.user-messages-resipients-list li.separator { + margin-right: 10px; +} +.user-messages-resipients-list li.separator:after { + content: ', '; +} +.user-messages-resipients-list li a:link, +.user-messages-resipients-list li a:visited { + color: #555; +} +/** mobile **/ +@media only screen and (max-width: 767px) { + .user-profile h1 { + clear: left; + padding-top: 10px; + } + .user-button .user-profile-links { + float: none; + margin-top: 0px; + } + header { + height: auto; + } + #site-logo-wrapper { + margin: 0px 20px; + } + #site-logo-wrapper a#site-logo:link, + #site-logo-wrapper a#site-logo:visited { + + } + #site-logo-wrapper #site-slogan { + display: block; + text-align: right; + } + header .header-top-item { + display: none; + } + ul#user-menu { + visibility: hidden; + } + #top-menu-wrapper { + margin: 10px 15px 0px; + } + .grid-category-wrapper .list .list-item { + width: 100%; + display: block; + margin-right: 0px; + } + #top-menu-container .zira-search-preview-wnd { + position: static; + width: 100%; + margin-bottom: 10px; + box-shadow: none; + } + .search-simple-form .search-text-clear { + top: 21px; + } + .search-simple-form .zira-loader { + top: 19px; + } + a.scroll-top { + display: none !important; + } +} +@media (min-width: 768px) { + .search-simple-form { + display: none; + } +} +@media (min-width: 992px) { + .search-simple-form { + display: block; + } +} diff --git a/themes/bulaksu/assets/images/bg-alt.jpg b/themes/bulaksu/assets/images/bg-alt.jpg new file mode 100644 index 0000000..925fa42 Binary files /dev/null and b/themes/bulaksu/assets/images/bg-alt.jpg differ diff --git a/themes/bulaksu/assets/images/bg.jpg b/themes/bulaksu/assets/images/bg.jpg new file mode 100644 index 0000000..36be373 Binary files /dev/null and b/themes/bulaksu/assets/images/bg.jpg differ diff --git a/themes/bulaksu/assets/images/gradient.jpg b/themes/bulaksu/assets/images/gradient.jpg new file mode 100644 index 0000000..630ee51 Binary files /dev/null and b/themes/bulaksu/assets/images/gradient.jpg differ diff --git a/themes/bulaksu/assets/images/rss.png b/themes/bulaksu/assets/images/rss.png new file mode 100644 index 0000000..586c822 Binary files /dev/null and b/themes/bulaksu/assets/images/rss.png differ diff --git a/themes/bulaksu/assets/images/share-buttons.jpg b/themes/bulaksu/assets/images/share-buttons.jpg new file mode 100644 index 0000000..de9c925 Binary files /dev/null and b/themes/bulaksu/assets/images/share-buttons.jpg differ diff --git a/themes/bulaksu/assets/images/up.png b/themes/bulaksu/assets/images/up.png new file mode 100644 index 0000000..6f84f98 Binary files /dev/null and b/themes/bulaksu/assets/images/up.png differ diff --git a/themes/bulaksu/assets/images/zira-loader.gif b/themes/bulaksu/assets/images/zira-loader.gif new file mode 100644 index 0000000..c48e97e Binary files /dev/null and b/themes/bulaksu/assets/images/zira-loader.gif differ diff --git a/themes/bulaksu/error.php b/themes/bulaksu/error.php new file mode 100644 index 0000000..43f5923 --- /dev/null +++ b/themes/bulaksu/error.php @@ -0,0 +1,8 @@ +
    +

    +

    + +
    + +
    +Zira diff --git a/themes/bulaksu/layout-left.php b/themes/bulaksu/layout-left.php new file mode 100644 index 0000000..98f97f9 --- /dev/null +++ b/themes/bulaksu/layout-left.php @@ -0,0 +1,42 @@ + + + + + + + + + + +
    +
    +
    +
    + +
    +
    +
    + +
    + + + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/themes/bulaksu/layout-right.php b/themes/bulaksu/layout-right.php new file mode 100644 index 0000000..c8b3b0a --- /dev/null +++ b/themes/bulaksu/layout-right.php @@ -0,0 +1,42 @@ + + + + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    + + + + +
    + +
    +
    +
    + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/themes/bulaksu/layout-wide.php b/themes/bulaksu/layout-wide.php new file mode 100644 index 0000000..63feda5 --- /dev/null +++ b/themes/bulaksu/layout-wide.php @@ -0,0 +1,37 @@ + + + + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    + + + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/themes/bulaksu/layout.php b/themes/bulaksu/layout.php new file mode 100644 index 0000000..0172771 --- /dev/null +++ b/themes/bulaksu/layout.php @@ -0,0 +1,47 @@ + + + + + + + + + + +
    +
    +
    +
    + +
    +
    +
    + +
    + + + + +
    + +
    +
    +
    + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/themes/bulaksu/page.php b/themes/bulaksu/page.php new file mode 100644 index 0000000..1e5bbfa --- /dev/null +++ b/themes/bulaksu/page.php @@ -0,0 +1,49 @@ +
    +
    + +<?php echo (!empty($title) ? Zira\Helper::html($title) : '') ?> + + + + + +

    + +

    + + + + + +
    + +
    + + +
    + + + + +
    + + +
    +
    \ No newline at end of file diff --git a/themes/bulaksu/screenshot.jpg b/themes/bulaksu/screenshot.jpg new file mode 100644 index 0000000..c00083d Binary files /dev/null and b/themes/bulaksu/screenshot.jpg differ diff --git a/themes/bulaksu/theme.meta b/themes/bulaksu/theme.meta new file mode 100644 index 0000000..0b35d9f --- /dev/null +++ b/themes/bulaksu/theme.meta @@ -0,0 +1,4 @@ +[meta] +name = Bulaksu +preview = screenshot +author = Zira \ No newline at end of file diff --git a/themes/bulaksu/zira/comments.php b/themes/bulaksu/zira/comments.php new file mode 100644 index 0000000..cb6771b --- /dev/null +++ b/themes/bulaksu/zira/comments.php @@ -0,0 +1,72 @@ + +
    + + + + +

    ()

    + + + +
      + + +sort_path)) - 1; ?> +0) $comment_offset_class = ' comments-item-nested-'.($comment_offset < Zira\Config::get('comments_max_nesting', 5) ? $comment_offset : Zira\Config::get('comments_max_nesting', 5)); ?> +
    • +author_id > 0 && $comment->author_username !== null && $comment->author_firstname !== null && $comment->author_secondname !== null): ?> +author_id, $comment->author_firstname, $comment->author_secondname, $comment->author_username, null, $comment->author_image, null, array('class'=>'comment-avatar')) ?> + +author_image, null, array('class'=>'comment-avatar')) ?> + + +author_id > 0 && $comment->author_username !== null && $comment->author_firstname !== null && $comment->author_secondname !== null): ?> +sender_name ? Zira\User::generateUserProfileLink($comment->author_id, null, null, $comment->sender_name) : Zira\User::generateUserProfileLink($comment->author_id, $comment->author_firstname, $comment->author_secondname, $comment->author_username)); ?> + +sender_name ? Zira\Helper::html($comment->sender_name) : t('Guest')); ?> + +recipient_name): ?> +   recipient_name) ?> + + +

      content))) ?>

      + + creation_date)) ?>   + + +likes); ?> +   + + +dislikes); ?> +   + + + + +
    • + +
    +$limit*($page+1)): ?> +
    + +
    + + + +
    + +
    + + +'.t('Login').'') ?> + + +
    + + \ No newline at end of file diff --git a/themes/bulaksu/zira/contact.php b/themes/bulaksu/zira/contact.php new file mode 100644 index 0000000..bd29e28 --- /dev/null +++ b/themes/bulaksu/zira/contact.php @@ -0,0 +1,44 @@ + +
    + +<?php if (!empty($name)) echo Zira\Helper::html($name); ?> + +
    + +

    + + +
    + + +
    + + +
    + + + + + +

    + +
    +
    +$address, 'name'=>!empty($name) ? $name : ''), 'zira/google-map'); ?> +$address, 'name'=>!empty($name) ? $name : ''), 'zira/yandex-map'); ?> + \ No newline at end of file diff --git a/themes/bulaksu/zira/gallery.php b/themes/bulaksu/zira/gallery.php new file mode 100644 index 0000000..999a41a --- /dev/null +++ b/themes/bulaksu/zira/gallery.php @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/themes/bulaksu/zira/google-map.php b/themes/bulaksu/zira/google-map.php new file mode 100644 index 0000000..90a314e --- /dev/null +++ b/themes/bulaksu/zira/google-map.php @@ -0,0 +1,44 @@ + + + + +
    + + + + + + + + \ No newline at end of file diff --git a/themes/bulaksu/zira/home.php b/themes/bulaksu/zira/home.php new file mode 100644 index 0000000..fbb3698 --- /dev/null +++ b/themes/bulaksu/zira/home.php @@ -0,0 +1,50 @@ + + + +
    + + + +
      + +
    • + +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      +
      + + creation_date)) ?> + + + author_id, $record->author_firstname, $record->author_secondname, $record->author_username) ?> + + + comments ?> + + + + +category_name && $record->category_title): ?> + category_title) ?> + +
      +
    • + +
    +
    + + diff --git a/themes/bulaksu/zira/list.php b/themes/bulaksu/zira/list.php new file mode 100644 index 0000000..40f0519 --- /dev/null +++ b/themes/bulaksu/zira/list.php @@ -0,0 +1,44 @@ + +
      + + +
    • +

      +title) ?> +

      +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      +
      + + creation_date)) ?> + + + author_id, $record->author_firstname, $record->author_secondname, $record->author_username) ?> + + + comments ?> + + + + +category_name && $record->category_title): ?> + category_title) ?> + +
      +
    • + +=$settings['limit']) break; ?> + +
    +$settings['limit']): ?> +
    + +
    + + diff --git a/themes/bulaksu/zira/map.php b/themes/bulaksu/zira/map.php new file mode 100644 index 0000000..846a20c --- /dev/null +++ b/themes/bulaksu/zira/map.php @@ -0,0 +1,20 @@ +
    + +
    \ No newline at end of file diff --git a/themes/bulaksu/zira/search-results.php b/themes/bulaksu/zira/search-results.php new file mode 100644 index 0000000..eabed89 --- /dev/null +++ b/themes/bulaksu/zira/search-results.php @@ -0,0 +1,34 @@ + +
      + + +
    • +

      +title) ?> +

      +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      + +
      +category_name && $record->category_title): ?> + category_title) ?> + +
      + +
    • + +=$settings['limit']) break; ?> + +
    +$settings['limit'] && isset($settings['offset'])): ?> +
    + +
    + + diff --git a/themes/bulaksu/zira/search.php b/themes/bulaksu/zira/search.php new file mode 100644 index 0000000..ef38f4c --- /dev/null +++ b/themes/bulaksu/zira/search.php @@ -0,0 +1,11 @@ + + + +
    + +
    + +

    + \ No newline at end of file diff --git a/themes/bulaksu/zira/slider.php b/themes/bulaksu/zira/slider.php new file mode 100644 index 0000000..6f0cffb --- /dev/null +++ b/themes/bulaksu/zira/slider.php @@ -0,0 +1,9 @@ + +
    +
      + +
    • <?php echo Zira\Helper::html($_image->description) ?>
    • + +
    +
    + diff --git a/themes/bulaksu/zira/user/conversations.php b/themes/bulaksu/zira/user/conversations.php new file mode 100644 index 0000000..90a1f6b --- /dev/null +++ b/themes/bulaksu/zira/user/conversations.php @@ -0,0 +1,122 @@ + + +
    + +
    + + +
      +$item): ?> +
    • + +    + modified_date))) ?> +    + subject) ?> +
    • + +
    + +

    + + + diff --git a/themes/bulaksu/zira/user/menu.php b/themes/bulaksu/zira/user/menu.php new file mode 100644 index 0000000..f16c87f --- /dev/null +++ b/themes/bulaksu/zira/user/menu.php @@ -0,0 +1,27 @@ + +
      +$item): ?> +0): ?> + + + + +
    + \ No newline at end of file diff --git a/themes/bulaksu/zira/user/messages.php b/themes/bulaksu/zira/user/messages.php new file mode 100644 index 0000000..0e4ed8f --- /dev/null +++ b/themes/bulaksu/zira/user/messages.php @@ -0,0 +1,71 @@ + + + +
      +0): ?> +
    •  
    • +$user): ?> +0) echo '
    • '; ?> +
    • id, $user->firstname, $user->secondname, $user->username, null); ?>
    • + + +
    •  
    • +
    • + +
    +
    + +
    + + +
      +$item): ?> +
    • +
      +username): ?> +user_id, $item->firstname, $item->secondname, $item->username); ?> + + + +    +
      creation_date))) ?>
      +
      +
      +username): ?> +user_id, $item->firstname, $item->secondname, $item->username, null, $item->image); ?> + +
      +
      +

      content))) ?>

      +
      +
    • + +
    + + +0) echo $form; ?> + + \ No newline at end of file diff --git a/themes/bulaksu/zira/user/profile.php b/themes/bulaksu/zira/user/profile.php new file mode 100644 index 0000000..9d651fa --- /dev/null +++ b/themes/bulaksu/zira/user/profile.php @@ -0,0 +1,73 @@ +
    + +
    \ No newline at end of file diff --git a/themes/bulaksu/zira/widgets/block.php b/themes/bulaksu/zira/widgets/block.php new file mode 100644 index 0000000..d335703 --- /dev/null +++ b/themes/bulaksu/zira/widgets/block.php @@ -0,0 +1,6 @@ +
    + +

    + + +
    \ No newline at end of file diff --git a/themes/bulaksu/zira/widgets/category.php b/themes/bulaksu/zira/widgets/category.php new file mode 100644 index 0000000..09156fc --- /dev/null +++ b/themes/bulaksu/zira/widgets/category.php @@ -0,0 +1,49 @@ +
    + + + + +
      + +
    • +

      +title) ?> +

      +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      + +
      + + creation_date)) ?> + + + author_id, $record->author_firstname, $record->author_secondname, $record->author_username) ?> + + + comments ?> + + + + +category_name && $record->category_title): ?> + category_title) ?> + +
      + +
    • + +
    + +
    diff --git a/themes/bulaksu/zira/widgets/childmenu.php b/themes/bulaksu/zira/widgets/childmenu.php new file mode 100644 index 0000000..eb0cb2c --- /dev/null +++ b/themes/bulaksu/zira/widgets/childmenu.php @@ -0,0 +1,28 @@ +
    + +
    \ No newline at end of file diff --git a/themes/bulaksu/zira/widgets/discussed.php b/themes/bulaksu/zira/widgets/discussed.php new file mode 100644 index 0000000..08bacf0 --- /dev/null +++ b/themes/bulaksu/zira/widgets/discussed.php @@ -0,0 +1,42 @@ +
    + + + + +
      + +
    • +

      +title) ?> +

      +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      +
      + + + creation_date)) ?> + + + + + + + comments ?> + +category_name && $record->category_title): ?> + category_title) ?> + +
      +
    • + +
    + +
    diff --git a/themes/bulaksu/zira/widgets/footermenu.php b/themes/bulaksu/zira/widgets/footermenu.php new file mode 100644 index 0000000..b192d5b --- /dev/null +++ b/themes/bulaksu/zira/widgets/footermenu.php @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/themes/bulaksu/zira/widgets/languages.php b/themes/bulaksu/zira/widgets/languages.php new file mode 100644 index 0000000..893de4c --- /dev/null +++ b/themes/bulaksu/zira/widgets/languages.php @@ -0,0 +1,15 @@ +1) { +echo '
      '; + Zira\Helper::setAddingLanguageToUrl(false); + foreach($languages as $language) { + $url = Zira\Helper::html($language); + $class = ''; + if ($language == Zira\Config::get('language')) $url='/'; + if ($language == Zira\Locale::getLanguage()) $class=' class="active"'; + echo '
    • '.Zira\Helper::html(t(ucfirst($language))).'
    • '; + } + Zira\Helper::setAddingLanguageToUrl(true); +echo '
    '; +} diff --git a/themes/bulaksu/zira/widgets/logo.php b/themes/bulaksu/zira/widgets/logo.php new file mode 100644 index 0000000..6f3bff1 --- /dev/null +++ b/themes/bulaksu/zira/widgets/logo.php @@ -0,0 +1,13 @@ +'; + if (!empty($logo) || !empty($title)) { + echo ''; + } + if (!empty($slogan)) echo '

    '.Zira\Helper::html($slogan).'

    '; + else echo '

     

    '; + echo ''; +} \ No newline at end of file diff --git a/themes/bulaksu/zira/widgets/rated.php b/themes/bulaksu/zira/widgets/rated.php new file mode 100644 index 0000000..7827295 --- /dev/null +++ b/themes/bulaksu/zira/widgets/rated.php @@ -0,0 +1,42 @@ +
    + + + + +
      + +
    • +

      +title) ?> +

      +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      +
      + + + creation_date)) ?> + + + comments ?> + + + + + +category_name && $record->category_title): ?> + category_title) ?> + +
      +
    • + +
    + +
    diff --git a/themes/bulaksu/zira/widgets/share.php b/themes/bulaksu/zira/widgets/share.php new file mode 100644 index 0000000..b52f9c1 --- /dev/null +++ b/themes/bulaksu/zira/widgets/share.php @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/themes/bulaksu/zira/widgets/topmenu.php b/themes/bulaksu/zira/widgets/topmenu.php new file mode 100644 index 0000000..0e34d0d --- /dev/null +++ b/themes/bulaksu/zira/widgets/topmenu.php @@ -0,0 +1,38 @@ +
    + +
    \ No newline at end of file diff --git a/themes/bulaksu/zira/xml/rss.php b/themes/bulaksu/zira/xml/rss.php new file mode 100644 index 0000000..c16c30a --- /dev/null +++ b/themes/bulaksu/zira/xml/rss.php @@ -0,0 +1,33 @@ +'; ?> + + + +<?php echo Zira\Helper::html($title); ?> + + + + + +<?php echo Zira\Helper::html($title); ?> + + + +Zira CMS + + + +<?php echo Zira\Helper::html($item['title']) ?> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/themes/bulaksu/zira/xml/sitemap-index.php b/themes/bulaksu/zira/xml/sitemap-index.php new file mode 100644 index 0000000..dc2c7eb --- /dev/null +++ b/themes/bulaksu/zira/xml/sitemap-index.php @@ -0,0 +1,9 @@ +'; ?> + + + + + + + + \ No newline at end of file diff --git a/themes/bulaksu/zira/xml/sitemap.php b/themes/bulaksu/zira/xml/sitemap.php new file mode 100644 index 0000000..5fc9d05 --- /dev/null +++ b/themes/bulaksu/zira/xml/sitemap.php @@ -0,0 +1,12 @@ +'; ?> + + +$url): ?> + + +weekly +0.8 + + + + diff --git a/themes/bulaksu/zira/yandex-map.php b/themes/bulaksu/zira/yandex-map.php new file mode 100644 index 0000000..c91a7a2 --- /dev/null +++ b/themes/bulaksu/zira/yandex-map.php @@ -0,0 +1,53 @@ + + + + + +
    + + + + + + + diff --git a/themes/default/assets/css/desk.css b/themes/default/assets/css/desk.css new file mode 100644 index 0000000..cf2c3ff --- /dev/null +++ b/themes/default/assets/css/desk.css @@ -0,0 +1,790 @@ +#dashpanel-container { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 14px; + width: 100%; + height: 40px; + position: fixed; + top: 0; + left: 0; + z-index: 999; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +#dashpanel-container .navbar { + min-height: 40px; + margin-bottom: 0px; + border-radius: 0px; +} +#dashpanel-container .navbar.disabled { + background: #F2D2BB; + animation: blinker 1s linear infinite; +} +@keyframes blinker { + 50% { background: #fff; } +} +#dashpanel-container .navbar-nav li a { + padding-top: 10px; + padding-bottom: 10px; +} +#dashpanel-container .navbar-brand { + height: 40px; + padding: 10px 15px; +} +#dashpanel-container .dropdown-menu li a { + padding-top: 5px; + padding-bottom: 5px; +} +#dashpanel-container .navbar-toggle { + margin-top: 2px; + margin-bottom: 2px; +} +body { + padding-top: 42px; +} +body.dashboard-window-resizing { + cursor: nwse-resize; +} +body.dashboard-window-sidebar-resizing { + cursor: ew-resize; +} +#dashpanel-container .navbar-brand img { + display: inline-block; + vertical-align: baseline; + margin-right: 2px; +} +.dashboard-window { + position: fixed; + top: 100px; + left: 100px; + width: 400px; + height: 300px; + min-width: 70px; + min-height: 70px; + background-color: #e6e6e6; + border: 1px solid #cccccc; + box-shadow: 0px 0px 4px rgba(85, 70, 113, 0.41), inset 0px 0px 3px #ffffff; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + z-index: 999; + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 14px; + color: #080808; + transition: background-color 50ms linear, box-shadow 50ms linear; + /* + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + */ +} +.dashboard-window-focused { + background-color: #f9f9f9; + box-shadow: 0px 0px 4px rgba(85, 70, 113, 0.41), 0px 0px 3px #FFF inset; +} +.dashboard-window-disabled { + background-color: #E7DDE6; +} +.dashboard-window-maximized { + border-radius: 0px; +} +.dashboard-window-minimized { + min-width: 0; + min-height: 0; + overflow: hidden; + background-color: #F2EBF9; + box-shadow: 0px 0px 4px #E5DFF3, 0px 0px 3px #FFF inset; +} +.dashboard-window-moving { + box-shadow: none; + border: 1px solid #97CFE9; +} +.dashboard-windows-overlay { + position: fixed; + left: 0px; + top: 0px; + width: 100%; + height: 100%; + background-color: rgba(139, 117, 189, 0.1); + z-index: 998; +} +.dashboard-window a:link, +.dashboard-window a:visited { + text-decoration: none; + outline: none; +} +.dashboard-window a:hover { + text-decoration: none; +} +.dashboard-window a img { + border: none; +} +.dashboard-window .dashboard-window-header { + position: relative; + width: 100%; + height: 30px; + border-bottom: 1px solid #eeeeee; + overflow: hidden; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.dashboard-window .dashboard-window-menu { + position: relative; + width: 100%; + height: 24px; + border-top: 1px solid #ffffff; + border-bottom: 1px solid #eeeeee; + background-color: #F4F5F8; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.dashboard-window .dashboard-window-sidebar { + position: relative; + float: left; + width: 180px; + height: 230px; + border-top: 1px solid #efefef; + border-bottom: 1px solid #eeeeee; + background-color: #D1D6E9; + overflow: auto; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.dashboard-window-focused .dashboard-window-sidebar { + border-top: 1px solid #ffffff; +} +.dashboard-window .dashboard-window-content { + position: relative; + width: auto; + height: 230px; + margin-left: 180px; + border-top: 1px solid #efefef; + border-bottom: 1px solid #eeeeee; + background-color: #ffffff; + overflow: auto; + transition: background-color 100ms linear; +} +.dashboard-window-focused .dashboard-window-content { + border-top: 1px solid #ffffff; +} +.dashboard-window-nosidebar .dashboard-window-content { + margin-left: 0px; +} +.dashboard-window-disabled .dashboard-window-content { + background-color: #F2EAF0; +} +.dashboard-window .dashboard-window-noselect-content { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.dashboard-window .dashboard-window-footer { + position: relative; + width: 100%; + height: 16px; + border-top: 1px solid #efefef; + overflow: hidden; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.dashboard-window-focused .dashboard-window-footer { + border-top: 1px solid #ffffff; +} +.dashboard-window .dashboard-window-header .dashboard-window-title { + display: block; + margin-left: 80px; + margin-right: 80px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + font-weight: bold; + text-align: center; + line-height: 30px; + cursor: default; + color: #99A7A3; + text-shadow: 1px 1px 1px #ffffff; +} +.dashboard-window-focused .dashboard-window-header .dashboard-window-title { + color: #645A69; +} +.dashboard-window-animating .dashboard-window-header .dashboard-window-title { + display: none; +} +.dashboard-window-minimized .dashboard-window-header, +.dashboard-window-minimized .dashboard-window-header .dashboard-window-title { + cursor: pointer; +} +.dashboard-window-minimized .dashboard-window-header .dashboard-window-title { + margin-left: 20px; + margin-right: 20px; + color: #4f494d; +} +.dashboard-window .dashboard-window-footer .dashboard-window-resizer { + position: absolute; + top: 0px; + right: 0px; + width: 14px; + height: 14px; + background-image: url(../images/dash-window-buttons-slice.png); + background-repeat: no-repeat; + background-position: 0 0; + cursor: nwse-resize; +} +.dashboard-window-noresize .dashboard-window-footer .dashboard-window-resizer, +.dashboard-window-maximized .dashboard-window-footer .dashboard-window-resizer, +.dashboard-window-minimized .dashboard-window-footer .dashboard-window-resizer, +.dashboard-window-animating .dashboard-window-footer .dashboard-window-resizer, +.dashboard-window-moving .dashboard-window-footer .dashboard-window-resizer { + visibility: hidden; +} +.dashboard-window .dashboard-window-content .dashboard-sidebar-resizer { + position: absolute; + top: 0px; + left: 0px; + width: 4px; + height: 230px; + background-image: url(../images/dash-window-buttons-slice.png); + background-repeat: repeat-y; + background-position: -78px 0px; + cursor: ew-resize; +} +.dashboard-window .dashboard-window-header a.dashboard-window-close-button:link, +.dashboard-window .dashboard-window-header a.dashboard-window-close-button:visited { + position: absolute; + display: block; + width: 16px; + height: 16px; + left: 7px; + top: 7px; + text-decoration: none; + background-image: url(../images/dash-window-buttons-slice.png); + background-repeat: no-repeat; + background-position: -16px 0px; +} +.dashboard-window .dashboard-window-header a.dashboard-window-close-button:hover { + background-position: -16px -16px; +} +.dashboard-window .dashboard-window-header a.dashboard-window-maximize-button:link, +.dashboard-window .dashboard-window-header a.dashboard-window-maximize-button:visited { + position: absolute; + display: block; + width: 16px; + height: 16px; + left: 45px; + top: 7px; + text-decoration: none; + background-image: url(../images/dash-window-buttons-slice.png); + background-repeat: no-repeat; + background-position: -48px 0px; +} +.dashboard-window .dashboard-window-header a.dashboard-window-maximize-button:hover { + background-position: -48px -16px; +} +.dashboard-window .dashboard-window-header a.dashboard-window-minimize-button:link, +.dashboard-window .dashboard-window-header a.dashboard-window-minimize-button:visited { + position: absolute; + display: block; + width: 16px; + height: 16px; + left: 26px; + top: 7px; + text-decoration: none; + background-image: url(../images/dash-window-buttons-slice.png); + background-repeat: no-repeat; + background-position: -32px 0px; +} +.dashboard-window .dashboard-window-header a.dashboard-window-minimize-button:hover { + background-position: -32px -16px; +} +.dashboard-window-animating .dashboard-window-sidebar, +.dashboard-window-moving .dashboard-window-sidebar, +.dashboard-window-minimized .dashboard-window-sidebar { + overflow: hidden; +} + +.dashboard-window-animating .dashboard-window-content, +.dashboard-window-minimized .dashboard-window-content { + overflow: hidden; +} +.dashboard-window .dashboard-window-menu .dropdown { + margin-right: 24px; +} +.dashboard-window .dashboard-window-menu ul.dashboard-window-menu-list { + list-style-type: none; + display: block; + margin: 0px; + padding: 0px; + height: 24px; +} +.dashboard-window-animating .dashboard-window-menu ul.dashboard-window-menu-list { + display: none; +} +.dashboard-window .dashboard-window-menu ul.dashboard-window-menu-list li.dashboard-window-menu-list-item { + display: inline-block; + vertical-align: top; + position: relative; +} +.dashboard-window .dashboard-window-menu ul.dashboard-window-menu-list li.dashboard-window-menu-list-item a.dashboard-window-menu-list-item-link:link, +.dashboard-window .dashboard-window-menu ul.dashboard-window-menu-list li.dashboard-window-menu-list-item a.dashboard-window-menu-list-item-link:visited { + display: block; + height: 24px; + line-height: 24px; + text-decoration: none; + color: #404347; + text-shadow: 1px 1px 1px #ffffff; + font-size: 14px; + padding: 0px 14px; +} +.dashboard-window .dashboard-window-menu ul.dashboard-window-menu-list li.dashboard-window-menu-list-item a.dashboard-window-menu-list-item-link:hover, +.dashboard-window .dashboard-window-menu ul.dashboard-window-menu-list li.dashboard-window-menu-list-item.open a.dashboard-window-menu-list-item-link { + color: #FFFFFF; + text-shadow: none; + background-color: #9eaeb4; +} +.dashboard-window .dashboard-window-menu ul.dashboard-window-menu-list li.dashboard-window-menu-list-item .dropdown-menu { + margin: 0px; + border-top-left-radius: 0px; + border-top-right-radius: 0px; + font-size: 14px; +} +.dashboard-window .dashboard-window-toolbar { + height: 50px; + position: relative; + border-top: 1px solid #ffffff; + border-bottom: 1px solid #eeeeee; + background-color: #eee; + overflow: hidden; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.dashboard-window .dashboard-window-toolbar .navbar { + margin: 0px; + border: none; +} +.dashboard-window .dashboard-window-toolbar .navbar-form { + width: auto; + padding-top: 0px; + padding-bottom: 0px; + margin-right: 0px; + margin-left: 0px; + border: 0px none; + box-shadow: none; +} +.dashboard-window-animating .dashboard-window-toolbar .navbar { + display: none; +} +.dashboard-window .dashboard-window-toolbar .navbar .navbar-left { + float: left !important; + margin-left: -15px; +} +.dashboard-window .dashboard-window-toolbar .navbar .navbar-right { + float: right !important; + margin-right: -15px; +} +.dashboard-window .dashboard-window-toolbar .navbar input[type=text].disabled { + background-color: #EEE; +} +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper { + margin: 10px; + font-size: 15px; + color: #564C60; + text-shadow: 0px 1px 1px #FFF; + white-space: nowrap; +} +.dashboard-window-animating .dashboard-window-sidebar .dashboard-sidebar-content-wrapper { + display: none; +} +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper div, +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper span { + display: block; + padding: 5px 14px; + font-weight: bold; +} +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper .disabled { + color: #9B979E; +} +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper span.glyphicon { + display: inline-block; + padding: 0px; +} +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper a:link, +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper a:visited { + display: block; + padding: 5px 14px; + color: #564C60; + font-weight: normal; + text-shadow: 0px 1px 1px #FFF; + text-decoration: none; + text-overflow: ellipsis; + overflow: hidden; +} +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper a:hover, +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper a.active { + background-color: #94AEC2; + color: #FBFBFB; + text-shadow: 0px 1px 1px #5C7D92; + border-radius: 5px; + box-shadow: 0px 0px 7px #768EA7 inset; +} +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper a.disabled:link, +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper a.disabled:visited { + color: #9B979E; +} +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper a.disabled:hover { + background: none; + color: #9B979E; + text-shadow: 0px 1px 1px #FFF; + border-radius: 0; + box-shadow: none; +} +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper span.devider { + height: 1px; + border-bottom: 1px solid #EDEDF6; + border-top: 1px solid #B3B6D1; + padding: 0px; + margin: 7px 14px; +} +.dashboard-window .dashboard-window-sidebar .dashboard-sidebar-content-wrapper ul { + list-style-type: none; + margin: 0px; + padding: 0px; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper { + margin: 0px; + padding: 0px 4px; + color: #000000; + text-shadow: none; + font-size: 14px; + white-space: normal; +} +.dashboard-window .dashboard-window-content .dashboard-body-full-content-wrapper { + padding: 0px; + height: 100%; + overflow: hidden; +} +.dashboard-window-animating .dashboard-window-content .dashboard-body-content-wrapper { + display: none; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper a:link, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper a:visited { + color: #3C3F57; + text-shadow: none; + text-decoration: none; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper a:hover, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper a.active { + text-decoration: underline; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper .dropdown-menu a:hover, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper .dropdown-menu a.active { + text-decoration: none; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper a.disabled:link, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper a.disabled:visited, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper a.inactive:link, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper a.inactive:visited { + color: #BDBDBD; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul { + list-style-type: none; + margin: 0px; + padding: 0px; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-grid li { + display: inline-block; + vertical-align: top; + margin: 2px; + text-align: center; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-grid li a:link, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-grid li a:visited { + display: block; + padding: 13px; + width: 86px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + font-size: 13px; + cursor: default; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-grid li a:hover, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-grid li a.active { + background-color: #F3F5F9; + box-shadow: 0px 0px 3px #E0E1F8 inset; + text-decoration: none; + border-radius: 7px; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-grid li a.active { + background-color: #C9D8F8; + box-shadow: 0px 0px 3px #D3D4F5 inset; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-grid li img, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-grid .dashwindow-content-icon { + display: block; + width: 60px; + height: 60px; + border: none; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-list li { + display: block; + margin: 0px; + text-align: left; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-list li.odd { + background-color: #F8F1FB; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-list li a:link, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-list li a:visited { + width: 100%; + line-height: 60px; + padding: 2px 13px; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-list li a:hover, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-list li a.active { + border-radius: 0; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-list li img, +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper ul.dashwindow-content-list .dashwindow-content-icon { + float: left; + margin-right: 10px; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper .dashwindow-content-icon-html { + background: url(../images/dash-window-buttons-slice.png) no-repeat 0px -277px; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper .dashwindow-content-icon-txt { + background: url(../images/dash-window-buttons-slice.png) no-repeat 0px -217px; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper .dashwindow-content-icon-archive { + background: url(../images/dash-window-buttons-slice.png) no-repeat 0px -152px; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper .dashwindow-content-icon-file { + background: url(../images/dash-window-buttons-slice.png) no-repeat 0px -32px; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper .dashwindow-content-icon-folder { + background: url(../images/dash-window-buttons-slice.png) no-repeat 0px -92px; +} +.dashboard-window .dashboard-window-content .dashboard-body-content-wrapper .dashwindow-content-icon-blank { + background: none; +} +.dashboard-window .dashboard-window-footer .dashboard-footer-content-wrapper { + margin: 0px 10px; + color: #9F9F9F; + text-shadow: 0px 1px 1px #ffffff; + font-size: 12px; + line-height: 12px; + white-space: nowrap; +} +.dashboard-window-animating .dashboard-window-footer .dashboard-footer-content-wrapper, +.dashboard-window-moving .dashboard-window-footer .dashboard-footer-content-wrapper { + visibility: hidden; +} +.dashboard-window .dashboard-window-loader { + display: none; + position: absolute; + right: 4px; + top: 4px; + width: 16px; + height: 16px; + background: url(../images/dash-window-loader.gif) no-repeat 0 0; +} +.dashboard-window-loading .dashboard-window-loader { + display: block; +} +.dashboard-window-contextmenu { + position: fixed; + display: none; +} +.dashboard-window-contextmenu.open { + display: block; +} +.dashboard-window-highlight { + border: 1px solid #cdafff; + box-shadow: 0px 0px 20px #AA83F6, inset 0px 0px 3px #ffffff; + background-color: #D7CAFB; +} +.dashboard-window-highlight .dashboard-window-header .dashboard-window-title { + color: #644484; + text-shadow: 0px 1px 1px #ffffff; +} +.dashboard-window-blink { + border: 1px solid #cdafff; + box-shadow: 0px 0px 20px #AA83F6, inset 0px 0px 3px #ffffff; + background-color: #D7CAFB; +} +.dashboard-window .mce-panel { + border-color: #eeeeee !important; + background-color: #F8F8F8 !important; +} +.dashboard-window .mce-btn { + background-color: #F8F8F8 !important; +} +.mce-window { + border-radius: 20px; + overflow: hidden; + box-shadow: 0px 0px 10px #777777; + padding: 10px 20px !important; +} +.mce-window .mce-window-head { + border: none !important; +} +.mce-window .mce-foot { + border: none !important; +} +.mce-window .mce-btn { + border-radius: 6px; +} +.mce-window .mce-listbox { + border-radius: 0px; +} +.dashboard-window .dash-window-form { + padding: 0px 0px; +} +.dashboard-window .dash-window-form .form-group { + margin: 0px; + padding: 14px 0px; +} +.dashboard-window .dash-window-form .control-label { + text-align: left; +} +.dashboard-window .dash-window-form .form-group.odd { + background-color: #F8F1FB; +} +.dashboard-window .dashboard-glyphicon-pointer { + cursor: pointer; +} +.system-warning { + color: #ff397b; +} +.system-ok { + color: #298069; +} + +/** Dashboard **/ +html.dashboard, +body.dashboard, +body.dashboard #main-wrapper, +body.dashboard #dashboard-wrapper, +body.dashboard #dashboard-canvas-wrapper, +body.dashboard #dashboard-sidebar { + height: 100%; +} +body.dashboard #main-wrapper { + min-width: 800px; + background: #efebf0; + background: -moz-linear-gradient(top, #efebf0 0%, #dfd1f0 100%); + background: -webkit-linear-gradient(top, #efebf0 0%,#dfd1f0 100%); + background: linear-gradient(to bottom, #efebf0 0%,#dfd1f0 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#efebf0', endColorstr='#dfd1f0',GradientType=0 ); +} +body.dashboard #dashboard-wrapper { + background: url(../images/dash-pattern.png) repeat 0 0; +} +body.dashboard #dashboard-canvas-wrapper { + background: url(../images/dash-wallpaper.png) no-repeat 50% 50%; + position: relative; + overflow: hidden; +} +body.dashboard #dashboard-sidebar { + width: 280px; + float: right; + background: #ddd; + background: rgba(246, 238, 244, 0.4); + border-left: 1px solid #F8F4F4; + box-shadow: 0px 0px 1px #AEAEAE, 0px 0px 100px #ECF2E2 inset; +} +body.dashboard #remote-clock-wrapper { + display: none; + position: absolute; + width: 230px; + height: 230px; + top: 25px; + right: 25px; +} +body.dashboard #remote-clock-wrapper canvas { + display: block; + margin: 0px; +} +body.dashboard #dash-version { + position: absolute; + right: 20px; + bottom: 20px; + color: #240036; + text-shadow: 1px 1px 0px #fff; + font-size: 12px; +} +body.dashboard #memory-stick-wrapper { + position: absolute; + left: 20px; + top: 20px; + width: 300px; + height: 300px; + background: url(../images/dash-memo-stick.png) no-repeat 0 0; +} +body.dashboard #memory-stick-wrapper textarea { + border: none; + background: none; + width: 230px; + height: 220px; + resize: none; + padding: 0px; + margin: 40px 0px 0px 30px; + outline: none; +} +body.dashboard #memory-stick-save { + display: none; + text-align: right; + position: absolute; + bottom: 14px; + right: 14px; +} +body.dashboard #memory-stick-save span { + cursor: pointer; +} +body.dashboard .dashboard-notification { + display: none; + position: fixed; + width: 500px; + margin: 0px auto; + font-size: 16px; + padding: 20px; + color: #CAC6ED; + background-color: #515769; + border-radius: 12px; + box-shadow: 0px 0px 2px #7F6A8F; + cursor: pointer; + text-shadow: 1px 1px 0px #3E354E; +} +body.dashboard .dashboard-notification .dashboard-notification-close { + float: right; + color: #E4A691; + cursor: pointer; + font-size: 120%; +} \ No newline at end of file diff --git a/themes/default/assets/css/editor.css b/themes/default/assets/css/editor.css new file mode 100644 index 0000000..997f43b --- /dev/null +++ b/themes/default/assets/css/editor.css @@ -0,0 +1,72 @@ +body { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 16px; +} +h1 { + font-size: 30px; +} +h2 { + font-size: 26px; +} +h3 { + font-size: 22px; +} +h4 { + font-size: 18px; +} +h5 { + font-size: 14px; +} +h6 { + font-size: 10px; +} +p { + margin: 0px; +} +a:link, +a:visited { + color: #1b6d85; + text-decoration: none; +} +a:hover, +a:active, +a.active { + text-decoration: underline; +} +.image { + max-width:100%; + height:auto; + display: inline-block; + vertical-align: top; + margin: 0px 20px 20px 0px; +} +blockquote { + background-color: #e5e4fe; + margin: 0px 0px 10px 0px; + padding: 10px; +} +pre { + color: #BABABA; + background: #2B2B2B none repeat scroll 0% 0%; + padding: 10px; + margin: 0px 0px 10px 0px; +} +code { + padding: 0px; + display: block; + padding: 2px 0px 2px 10px; + margin: 0px; + border-left: 3px solid #D5C5CA; + border-radius: 0px; + color: #c7254e; + background-color: #f9f2f4; +} +q { + display: block; + color: #858D93; + padding: 2px 0px 2px 10px; + margin: 0px; + border-left: 3px solid #C5D0D8; + background-color: #F8F8F8; + border-radius: 0px; +} \ No newline at end of file diff --git a/themes/default/assets/css/main.css b/themes/default/assets/css/main.css new file mode 100644 index 0000000..c5d735b --- /dev/null +++ b/themes/default/assets/css/main.css @@ -0,0 +1,1497 @@ +@font-face { + font-family: 'Roboto'; + src: url(../fonts/Roboto-Regular.ttf); +} +html, body { + height: 100%; +} +body { + font-family: Roboto,Arial,sans-serif; + font-size: 16px; + background-color: #F6F6F6; +} +h1 { + font-size: 28px; +} +h2 { + font-size: 26px; +} +h3 { + font-size: 22px; +} +h4 { + font-size: 18px; +} +h5 { + font-size: 14px; +} +h6 { + font-size: 10px; +} +p { + margin: 0px; +} +a:link, +a:visited { + color: #1C4F74; + text-decoration: none; +} +a:hover, +a:active, +a.active { + text-decoration: underline; + color: #337AB7; +} +a.external-url { + color: #337AB7 !important; +} +a.btn-primary { + color: #FFF; +} +dt { + font-weight: normal; +} +#main-container-wrapper { + height: 100%; +} +#main-container { + min-height: 100%; +} +/** bootstrap **/ +.container { + +} +.breadcrumb { + padding: 10px 15px; + background-color: #ececec; +} +.page-header { + border-bottom: 1px solid #DBDCEA; +} +.navbar-default { + background-image: -webkit-linear-gradient(top, #fff 0, #F0EDF5 100%); + background-image: -o-linear-gradient(top, #fff 0, #F0EDF5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#F0EDF5)); + background-image: linear-gradient(to bottom, #fff 0, #F0EDF5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffF0EDF5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} +.navbar-default .navbar-nav li a { + color: #555; +} +.dropdown-menu { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 14px; +} +.form-panel { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 14px; +} +.btn-default { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + text-shadow:0 1px 0 #fff; + background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%); + background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%); + background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0)); + background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); + filter:progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat:repeat-x; + border-color:#dbdbdb; + border-color:#ccc; +} +.btn-primary { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + background-color: #5E7987; + background-image:-webkit-linear-gradient(top,#5E7987 0, #3D475C 100%); + background-image:-o-linear-gradient(top,#5E7987 0,#3D475C 100%); + background-image:-webkit-gradient(linear,left top,left bottom,from(#5E7987),to(#3D475C)); + background-image:linear-gradient(to bottom,#5E7987 0,#3D475C 100%); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5E7987', endColorstr='#ff3D475C', GradientType=0); + filter:progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat:repeat-x; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.btn-primary:hover, .btn-primary:focus { + background-color: #3D475C; +} +.btn-primary.active, .btn-primary:active, .open > .dropdown-toggle.btn-primary { + color: #FFF; + background-color: #3D475C; + border-color: #324465; +} +.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover { + color:#fff; + background-color: rgb(60, 67, 78); + border-color: #1b2e40 +} +.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover { + background-color: #3D475C; + border-color: #324465; +} +.zira-confirm-modal .modal-content { + background-color: #959C89; +} +.zira-confirm-modal .modal-header { + background-color: #778A75; + border-bottom: 1px solid #626B5A; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + color: #FFFFFF; +} +.zira-confirm-modal .modal-body { + border-bottom: 1px solid #DED8BA; + border-top: 1px solid #ffffff; + background-color: #F9F7EB; +} +.zira-confirm-modal .modal-footer { + border-top: 1px solid #ffffff; + background-color: #F9F7EB; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; +} +.zira-error-modal .modal-content { + background-color: #8C6781; +} +.zira-error-modal .modal-header { + background-color: #AA4372; + border-bottom: 1px solid #7E1166; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + color: #fff; +} +.zira-error-modal .modal-body { + border-bottom: 1px solid #E9D7E4; + border-top: 1px solid #ffffff; + background-color: #FBF7FA; +} +.zira-error-modal .modal-footer { + border-top: 1px solid #ffffff; + background-color: #FBF7FA; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; +} +.zira-message-modal .modal-content { + background-color: #5B7EA1; +} +.zira-message-modal .modal-header { + background-color: #357BA1; + border-bottom: 1px solid #064480; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + color: #fff; +} +.zira-message-modal .modal-body { + border-bottom: 1px solid #CBD7DA; + border-top: 1px solid #ffffff; + background-color: #F6F7F8; +} +.zira-message-modal .modal-footer { + border-top: 1px solid #ffffff; + background-color: #F6F7F8; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; +} +.zira-prompt-modal .modal-content { + background-color: #899C9C; +} +.zira-prompt-modal .modal-header { + background-color: #7D8892; + border-bottom: 1px solid #5A656B; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + color: #FFFFFF; +} +.zira-prompt-modal .modal-body { + border-bottom: 1px solid #DED8BA; + border-top: 1px solid #ffffff; + background-color: #F9F7EB; +} +.zira-prompt-modal .modal-footer { + border-top: 1px solid #ffffff; + background-color: #F9F7EB; + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; +} +/** user profile **/ +.user-profile-photo { + float: left; + border: 5px solid #CCCCCC; + padding: 5px; + margin-right: 10px; + overflow: hidden; + border-radius: 3px; + box-shadow: 0px 0px 2px #cccccc; + background-color: #FFFFFF; +} +.user-head { + margin-bottom: 10px; +} +.user-profile h1 { + margin: 0px 0px 5px; +} +.user-profile h2 { + margin: 60px 0px 10px; + padding: 10px 0px; + border-bottom: 1px solid #E4E4E4; +} +.user-button .user-profile-links { + float: right; + margin-top: -40px; +} +.user-black-list-link .if-blocked { + display: none; +} +.user-black-list-link.blocked .if-blocked { + display: inline; +} +.user-black-list-link.blocked .if-not-blocked { + display: none; +} +#dashpanel-fixed-button:link, +#dashpanel-fixed-button:visited { + display: block; + position: fixed; + height: 42px; + top: 0px; + left: 8px; + z-index: 999; + font-size: 18px; + color: #444444; + text-decoration: none; + background-image: -webkit-linear-gradient(top, #fff 0, #F0EDF5 100%); + background-image: -o-linear-gradient(top, #fff 0, #F0EDF5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#F0EDF5)); + background-image: linear-gradient(to bottom, #fff 0, #F0EDF5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffF0EDF5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + padding: 8px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + box-shadow: 0px 0px 4px #e3e3e3; +} +#dashpanel-fixed-button:hover { + color: #000000; + box-shadow: 0px 0px 4px #d3d3d3; +} +#dashpanel-fixed-button img { + display: block; + float: left; + margin-top: 4px; + margin-right: 2px; +} +/** header **/ +header { + min-height: 210px; + position: relative; + margin-bottom: 40px; + background-color: #2F4E6C; + color: #333; + border-top: 4px solid #1EBD8A; +} +header .header-top-item { + float: right; + margin: 0px 60px 0px 20px; +} +header .header-top-buttons { + padding: 10px 0px 0px; + color: #fff; + font-size: 14px; +} +header .header-top-buttons .header-top-button-text, +header .header-top-buttons .header-top-button { + float: left; + margin-right: 10px; +} +header .header-top-buttons .header-top-button { + margin-right: 5px; +} +header .header-top-buttons .header-top-button .social-btn { + box-shadow: none; + margin-top: -5px; +} +ul#user-menu { + list-style-type: none; + display: block; + margin: -4px 60px 0px 20px; + padding: 0px; + float: right; + background-color: #f6f6f6; + border-radius: 0px 0px 10px 10px; +} +ul#user-menu.authorized { + +} +ul#user-menu li.menu-item { + display: block; + float: left; + position: relative; + margin: 0px; + color: #333; +} +ul#user-menu li.menu-item.open { + +} +ul#user-menu li.menu-item-separator { + margin: 0px 0px; + padding: 8px 0px; +} +ul#user-menu li.menu-item-separator:after { + content: '\2022'; +} +ul#user-menu li.menu-item a.menu-link:link, +ul#user-menu li.menu-item a.menu-link:visited { + display: block; + padding: 8px 14px; + color: #333; + font-size: 15px; +} +ul#user-menu li.menu-item a.menu-link:hover, +ul#user-menu li.menu-item a.menu-link.active { + color: #000; + text-decoration: none; +} +ul#user-menu li.menu-item.open a.menu-link { + color: #333; +} +ul#language-switcher { + list-style-type: none; + display: block; + padding: 0px; + margin: 0px 60px 0px 20px; + height: 30px; + float: right; +} +ul#language-switcher li { + float: left; + margin: 0px 0px 0px 1px; +} +ul#language-switcher li a:link, +ul#language-switcher li a:visited { + display: block; + font-size: 13px; + color: #ececec; + padding: 5px 10px; + text-shadow: 1px 1px 0px #0A3241; +} +ul#language-switcher li a:hover, +ul#language-switcher li a.active { + color: #fff; + text-decoration: none; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; +} +ul#language-switcher li a.active { + background-color: #52879C; + color: #FFF; + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.12) inset; +} +#site-logo-wrapper { + position: relative; + clear: both; + margin-left: 15px; + margin-bottom: 30px; +} +#site-logo-wrapper a#site-logo:link, +#site-logo-wrapper a#site-logo:visited { + display: inline-block; + color: #ececec; + margin: 0px; + text-decoration: none; + text-shadow: 1px 1px 0px #0A3241; + height: 80px; +} +#site-logo-wrapper a#site-logo:hover { + color: #fff; +} +#site-logo-wrapper a#site-logo img { + border: none; + vertical-align: middle; + margin-right: 10px; + max-width: 200px; + max-height: 80px; + + /*-webkit-filter: hue-rotate(330deg);*/ + /*filter: hue-rotate(330deg);*/ +} +#site-logo-wrapper a#site-logo span { + font-size: 30px; + vertical-align: middle; +} +#site-logo-wrapper #site-slogan { + display: inline-block; + white-space: nowrap; + vertical-align: bottom; + color: #ECECEC; + text-shadow: 1px 1px 0px #0A3241; +} +#top-menu-wrapper { + margin: 50px 15px 0px; + clear: both; +} +#top-menu-wrapper nav { + background: none; + background-color: #F6F6F6; + margin-bottom: 0px; + border-radius: 10px 10px 0px 0px; + box-shadow: none; + border: none; +} +#top-menu-wrapper .navbar-default .navbar-nav > .active { + margin-top: -4px; + border-top: 4px solid #1EBD8A; +} +#top-menu-wrapper .navbar-default .navbar-nav > .active > a, +#top-menu-wrapper .navbar-default .navbar-nav > .open > a { + background:none; + box-shadow: none; + color: #000; +} +/** content **/ +.image { + max-width:100%; + height:auto; + display: inline-block; + vertical-align: top; + margin: 0px 18px 18px 0px; + border: 1px solid #EEEEEE; + border-radius: 3px; + box-shadow: 0px 0px 2px #eeeeee; +} +.image-wrapper { + max-width:100%; + display: inline-block; + vertical-align: top; + margin: 0px 18px 18px 0px; + background: #DDE0E4; + border: 1px solid #EEEEEE; + box-shadow: 0px 0px 2px #eeeeee; +} +.image-wrapper .image { + border: none; + box-shadow: none; + border-radius: 0; + margin: 0; +} +.image-wrapper .image-description { + color: #5d5b6b; + font-size: 12px; + text-align: center; + padding: 10px 0px; +} +.lightbox-image { + cursor: pointer; +} +.block { + margin-bottom: 20px; +} +.block h1, +.block h2, +.block h3, +.block h4, +.block h5, +.block h6 { + margin-top: 0px; +} +.block-image { + max-width:100%; + height:auto; + display: block; + margin: 0px auto 20px; +} +article .article p { + line-height: 26px; +} +article .datetime { + font-style: italic; + color: #888888; + float: left; + margin-right: 20px; +} +article .author { + font-style: italic; + color: #888888; + float: right; + margin-left: 20px; +} +article .article-info { + overflow: hidden; + margin-bottom: 10px; +} +article .article { + margin: 30px 0px; +} +article .rating { + color: #888888; + overflow: hidden; + margin-bottom: 30px; +} +article .rating a.like:link, +article .rating a.like:visited { + position: relative; + z-index: 2; + font-size: 16px; + height: 30px; + line-height: 30px; + background-color: #2F5F87; + background-color: #337AB7; + display: inline-block; + padding: 0px 25px; + color: #FFF; + border-radius: 3px; +} +article .rating a.like:hover { + text-decoration: none; + background-color: #3A67A2; + box-shadow: inset 0px 0px 1px #ffffff; +} +article .rating a.like.active { + text-decoration: none; + background-color: #2C7E72; +} +article .rating a span.glyphicon { + font-size: 20px; + vertical-align: middle; + margin-right: 5px; +} +article .rating .share-wrapper { + position: relative; + z-index: 1; + left: -999px; + display: inline-block; + vertical-align: top; + margin-left: 10px; + transition: left .5s ease; +} +.share-btn-wrapper, +.social-btn-wrapper { + overflow: hidden; +} +.share-btn, +.social-btn { + display: block; + float: left; + width: 28px; + height: 28px; + background-image: url(../images/share-buttons.jpg); + background-repeat: no-repeat; + margin-right: 4px; + border-radius: 3px; + box-shadow: 0px 0px 2px #eeeeee; + text-decoration: none; +} +.share-btn:hover, +.social-btn:hover { + box-shadow: 0px 0px 2px #aaaaaa; +} +article .rating .share-wrapper .share-btn { + margin-top: 1px; +} +.share-btn.gp, +.social-btn.gp { + background-position: 0px 0px; +} +.share-btn.vk, +.social-btn.vk { + background-position: -28px 0px; +} +.share-btn.fb, +.social-btn.fb { + background-position: -56px 0px; +} +.share-btn.tw, +.social-btn.tw { + background-position: -84px 0px; +} +.share-btn.ok, +.social-btn.ok { + background-position: -112px 0px; +} +.oauth-btn { + float: left; + margin-right: 10px; +} +.oauth-btn.social-btn { + margin-top: -6px; + margin-right: 5px; +} +.user-login-form-extra-items { + float: left; +} +.user-login-form-extra-item { + float: left; +} +.gallery-wrapper { + margin: 30px 0px 20px; +} +.gallery { + display: block; + margin: 0px; + padding: 2px; + list-style-type: none; + border: 1px solid #eeeeee; + border-radius: 3px; + color: #ffffff; + overflow: hidden; + box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.15) inset, 0px 1px 5px rgba(0, 0, 0, 0.075); + background-color: #fafafa; + background-color: rgba(250, 250, 250, 0.9); +} +.gallery li { + display: block; + float: left; + margin: 0px; +} +.gallery li a:link, +.gallery li a:visited { + display: block; + margin: 1px; + border: 1px solid #eeeeee; + transition: border .2s; +} +.gallery li a:hover { + border: 1px solid #337AB7; +} +.gallery li img { + display: block; + border: none; +} +.slider { + display: block; + margin: 0px; + padding: 0px; + list-style-type: none; +} +.list { + list-style-type: none; + margin: 20px 0px; + padding: 0px; +} +.list .list-item { + margin-bottom: 20px; + overflow: hidden; + border: 1px solid #eeeeee; + background-color: #FAFAFA; + background-color: rgba(250, 250, 250, 0.9); + border-radius: 3px; + box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.15) inset, 0px 1px 5px rgba(0, 0, 0, 0.075); +} +.list .list-item .list-title-wrapper { + background-color: #F5F5F5; + border-bottom: 1px solid #eeeeee; + padding: 10px 14px; + margin: 0px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} +.list .list-item a.list-title:link, +.list .list-item a.list-title:visited { + font-size: 18px; + margin: 0px 0px 5px; + text-shadow: 1px 1px 0px #ffffff; +} +.list .list-item .list-content-wrapper { + padding: 10px 14px 0px; +} +.list .list-item a.list-thumb:link, +.list .list-item a.list-thumb:visited { + display: block; + text-decoration: none; + float: left; + margin: 0px 10px 10px 0px; + border: 1px solid #EEEEEE; + background-color: #EBE6F0; + padding: 2px; +} +.list .list-item a.list-thumb:hover { + box-shadow: 0px 0px 2px #eeeeee; +} +.list .list-item a.list-thumb img { + border: none; + max-width: 100%; + max-width: none\9; /** ie8 hack **/ + height: auto; +} +.list .list-item .list-info-wrapper { + clear: left; + margin: 10px 0px 0px; + padding: 0px 14px 10px; + font-style: italic; +} +.list .list-item .list-info { + margin-right: 10px; + color: #3F3F3F; +} +.list .list-item .list-info a:link, +.list .list-item .list-info a:visited { + color: #3F3F3F; +} +.list-view-more-wrapper { + margin: 20px 0px; +} +.widget-category-wrapper, +.widget-top-wrapper { + margin-bottom: 20px; +} +/** comments **/ +.comments-wrapper { + margin: 40px 0px; +} +.comment-btn:link, +.comment-btn:visited { + display: block; + float: right; + color: #ffffff; +} +.comments { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + list-style-type: none; + margin: 40px 0px; + padding: 0px; + font-size: 14px; +} +.comments .comments-item { + margin-bottom: 20px; + overflow: hidden; +} +.comments .comments-item-nested-1 { + margin-left: 60px; +} +.comments .comments-item-nested-2 { + margin-left: 120px; +} +.comments .comments-item-nested-3 { + margin-left: 180px; +} +.comments .comments-item-nested-4 { + margin-left: 240px; +} +.comments .comments-item-nested-5 { + margin-left: 300px; +} +.comments .comments-item-nested-6 { + margin-left: 360px; +} +.comments .comments-item-nested-7 { + margin-left: 420px; +} +.comments .comments-item-nested-8 { + margin-left: 480px; +} +.comments .comments-item-nested-9 { + margin-left: 540px; +} +.comments .comments-item-nested-10 { + margin-left: 600px; +} +.comments .comments-item.disabled { + color: #777777; +} +.comments .comments-item .comment-avatar { + max-width: 50px; + height: auto; + display: block; + float: left; + border-radius: 5px; +} +.comments .comments-item .comment-head { + display: block; + margin-left: 60px; +} +.comments .comments-item .comment-text { + display: block; + margin: 5px 0px 5px 60px; + background-color: #EBEEF3; + padding: 14px; + border-radius: 14px; + border: 1px solid #E1E3E4; + box-shadow: inset 0px 0px 10px #E3EBED; +} +.comments .comments-item.disabled .comment-text { + background-color: #E3E3E3; +} +.comments .comments-item .comment-info { + display: block; + margin: 5px 0px 5px 60px; +} +.comments .comments-item .comment-info a:link, +.comments .comments-item .comment-info a:visited { + color: #000000; + text-decoration: none; +} +.comments .comments-item .comment-info a:hover { + color: #474855; + text-decoration: none; +} +.comments .comments-item .comment-info a.comment-like:link, +.comments .comments-item .comment-info a.comment-like:visited { + color: #1d7690; +} +.comments .comments-item .comment-info a.comment-like:hover, +.comments .comments-item .comment-info a.comment-like.active { + color: #114150; +} +.comments .comments-item .comment-info a.comment-dislike:link, +.comments .comments-item .comment-info a.comment-dislike:visited { + color: #a41748; +} +.comments .comments-item .comment-info a.comment-dislike:hover, +.comments .comments-item .comment-info a.comment-dislike.active { + color: #550e2a; +} +.comments-view-more-wrapper { + margin-bottom: 40px; +} +.parse-content code { + padding: 0px; + display: block; + padding: 2px 0px 2px 10px; + margin: 0px; + border-left: 3px solid #D5C5CA; + border-radius: 0px; +} +.parse-content q { + display: block; + color: #858D93; + padding: 2px 0px 2px 10px; + margin: 0px; + border-left: 3px solid #C5D0D8; + background-color: #F8F8F8; + border-radius: 0px; +} +blockquote { + color: #6E7899; + font-size: 100%; + background-color: #E5E9F3; + margin: 0px 0px 18px; + border-left: 4px solid #6E7899; +} +pre { + background-color: #FEFEFE; + border: 1px solid #eee; +} +/** sidebar **/ +.sidebar .page-header { + margin: 0px; + padding-bottom: 4px; +} +.sidebar .widget-category-title { + font-size: 20px; + margin-top: 0px; + text-shadow: 1px 1px 0px #fff; +} +.sidebar .list { + margin: 4px 0px 20px; +} +.sidebar .list .list-item { + margin-bottom: 10px; + overflow: hidden; + border: none; + background: none; + border-radius: 0px; + border-bottom: 1px dashed #eeeeee; + box-shadow: none; +} +.sidebar .list .list-item .list-title-wrapper { + background: none; + border-bottom: none; + padding: 4px 0px; + margin: 0px; + text-overflow: clip; + white-space: normal; + overflow: hidden; +} +.sidebar .list .list-item a.list-title:link, +.sidebar .list .list-item a.list-title:visited { + font-size: 16px; +} +.sidebar .list .list-item .list-content-wrapper { + padding: 4px 0px 0px; + margin-bottom: 10px; +} +.sidebar .list .list-item a.list-thumb:link, +.sidebar .list .list-item a.list-thumb:visited { + /*float: none;*/ + /*display: inline-block;*/ + max-width: 50%; +} +.sidebar .list .list-item a.list-thumb img { + width: 100%\9; /** ie8 hack **/ +} +.sidebar .list .list-item .list-info-wrapper { + padding: 4px 0px; +} +.sidebar .list .list-item .list-info { + display: block; +} +/** secondary menu **/ +#secondary-menu-wrapper { + margin-bottom: 20px; +} +#secondary-menu-wrapper ul li a:link, +#secondary-menu-wrapper ul li a:visited { + background-color: #fafafa; + color: #333333; +} +#secondary-menu-wrapper ul li a:hover { + background-color: #f5f5f5; + color: #337AB7; +} +#secondary-menu-wrapper ul li.active a { + background-color: #337AB7; + color: #ffffff; +} +#secondary-menu-wrapper ul li.parent { + margin-bottom: 10px; +} +#secondary-menu-wrapper ul li.parent a.menu-link { + color: #333333; + background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%); + background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%); + background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2)); + background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); + background-repeat:repeat-x; + -webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075); + box-shadow:inset 0 3px 9px rgba(0,0,0,.075) +} +#secondary-menu-wrapper .secondary-child ul { + margin-top: 2px; +} +#secondary-menu-wrapper .secondary-child ul .menu-link-ico { + margin-right: 2px; +} +#secondary-menu-wrapper .secondary-child ul .menu-link-ico:after { + content: '\203A'; +} +/** search **/ +.search-form-wrapper { + overflow: hidden; +} +.search-form-description { + margin-top: 0px; + margin-bottom: 100px; + font-style: italic; +} +.search-form-wrapper .col-sm-3 { + padding-left: 0px; + padding-right: 0px; +} +.search-simple-form { + display: none; + position: relative; +} +.search-simple-form .search-text-clear { + position: absolute; + top: 11px; + right: 59px; + z-index: 9; + cursor: pointer; +} +.search-simple-form input[type=text] { + padding-right: 20px; +} +.search-simple-form.loading button[type=submit] .glyphicon { + visibility: hidden; +} +#top-menu-container .zira-search-preview-wnd { + position: absolute; + width: 450px; + right: 30px; + top: 52px; + z-index: 99; + background-color: #f9f9f9; + box-shadow: 0px 5px 10px rgba(113, 113, 113, 0.52); +} +.zira-search-preview-wnd .list { + margin: 0px; +} +.zira-search-preview-wnd .list .list-item { + border: none; + border-top: 1px solid #f4f4f4; + border-left: 1px solid #eeeeee; + border-right: 1px solid #eeeeee; + border-bottom: 1px solid #eeeeee; + box-shadow: none; + background-color: #fafafa; + margin-bottom: 0px; + border-radius: 0; + cursor: pointer; +} +.zira-search-preview-wnd .list .list-item:first-child { + border-top: none; +} +.zira-search-preview-wnd .list .list-item:last-child { + border-bottom: 1px solid #dddddd; +} +.zira-search-preview-wnd .list .list-item:hover { + background-color: #FFFFFF; + border-left: 1px solid #C9D3F2; + border-right: 1px solid #C9D3F2; + border-bottom: 1px solid #C9D3F2; +} +.zira-search-preview-wnd .list .list-item .list-title-wrapper { + /**background-color: #EAEAEA;**/ + background-color: #f6f6f6; + padding: 6px 10px; +} +.zira-search-preview-wnd .list .list-item:hover .list-title-wrapper { + background-color: #DDE0E3; + color: #3B4350; +} +.zira-search-preview-wnd .list .list-item a.list-title:link, +.zira-search-preview-wnd .list .list-item a.list-title:visited { + font-size: 16px; + color: #656587; + text-shadow: none; +} +.zira-search-preview-wnd .list .list-item:hover a.list-title:link, +.zira-search-preview-wnd .list .list-item:hover a.list-title:visited { + color: #3B4350; +} +.zira-search-preview-wnd .list .list-item a.list-title:hover { + text-decoration: none; +} +.zira-search-preview-wnd .list .list-item a.list-thumb:link, +.zira-search-preview-wnd .list .list-item a.list-thumb:visited { + margin-bottom: 6px; + padding: 0px; +} +.zira-search-preview-wnd .list .list-item a.list-thumb img { + max-height: 60px; + width: auto; +} +.zira-search-preview-wnd .list .list-item .list-content-wrapper { + padding: 6px 10px; +} +.zira-search-preview-wnd .list .list-item .list-content-wrapper p { + max-height: 60px; + overflow: hidden; + font-size: 14px; +} +/** footer **/ +footer { + min-height: 50px; + position: relative; + margin-top: 40px; + padding: 40px 0px; + border-top: 4px solid #1EBD8A; + background: #33434E; + background: -moz-linear-gradient(top, #33434E 0%, #213F47 100%); + background: -webkit-linear-gradient(top, #33434E 0%,#213F47 100%); + background: linear-gradient(to bottom, #33434E 0%,#213F47 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33434E', endColorstr='#213F47',GradientType=0 ); + box-shadow: 0px 2px 2px #4a6072; +} +footer p { + line-height: 50px; + padding: 0px 15px; + color: #ececec; +} +footer p a:link, +footer p a:visited { + color: #1EB5E1; +} +#footer-menu-wrapper { + margin: 15px 0px 0px; +} +#footer-menu-wrapper ul.menu { + list-style-type: none; + margin: 0px 3px; + padding: 0px; +} +#footer-menu-wrapper ul.menu li.menu-item { + display: inline-block; + margin: 0px 8px; +} +#footer-menu-wrapper ul.menu li.menu-item-separator { + display: inline-block; + margin: 0px; + font-size: 90%; + vertical-align: top; +} +#footer-menu-wrapper ul.menu li.menu-item-separator:after { + /*content: '\22c5';*/ + content: '|'; +} +#footer-menu-wrapper ul.menu li.menu-item a.menu-link:link, +#footer-menu-wrapper ul.menu li.menu-item a.menu-link:visited { + text-decoration: none; + color: #ACB8BA; + padding: 2px 4px; + border-radius: 2px; +} +#footer-menu-wrapper ul.menu li.menu-item a.menu-link:hover, +#footer-menu-wrapper ul.menu li.menu-item a.menu-link.active, +#footer-menu-wrapper ul.menu li.menu-item.active a.menu-link { + text-decoration: none; + color: #ececec; +} +footer a.rss-link:link, +footer a.rss-link:visited { + position: absolute; + bottom: 14px; + right: 14px; + display: block; + width: 20px; + height: 20px; + background: url(../images/rss.png) no-repeat 0 0; + outline: none; +} +.zira-loader-wrapper { + font-style: italic; + display: inline-block; + vertical-align: middle; + margin-left: 10px; +} +.zira-loader { + display: inline-block; + vertical-align: top; + width: 16px; + height: 16px; + background: url(../images/zira-loader.gif) no-repeat 0 0; +} +.search-simple-form .zira-loader { + position: absolute; + top: 9px; + right: 28px; + z-index: 9; +} +a.scroll-top:link, +a.scroll-top:visited { + display: block; + position: fixed; + bottom: 180px; + right: 10px; + width: 32px; + height: 32px; + background: url(../images/up.png) no-repeat 0 0; + opacity: 0; + filter: alpha(opacity=0); + transition: opacity 1s ease; + outline: none; +} +a.scroll-top:hover { + opacity: 1 !important; + filter: alpha(opacity=100); +} +a.scroll-top.visible:link, +a.scroll-top.visible:visited { + opacity: .6; + filter: alpha(opacity=60); +} + +/** home page **/ +.home-category-wrapper { + margin: 40px 0px; +} +.home-category-wrapper .home-category-title, +.home-category-wrapper .home-category-title a:link, +.home-category-wrapper .home-category-title a:visited { + color: #222222; +} +.home-category-wrapper .home-category-title a:hover { + color: #1B6D85; + text-decoration: none; +} +.grid-category-wrapper .list .list-item { + width: 49%; + display: inline-block; + vertical-align: top; + margin-right: 1%; +} +.grid-category-wrapper .list .list-item:nth-child(2) { + margin-right: 0px; +} + +.caret-right { + border-bottom: 4px solid transparent; + border-top: 4px solid transparent; + border-left: 4px solid; + display: inline-block; + width: 0; + height: 0; + vertical-align: middle; + margin-right: 2px; +} +.menu-default { + background: #777 !important; + color: #ffffff !important; +} +.menu-primary { + background: #337AB7 !important; + color: #ffffff !important; +} +.menu-success { + background: #5CB85C !important; + color: #ffffff !important; +} +.menu-info { + background: #5BC0DE !important; + color: #ffffff !important; +} +.menu-warning { + background: #F0AD4E !important; + color: #ffffff !important; +} +.menu-danger { + background: #D9534F !important; + color: #ffffff !important; +} +.menu-default a, +.menu-primary a, +.menu-success a, +.menu-info a, +.menu-warning a, +.menu-danger a { + color: #ffffff !important; + background: none !important; +} + +#sitemap-wrapper { + margin-bottom: 40px; +} +#sitemap-wrapper ul { + list-style-type: none; + margin: 0px; + padding: 0px; + box-shadow: 0px 0px 2px #efefef; + border: 1px solid #eee; + border-radius: 3px; +} +#sitemap-wrapper ul li { + padding: 14px; + margin: 0px; + border-top: 1px solid #fff; + border-bottom: 1px solid #efefef; +} +#sitemap-wrapper ul li:first-child { + border-top: none; +} +#sitemap-wrapper ul li:last-child { + border-bottom: none; +} +#sitemap-wrapper ul li.even { + background-color: #FAFAFA; + background-color: rgba(250, 250, 250, 0.2); +} +#sitemap-wrapper ul li.odd { + background-color: #FFFFFF; + background-color: rgba(255, 255, 255, 0.4); +} +#sitemap-wrapper ul li.menu-item-offset { + padding-left: 310px; +} +#sitemap-wrapper ul li.menu-item-offset-1 { + padding-left: 40px; +} +#sitemap-wrapper ul li.menu-item-offset-2 { + padding-left: 70px; +} +#sitemap-wrapper ul li.menu-item-offset-3 { + padding-left: 100px; +} +#sitemap-wrapper ul li.menu-item-offset-4 { + padding-left: 130px; +} +#sitemap-wrapper ul li.menu-item-offset-5 { + padding-left: 160px; +} +#sitemap-wrapper ul li.menu-item-offset-6 { + padding-left: 190px; +} +#sitemap-wrapper ul li.menu-item-offset-7 { + padding-left: 220px; +} +#sitemap-wrapper ul li.menu-item-offset-8 { + padding-left: 250px; +} +#sitemap-wrapper ul li.menu-item-offset-9 { + padding-left: 280px; +} +#sitemap-wrapper ul li a:link, +#sitemap-wrapper ul li a:visited { + color: #333; +} + +.contacts-wrapper { + overflow: hidden; + margin-bottom: 40px; +} +.contact-image { + max-width: 50%; + height: auto; + float: left; + margin: 0px 20px 0px 0px; + border: 5px solid #CCCCCC; + padding: 5px; + border-radius: 3px; + background-color: #FFFFFF; +} +.contact-name { + margin: 0px 0px 20px; + font-size: 22px; +} +.contact-details { + float: left; +} +.contact-address { + margin: 0px; +} +.contact-info { + margin: 10px 0px 0px; + font-style: italic; +} +.social-contacts { + margin: 10px 0px 0px; +} +#yandex-map, +#google-map { + margin-bottom: 40px; + border: 5px solid #EEEEEE; + box-shadow: 0px 0px 2px #cccccc; + border-radius: 3px; +} +.messages-panel { + overflow: hidden; +} +.messages-panel .navbar { + margin-bottom: 0px; + border-radius: 0; + background: #fefefe; +} +.messages-list li { + border-bottom: 1px solid #ffffff; + border-top: 1px solid #eeeeee; + padding: 10px; + overflow: hidden; +} +.messages-list li.even { + background-color: #fefefe; +} +.messages-list li.odd { + background-color: #fafafa; +} +.messages-list li a:link, +.messages-list li a:visited { + color: #333; +} +.messages-list li.highlight a:link, +.messages-list li.highlight a:visited { + color: #000; + font-weight: bold; +} +.messages-list .message-head { + padding-bottom: 10px; + margin-bottom: 10px; + border-bottom: 1px solid #EEEEEE; +} +.messages-list .message-head .message-date { + float: right; +} +.messages-list .message-avatar { + float: left; +} +.messages-list .message-avatar a img { + display: block; + max-width: 100px; + height: auto; + border-radius: 5px; +} +.messages-list .message-content { + margin-left: 120px; +} +.no-messages-message { + font-style: italic; + margin: 20px 0px 100px; +} +.compose-message-btn { + float: right; +} +.user-messages-resipients-list { + list-style-type: none; + margin: 0px 0px 20px; + padding: 0px; +} +.user-messages-resipients-list li { + display: inline-block; +} +.user-messages-resipients-list li.separator { + margin-right: 10px; +} +.user-messages-resipients-list li.separator:after { + content: ', '; +} +.user-messages-resipients-list li a:link, +.user-messages-resipients-list li a:visited { + color: #555; +} +/** mobile **/ +@media only screen and (max-width: 767px) { + .user-profile h1 { + clear: left; + padding-top: 10px; + } + .user-button .user-profile-links { + float: none; + margin-top: 0px; + } + header { + height: auto; + } + #site-logo-wrapper { + margin: 0px 20px; + } + #site-logo-wrapper a#site-logo:link, + #site-logo-wrapper a#site-logo:visited { + + } + #site-logo-wrapper #site-slogan { + display: block; + text-align: right; + } + header .header-top-item { + display: none; + } + ul#user-menu { + visibility: hidden; + } + #top-menu-wrapper { + margin: 30px 15px 0px; + } + #top-menu-wrapper .navbar-default .navbar-nav > .active { + margin-top: 0px; + border-top: 0px; + } + .grid-category-wrapper .list .list-item { + width: 100%; + display: block; + margin-right: 0px; + } + #top-menu-container .zira-search-preview-wnd { + position: static; + width: 100%; + margin-bottom: 10px; + box-shadow: none; + } + .search-simple-form .search-text-clear { + top: 21px; + } + .search-simple-form .zira-loader { + top: 19px; + } + a.scroll-top { + display: none !important; + } +} +@media (min-width: 768px) { + .search-simple-form { + display: none; + } +} +@media (min-width: 992px) { + .search-simple-form { + display: block; + } +} diff --git a/themes/default/assets/fonts/Roboto-Regular.ttf b/themes/default/assets/fonts/Roboto-Regular.ttf new file mode 100644 index 0000000..8c082c8 Binary files /dev/null and b/themes/default/assets/fonts/Roboto-Regular.ttf differ diff --git a/themes/default/assets/images/dash-memo-stick.png b/themes/default/assets/images/dash-memo-stick.png new file mode 100644 index 0000000..6da9688 Binary files /dev/null and b/themes/default/assets/images/dash-memo-stick.png differ diff --git a/themes/default/assets/images/dash-pattern.png b/themes/default/assets/images/dash-pattern.png new file mode 100644 index 0000000..3ac4bdc Binary files /dev/null and b/themes/default/assets/images/dash-pattern.png differ diff --git a/themes/default/assets/images/dash-wallpaper.png b/themes/default/assets/images/dash-wallpaper.png new file mode 100644 index 0000000..d1da1cd Binary files /dev/null and b/themes/default/assets/images/dash-wallpaper.png differ diff --git a/themes/default/assets/images/dash-window-buttons-slice.png b/themes/default/assets/images/dash-window-buttons-slice.png new file mode 100644 index 0000000..00d97fa Binary files /dev/null and b/themes/default/assets/images/dash-window-buttons-slice.png differ diff --git a/themes/default/assets/images/dash-window-loader.gif b/themes/default/assets/images/dash-window-loader.gif new file mode 100644 index 0000000..4bb5f44 Binary files /dev/null and b/themes/default/assets/images/dash-window-loader.gif differ diff --git a/themes/default/assets/images/gradient.jpg b/themes/default/assets/images/gradient.jpg new file mode 100644 index 0000000..c29c5ec Binary files /dev/null and b/themes/default/assets/images/gradient.jpg differ diff --git a/themes/default/assets/images/rss.png b/themes/default/assets/images/rss.png new file mode 100644 index 0000000..586c822 Binary files /dev/null and b/themes/default/assets/images/rss.png differ diff --git a/themes/default/assets/images/share-buttons.jpg b/themes/default/assets/images/share-buttons.jpg new file mode 100644 index 0000000..de9c925 Binary files /dev/null and b/themes/default/assets/images/share-buttons.jpg differ diff --git a/themes/default/assets/images/up.png b/themes/default/assets/images/up.png new file mode 100644 index 0000000..6f84f98 Binary files /dev/null and b/themes/default/assets/images/up.png differ diff --git a/themes/default/assets/images/zira-loader.gif b/themes/default/assets/images/zira-loader.gif new file mode 100644 index 0000000..c48e97e Binary files /dev/null and b/themes/default/assets/images/zira-loader.gif differ diff --git a/themes/default/dash/button.php b/themes/default/dash/button.php new file mode 100644 index 0000000..e72d540 --- /dev/null +++ b/themes/default/dash/button.php @@ -0,0 +1 @@ +ZiraZira diff --git a/themes/default/dash/layout.php b/themes/default/dash/layout.php new file mode 100644 index 0000000..f0accc7 --- /dev/null +++ b/themes/default/dash/layout.php @@ -0,0 +1,15 @@ + + + + + + + + +renderPanel(); ?> +
    + +
    + + + \ No newline at end of file diff --git a/themes/default/dash/page.php b/themes/default/dash/page.php new file mode 100644 index 0000000..043e6eb --- /dev/null +++ b/themes/default/dash/page.php @@ -0,0 +1,38 @@ +
    +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    + \ No newline at end of file diff --git a/themes/default/dash/panel.php b/themes/default/dash/panel.php new file mode 100644 index 0000000..258e6bd --- /dev/null +++ b/themes/default/dash/panel.php @@ -0,0 +1,73 @@ +'."\r\n"; + echo ''."\r\n"; + echo ''; +} \ No newline at end of file diff --git a/themes/default/error.php b/themes/default/error.php new file mode 100644 index 0000000..43f5923 --- /dev/null +++ b/themes/default/error.php @@ -0,0 +1,8 @@ +
    +

    +

    + +
    + +
    +Zira diff --git a/themes/default/layout-left.php b/themes/default/layout-left.php new file mode 100644 index 0000000..303d667 --- /dev/null +++ b/themes/default/layout-left.php @@ -0,0 +1,46 @@ + + + + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    + + + + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/themes/default/layout-right.php b/themes/default/layout-right.php new file mode 100644 index 0000000..b944ea0 --- /dev/null +++ b/themes/default/layout-right.php @@ -0,0 +1,46 @@ + + + + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + +
    + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/themes/default/layout-wide.php b/themes/default/layout-wide.php new file mode 100644 index 0000000..bdcdb7a --- /dev/null +++ b/themes/default/layout-wide.php @@ -0,0 +1,41 @@ + + + + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/themes/default/layout.php b/themes/default/layout.php new file mode 100644 index 0000000..e733f6b --- /dev/null +++ b/themes/default/layout.php @@ -0,0 +1,51 @@ + + + + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    + + + + +
    + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/themes/default/oauth/fb-comments.php b/themes/default/oauth/fb-comments.php new file mode 100644 index 0000000..541496b --- /dev/null +++ b/themes/default/oauth/fb-comments.php @@ -0,0 +1,7 @@ + +
    +
    + \ No newline at end of file diff --git a/themes/default/oauth/fb-login.php b/themes/default/oauth/fb-login.php new file mode 100644 index 0000000..9a2cd4f --- /dev/null +++ b/themes/default/oauth/fb-login.php @@ -0,0 +1,34 @@ + + + \ No newline at end of file diff --git a/themes/default/oauth/fb-page.php b/themes/default/oauth/fb-page.php new file mode 100644 index 0000000..6ba2b81 --- /dev/null +++ b/themes/default/oauth/fb-page.php @@ -0,0 +1,10 @@ + +
    +
    + \ No newline at end of file diff --git a/themes/default/oauth/vk-comments.php b/themes/default/oauth/vk-comments.php new file mode 100644 index 0000000..a07ac20 --- /dev/null +++ b/themes/default/oauth/vk-comments.php @@ -0,0 +1,12 @@ +
    + \ No newline at end of file diff --git a/themes/default/oauth/vk-group.php b/themes/default/oauth/vk-group.php new file mode 100644 index 0000000..26f6796 --- /dev/null +++ b/themes/default/oauth/vk-group.php @@ -0,0 +1,22 @@ + +
    + + \ No newline at end of file diff --git a/themes/default/oauth/vk-login.php b/themes/default/oauth/vk-login.php new file mode 100644 index 0000000..7ff43e7 --- /dev/null +++ b/themes/default/oauth/vk-login.php @@ -0,0 +1,29 @@ + + + \ No newline at end of file diff --git a/themes/default/oauth/vk-response.php b/themes/default/oauth/vk-response.php new file mode 100644 index 0000000..9330357 --- /dev/null +++ b/themes/default/oauth/vk-response.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/themes/default/page.php b/themes/default/page.php new file mode 100644 index 0000000..1e5bbfa --- /dev/null +++ b/themes/default/page.php @@ -0,0 +1,49 @@ +
    +
    + +<?php echo (!empty($title) ? Zira\Helper::html($title) : '') ?> + + + + + +

    + +

    + + + + + +
    + +
    + + +
    + + + + +
    + + +
    +
    \ No newline at end of file diff --git a/themes/default/screenshot.jpg b/themes/default/screenshot.jpg new file mode 100644 index 0000000..bbcbd1f Binary files /dev/null and b/themes/default/screenshot.jpg differ diff --git a/themes/default/theme.meta b/themes/default/theme.meta new file mode 100644 index 0000000..06c1f5a --- /dev/null +++ b/themes/default/theme.meta @@ -0,0 +1,4 @@ +[meta] +name = Zira +preview = screenshot +author = Zira \ No newline at end of file diff --git a/themes/default/zira/comments.php b/themes/default/zira/comments.php new file mode 100644 index 0000000..cb6771b --- /dev/null +++ b/themes/default/zira/comments.php @@ -0,0 +1,72 @@ + +
    + + + + +

    ()

    + + + +
      + + +sort_path)) - 1; ?> +0) $comment_offset_class = ' comments-item-nested-'.($comment_offset < Zira\Config::get('comments_max_nesting', 5) ? $comment_offset : Zira\Config::get('comments_max_nesting', 5)); ?> +
    • +author_id > 0 && $comment->author_username !== null && $comment->author_firstname !== null && $comment->author_secondname !== null): ?> +author_id, $comment->author_firstname, $comment->author_secondname, $comment->author_username, null, $comment->author_image, null, array('class'=>'comment-avatar')) ?> + +author_image, null, array('class'=>'comment-avatar')) ?> + + +author_id > 0 && $comment->author_username !== null && $comment->author_firstname !== null && $comment->author_secondname !== null): ?> +sender_name ? Zira\User::generateUserProfileLink($comment->author_id, null, null, $comment->sender_name) : Zira\User::generateUserProfileLink($comment->author_id, $comment->author_firstname, $comment->author_secondname, $comment->author_username)); ?> + +sender_name ? Zira\Helper::html($comment->sender_name) : t('Guest')); ?> + +recipient_name): ?> +   recipient_name) ?> + + +

      content))) ?>

      + + creation_date)) ?>   + + +likes); ?> +   + + +dislikes); ?> +   + + + + +
    • + +
    +$limit*($page+1)): ?> +
    + +
    + + + +
    + +
    + + +'.t('Login').'') ?> + + +
    + + \ No newline at end of file diff --git a/themes/default/zira/contact.php b/themes/default/zira/contact.php new file mode 100644 index 0000000..bd29e28 --- /dev/null +++ b/themes/default/zira/contact.php @@ -0,0 +1,44 @@ + +
    + +<?php if (!empty($name)) echo Zira\Helper::html($name); ?> + +
    + +

    + + +
    + + +
    + + +
    + + + + + +

    + +
    +
    +$address, 'name'=>!empty($name) ? $name : ''), 'zira/google-map'); ?> +$address, 'name'=>!empty($name) ? $name : ''), 'zira/yandex-map'); ?> + \ No newline at end of file diff --git a/themes/default/zira/gallery.php b/themes/default/zira/gallery.php new file mode 100644 index 0000000..999a41a --- /dev/null +++ b/themes/default/zira/gallery.php @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/themes/default/zira/google-map.php b/themes/default/zira/google-map.php new file mode 100644 index 0000000..90a314e --- /dev/null +++ b/themes/default/zira/google-map.php @@ -0,0 +1,44 @@ + + + + +
    + + + + + + + + \ No newline at end of file diff --git a/themes/default/zira/home.php b/themes/default/zira/home.php new file mode 100644 index 0000000..fbb3698 --- /dev/null +++ b/themes/default/zira/home.php @@ -0,0 +1,50 @@ + + + +
    + + + +
      + +
    • + +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      +
      + + creation_date)) ?> + + + author_id, $record->author_firstname, $record->author_secondname, $record->author_username) ?> + + + comments ?> + + + + +category_name && $record->category_title): ?> + category_title) ?> + +
      +
    • + +
    +
    + + diff --git a/themes/default/zira/list.php b/themes/default/zira/list.php new file mode 100644 index 0000000..40f0519 --- /dev/null +++ b/themes/default/zira/list.php @@ -0,0 +1,44 @@ + +
      + + +
    • +

      +title) ?> +

      +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      +
      + + creation_date)) ?> + + + author_id, $record->author_firstname, $record->author_secondname, $record->author_username) ?> + + + comments ?> + + + + +category_name && $record->category_title): ?> + category_title) ?> + +
      +
    • + +=$settings['limit']) break; ?> + +
    +$settings['limit']): ?> +
    + +
    + + diff --git a/themes/default/zira/map.php b/themes/default/zira/map.php new file mode 100644 index 0000000..846a20c --- /dev/null +++ b/themes/default/zira/map.php @@ -0,0 +1,20 @@ +
    + +
    \ No newline at end of file diff --git a/themes/default/zira/search-results.php b/themes/default/zira/search-results.php new file mode 100644 index 0000000..eabed89 --- /dev/null +++ b/themes/default/zira/search-results.php @@ -0,0 +1,34 @@ + +
      + + +
    • +

      +title) ?> +

      +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      + +
      +category_name && $record->category_title): ?> + category_title) ?> + +
      + +
    • + +=$settings['limit']) break; ?> + +
    +$settings['limit'] && isset($settings['offset'])): ?> +
    + +
    + + diff --git a/themes/default/zira/search.php b/themes/default/zira/search.php new file mode 100644 index 0000000..ef38f4c --- /dev/null +++ b/themes/default/zira/search.php @@ -0,0 +1,11 @@ + + + +
    + +
    + +

    + \ No newline at end of file diff --git a/themes/default/zira/slider.php b/themes/default/zira/slider.php new file mode 100644 index 0000000..6f0cffb --- /dev/null +++ b/themes/default/zira/slider.php @@ -0,0 +1,9 @@ + +
    +
      + +
    • <?php echo Zira\Helper::html($_image->description) ?>
    • + +
    +
    + diff --git a/themes/default/zira/user/conversations.php b/themes/default/zira/user/conversations.php new file mode 100644 index 0000000..90a1f6b --- /dev/null +++ b/themes/default/zira/user/conversations.php @@ -0,0 +1,122 @@ + + +
    + +
    + + +
      +$item): ?> +
    • + +    + modified_date))) ?> +    + subject) ?> +
    • + +
    + +

    + + + diff --git a/themes/default/zira/user/menu.php b/themes/default/zira/user/menu.php new file mode 100644 index 0000000..f16c87f --- /dev/null +++ b/themes/default/zira/user/menu.php @@ -0,0 +1,27 @@ + +
      +$item): ?> +0): ?> + + + + +
    + \ No newline at end of file diff --git a/themes/default/zira/user/messages.php b/themes/default/zira/user/messages.php new file mode 100644 index 0000000..0e4ed8f --- /dev/null +++ b/themes/default/zira/user/messages.php @@ -0,0 +1,71 @@ + + + +
      +0): ?> +
    •  
    • +$user): ?> +0) echo '
    • '; ?> +
    • id, $user->firstname, $user->secondname, $user->username, null); ?>
    • + + +
    •  
    • +
    • + +
    +
    + +
    + + +
      +$item): ?> +
    • +
      +username): ?> +user_id, $item->firstname, $item->secondname, $item->username); ?> + + + +    +
      creation_date))) ?>
      +
      +
      +username): ?> +user_id, $item->firstname, $item->secondname, $item->username, null, $item->image); ?> + +
      +
      +

      content))) ?>

      +
      +
    • + +
    + + +0) echo $form; ?> + + \ No newline at end of file diff --git a/themes/default/zira/user/profile.php b/themes/default/zira/user/profile.php new file mode 100644 index 0000000..9d651fa --- /dev/null +++ b/themes/default/zira/user/profile.php @@ -0,0 +1,73 @@ +
    + +
    \ No newline at end of file diff --git a/themes/default/zira/widgets/block.php b/themes/default/zira/widgets/block.php new file mode 100644 index 0000000..d335703 --- /dev/null +++ b/themes/default/zira/widgets/block.php @@ -0,0 +1,6 @@ +
    + +

    + + +
    \ No newline at end of file diff --git a/themes/default/zira/widgets/category.php b/themes/default/zira/widgets/category.php new file mode 100644 index 0000000..09156fc --- /dev/null +++ b/themes/default/zira/widgets/category.php @@ -0,0 +1,49 @@ +
    + + + + +
      + +
    • +

      +title) ?> +

      +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      + +
      + + creation_date)) ?> + + + author_id, $record->author_firstname, $record->author_secondname, $record->author_username) ?> + + + comments ?> + + + + +category_name && $record->category_title): ?> + category_title) ?> + +
      + +
    • + +
    + +
    diff --git a/themes/default/zira/widgets/childmenu.php b/themes/default/zira/widgets/childmenu.php new file mode 100644 index 0000000..eb0cb2c --- /dev/null +++ b/themes/default/zira/widgets/childmenu.php @@ -0,0 +1,28 @@ +
    + +
    \ No newline at end of file diff --git a/themes/default/zira/widgets/discussed.php b/themes/default/zira/widgets/discussed.php new file mode 100644 index 0000000..08bacf0 --- /dev/null +++ b/themes/default/zira/widgets/discussed.php @@ -0,0 +1,42 @@ +
    + + + + +
      + +
    • +

      +title) ?> +

      +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      +
      + + + creation_date)) ?> + + + + + + + comments ?> + +category_name && $record->category_title): ?> + category_title) ?> + +
      +
    • + +
    + +
    diff --git a/themes/default/zira/widgets/footermenu.php b/themes/default/zira/widgets/footermenu.php new file mode 100644 index 0000000..b192d5b --- /dev/null +++ b/themes/default/zira/widgets/footermenu.php @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/themes/default/zira/widgets/languages.php b/themes/default/zira/widgets/languages.php new file mode 100644 index 0000000..893de4c --- /dev/null +++ b/themes/default/zira/widgets/languages.php @@ -0,0 +1,15 @@ +1) { +echo '
      '; + Zira\Helper::setAddingLanguageToUrl(false); + foreach($languages as $language) { + $url = Zira\Helper::html($language); + $class = ''; + if ($language == Zira\Config::get('language')) $url='/'; + if ($language == Zira\Locale::getLanguage()) $class=' class="active"'; + echo '
    • '.Zira\Helper::html(t(ucfirst($language))).'
    • '; + } + Zira\Helper::setAddingLanguageToUrl(true); +echo '
    '; +} diff --git a/themes/default/zira/widgets/logo.php b/themes/default/zira/widgets/logo.php new file mode 100644 index 0000000..6f3bff1 --- /dev/null +++ b/themes/default/zira/widgets/logo.php @@ -0,0 +1,13 @@ +'; + if (!empty($logo) || !empty($title)) { + echo ''; + } + if (!empty($slogan)) echo '

    '.Zira\Helper::html($slogan).'

    '; + else echo '

     

    '; + echo ''; +} \ No newline at end of file diff --git a/themes/default/zira/widgets/rated.php b/themes/default/zira/widgets/rated.php new file mode 100644 index 0000000..7827295 --- /dev/null +++ b/themes/default/zira/widgets/rated.php @@ -0,0 +1,42 @@ +
    + + + + +
      + +
    • +

      +title) ?> +

      +
      +thumb): ?> + +<?php echo Zira\Helper::html($record->title) ?> + + +

      description)) ?>

      +
      +
      + + + creation_date)) ?> + + + comments ?> + + + + + +category_name && $record->category_title): ?> + category_title) ?> + +
      +
    • + +
    + +
    diff --git a/themes/default/zira/widgets/share.php b/themes/default/zira/widgets/share.php new file mode 100644 index 0000000..b52f9c1 --- /dev/null +++ b/themes/default/zira/widgets/share.php @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/themes/default/zira/widgets/topmenu.php b/themes/default/zira/widgets/topmenu.php new file mode 100644 index 0000000..0e34d0d --- /dev/null +++ b/themes/default/zira/widgets/topmenu.php @@ -0,0 +1,38 @@ +
    + +
    \ No newline at end of file diff --git a/themes/default/zira/xml/rss.php b/themes/default/zira/xml/rss.php new file mode 100644 index 0000000..c16c30a --- /dev/null +++ b/themes/default/zira/xml/rss.php @@ -0,0 +1,33 @@ +'; ?> + + + +<?php echo Zira\Helper::html($title); ?> + + + + + +<?php echo Zira\Helper::html($title); ?> + + + +Zira CMS + + + +<?php echo Zira\Helper::html($item['title']) ?> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/themes/default/zira/xml/sitemap-index.php b/themes/default/zira/xml/sitemap-index.php new file mode 100644 index 0000000..dc2c7eb --- /dev/null +++ b/themes/default/zira/xml/sitemap-index.php @@ -0,0 +1,9 @@ +'; ?> + + + + + + + + \ No newline at end of file diff --git a/themes/default/zira/xml/sitemap.php b/themes/default/zira/xml/sitemap.php new file mode 100644 index 0000000..5fc9d05 --- /dev/null +++ b/themes/default/zira/xml/sitemap.php @@ -0,0 +1,12 @@ +'; ?> + + +$url): ?> + + +weekly +0.8 + + + + diff --git a/themes/default/zira/yandex-map.php b/themes/default/zira/yandex-map.php new file mode 100644 index 0000000..c91a7a2 --- /dev/null +++ b/themes/default/zira/yandex-map.php @@ -0,0 +1,53 @@ + + + + + +
    + + + + + + + diff --git a/zira.php b/zira.php new file mode 100644 index 0000000..696ef9e --- /dev/null +++ b/zira.php @@ -0,0 +1,10 @@ +self::CACHE_LIFETIME; + } + + public static function isJSExpired() { + return time()-self::getJSMTime()>self::CACHE_LIFETIME; + } + + public static function isCSSCached() { + $url = CACHE_DIR . DIRECTORY_SEPARATOR . self::CSS_ASSETS_CACHE_FILE; + $css_file = ROOT_DIR . DIRECTORY_SEPARATOR . $url; + return file_exists($css_file) && is_readable($css_file) && filesize($css_file)>0; + } + + public static function isJSCached() { + $url = CACHE_DIR . DIRECTORY_SEPARATOR . self::JS_ASSETS_CACHE_FILE; + $js_file = ROOT_DIR . DIRECTORY_SEPARATOR . $url; + return file_exists($js_file) && is_readable($js_file) && filesize($js_file)>0; + } + + public static function isCached() { + return self::isCSSCached() && self::isJSCached(); + } + + public static function isCachedAndNotExpired() { + if (defined('DEBUG') && DEBUG) return false; + return self::isCached() && !self::isCSSExpired() && !self::isJSExpired(); + } + + public static function setActive($active) { + self::$_active = (bool)$active; + } + + public static function isActive() { + return self::$_active; + } + + public static function isMergedCSS($file) { + return in_array($file, self::$_css_assets); + } + + public static function isMergedJS($file) { + return in_array($file, self::$_js_assets); + } + + public static function getCSSURL() { + if (Config::get('clean_url')) { + $url = Helper::baseUrl(self::CSS_SCRIPT_CLEAN); + } else { + $url = Helper::baseUrl(self::CSS_SCRIPT); + } + $q = '?'; + $q .= 't='.(intval(self::isGzipEnabled())+1).self::getCSSMTime(); + return $url.$q; + } + + public static function getJSURL() { + if (Config::get('clean_url')) { + $url = Helper::baseUrl(self::JS_SCRIPT_CLEAN); + } else { + $url = Helper::baseUrl(self::JS_SCRIPT); + } + $q = '?'; + $q .= 't='.(intval(self::isGzipEnabled())+1).self::getJSMTime(); + return $url.$q; + } + + public static function addStyle() { + $attributes = array(); + $attributes['rel'] = 'stylesheet'; + $attributes['type'] = 'text/css'; + $attributes['href'] = self::getCSSURL(); + View::addHTML(Helper::tag_short('link', $attributes),View::VAR_STYLES); + } + + public static function addScript() { + $attributes = array(); + $attributes['src'] = self::getJSURL(); + View::addHTML(Helper::tag('script', null, $attributes),View::VAR_SCRIPTS); + } + + public static function init() { + if (Request::isAjax()) return; + if (Config::get('caching') && self::isCachedAndNotExpired()) { + self::setActive(true); + } else if (Config::get('caching') && self::merge()) { + self::setActive(true); + } else { + self::setActive(false); + } + if (self::isActive()) { + self::addStyle(); + self::addScript(); + } + } + + public static function isGzipEnabled() { + if (self::$_gzip!==null) return self::$_gzip; + $accept_encoding = ''; + if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && preg_match( '/\b(x-gzip|gzip)\b/', strtolower($_SERVER['HTTP_ACCEPT_ENCODING']), $match)) { + $accept_encoding = $match[1]; + } + if (empty($accept_encoding) && defined('FORCE_GZIP_ASSETS') && FORCE_GZIP_ASSETS) $accept_encoding = 'gzip'; + if (Config::get('gzip') && function_exists('gzencode') && !@ini_get('zlib.output_compression') && !empty($accept_encoding)) { + self::$_gzip = true; + } else { + self::$_gzip = false; + } + return self::$_gzip; + } +} \ No newline at end of file diff --git a/zira/cache.php b/zira/cache.php new file mode 100644 index 0000000..ff06cef --- /dev/null +++ b/zira/cache.php @@ -0,0 +1,88 @@ +Config::get('cache_lifetime')); + } + + public static function get($key, $unserialize = false) { + if (!Config::get('caching')) return false; + + $cache_file = ROOT_DIR . DIRECTORY_SEPARATOR . + CACHE_DIR . DIRECTORY_SEPARATOR . + '.' . $key . '.cache'; + + if (!file_exists($cache_file)) return false; + if (self::isExpired($cache_file)) return false; + + chmod($cache_file, 0440); + $data = file_get_contents($cache_file); + chmod($cache_file, 0000); + + if ($unserialize) { + $data = unserialize($data); + } + + return $data; + } + + public static function getArray($key) { + return self::get($key, true); + } + + public static function getObject($key) { + return self::get($key, true); + } + + public static function clear($force=false) { + if (!Config::get('caching') && !$force) return; + $d = opendir(ROOT_DIR . DIRECTORY_SEPARATOR . CACHE_DIR); + if (!$d) return; + while(($f=readdir($d))!==false) { + if ($f=='.' || $f=='..' || !is_file(ROOT_DIR . DIRECTORY_SEPARATOR . CACHE_DIR . DIRECTORY_SEPARATOR . $f)) continue; + if (substr($f,-6)!='.cache') continue; + @chmod(ROOT_DIR . DIRECTORY_SEPARATOR . CACHE_DIR . DIRECTORY_SEPARATOR . $f, 0660); + @unlink(ROOT_DIR . DIRECTORY_SEPARATOR . CACHE_DIR . DIRECTORY_SEPARATOR . $f); + } + closedir($d); + } +} \ No newline at end of file diff --git a/zira/category.php b/zira/category.php new file mode 100644 index 0000000..1f463a4 --- /dev/null +++ b/zira/category.php @@ -0,0 +1,178 @@ +name, Locale::t($row->title)); + if ($row->name == $request) { + self::$_current = $row; + self::$_param = null; + } + if ($p !== false && $p_request && $row->name != $request && $row->name == $p_request) { + self::$_current = $row; + self::$_param = substr($request, $p + 1); + } + } + } + + public static function loadPartial($request) { + $parts = explode('/',$request); + + if (count($parts)>1) { + $_request = $parts[0]; + $query = Models\Category::getCollection() + ->open_query() + ->where('name','=',$_request); + for($i=1;$iclose_query(); + $query->union(); + $query->open_query(); + $query->where('name','=',$_request); + } + $query->close_query(); + $rows = $query->get(); + } else { + $rows = Models\Category::getCollection() + ->where('name','=',$request) + ->get(); + } + + return $rows; + } + + public static function getAllCategories() { + $rows = Cache::getArray(self::CACHE_KEY); + if ($rows===false) { + $rows = Models\Category::getCollection()->order_by('id','asc')->get(); + Cache::setArray(self::CACHE_KEY, $rows); + } + return $rows; + } + + public static function loadAll($request) { + $parts = explode('/',$request); + + $rows = self::getAllCategories(); + + self::$_childs = array(); + $_rows = array(); + if (count($parts)>1) { + $map = array(); + foreach($rows as $row) { + $map[$row->name] = $row; + if (strpos($row->name, $request.'/')===0) { + self::$_childs []= $row; + } + } + $_request = ''; + for($i=0;$iname == $request) { + $_rows []= $row; + } + if (strpos($row->name, $request.'/')===0) { + self::$_childs []= $row; + } + } + } + + return $_rows; + } + + public static function current() { + return self::$_current; + } + + public static function param() { + return self::$_param; + } + + public static function chain() { + return self::$_chain; + } + + public static function setCurrent($category) { + self::$_current = $category; + } + + public static function setChilds($childs) { + self::$_childs = $childs; + } + + public static function getChainIdsArray() { + $ids = array(); + foreach(self::$_chain as $row) { + $ids []= $row->id; + } + return $ids; + } + + public static function currentChilds() { + return self::$_childs; + } + + public static function getChilds($category = null) { + return Models\Category::getChildCategories($category); + } + + public static function getCategoriesMap() { + $categories = self::getAllCategories(); + if (empty($categories)) return array(); + $child_counts = array(); + foreach($categories as $category) { + if (!array_key_exists($category->parent_id, $child_counts)) { + $child_counts[$category->parent_id] = 0; + } + $child_counts[$category->parent_id]++; + } + $items = array(); + self::buildCategoriesMap($items, $categories, $child_counts); + return $items; + } + + protected static function buildCategoriesMap(array &$items, array &$categories, array &$child_counts, $parent_id = 0) { + foreach($categories as $category) { + if ($category->parent_id == $parent_id) { + $items []= $category; + if (array_key_exists($category->id, $child_counts) && $child_counts[$category->id]>0) { + self::buildCategoriesMap($items, $categories, $child_counts, $category->id); + } + } + } + } +} \ No newline at end of file diff --git a/zira/collection.php b/zira/collection.php new file mode 100644 index 0000000..7d8e110 --- /dev/null +++ b/zira/collection.php @@ -0,0 +1,12 @@ +access_check && !Zira\Permission::check(Zira\Permission::TO_VIEW_RECORDS)) { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login?redirect='.static::generateCategoryUrl(Zira\Category::current()->name), true); + } else { + Zira\Response::forbidden(); + } + } + + if (!$is_ajax) { + $record = static::record(Zira\Category::current()); + + // adding meta tags + $title = Zira\Category::current()->title; + if (Zira\Category::current()->meta_title) $meta_title = Zira\Category::current()->meta_title; + else $meta_title = Zira\Category::current()->title; + if (Zira\Category::current()->meta_keywords) $meta_keywords = Zira\Locale::t(Zira\Category::current()->meta_keywords); + else $meta_keywords = mb_strtolower(Zira\Locale::t(Zira\Category::current()->title), CHARSET); + if (Zira\Category::current()->meta_description) $meta_description = Zira\Category::current()->meta_description; + else if (Zira\Category::current()->description) $meta_description = Zira\Category::current()->description; + else $meta_description = Zira\Locale::t('Category: %s', Zira\Category::current()->title); + $thumb = null; + + if ($record) { + $title = $record->title; + if ($record->meta_title) $meta_title = $record->meta_title; + else $meta_title = $record->title; + if ($record->meta_keywords) $meta_keywords = $record->meta_keywords; + if ($record->meta_description) $meta_description = $record->meta_description; + else $meta_description = $record->description; + if ($record->thumb) $thumb = $record->thumb; + } + + static::addTitle(Zira\Locale::t($meta_title)); + static::setKeywords($meta_keywords); + static::setDescription(Zira\Locale::t($meta_description)); + static::addOpenGraphTags(Zira\Locale::t($meta_title), Zira\Locale::t($meta_description), static::generateCategoryUrl(Zira\Category::current()->name), $thumb); + } + + $limit = Zira\Config::get('records_limit', 10); + if (Zira\Category::current()->records_list===null || Zira\Category::current()->records_list) { + $records = static::getRecords(Zira\Category::current(), false, $limit + 1, $last_id, Zira\Config::get('category_childs_list', true), Zira\Category::currentChilds()); + } else { + $records = array(); + } + + $comments_enabled = Zira\Category::current()->comments_enabled!==null ? Zira\Category::current()->comments_enabled : Zira\Config::get('comments_enabled', 1); + $rating_enabled = Zira\Category::current()->rating_enabled!==null ? Zira\Category::current()->rating_enabled : Zira\Config::get('rating_enabled', 0); + $display_author = Zira\Category::current()->display_author!==null ? Zira\Category::current()->display_author : Zira\Config::get('display_author', 0); + $display_date = Zira\Category::current()->display_date!==null ? Zira\Category::current()->display_date : Zira\Config::get('display_date', 0); + + $data = array( + static::VIEW_PLACEHOLDER_CLASS => 'records', + static::VIEW_PLACEHOLDER_RECORDS => $records, + static::VIEW_PLACEHOLDER_SETTINGS => array( + 'limit' => $limit, + 'comments_enabled' => $comments_enabled, + 'rating_enabled' => $rating_enabled, + 'display_author' => $display_author, + 'display_date' => $display_date + ) + ); + + if (!$is_ajax) { + Zira\View::addPlaceholderView(Zira\View::VAR_CONTENT, $data, 'zira/list'); + Zira\View::preloadThemeLoader(); + + $_data = array( + static::VIEW_PLACEHOLDER_TITLE => Zira\Locale::t($title) + ); + + if ($record) { + $_data[static::VIEW_PLACEHOLDER_IMAGE] = $record->image; + $_data[static::VIEW_PLACEHOLDER_CONTENT] = $record->content; + $_data[static::VIEW_PLACEHOLDER_CLASS] = 'parse-content'; + Zira\View::addParser(); + } else { + $_data[static::VIEW_PLACEHOLDER_DESCRIPTION] = Zira\Locale::t(Zira\Category::current()->description); + } + static::render($_data); + } else { + $data[static::VIEW_PLACEHOLDER_CLASS] .= ' xhr-list'; + Zira\View::renderView($data, 'zira/list'); + } + } + + public static function record($category) { + $record = null; + $record_name = $category->name; + if (strpos($record_name,'/')!==false) { + $record_name_parts = explode('/', $record_name); + $record_name = array_pop($record_name_parts); + $category_id = $category->parent_id; + } else { + $category_id = Zira\Category::ROOT_CATEGORY_ID; + } + + if (!empty($record_name)) { + $record = Zira\Models\Record::getCollection() + ->select(Zira\Models\Record::getFields()) + ->where('category_id', '=', $category_id) + ->and_where('language', '=', Zira\Locale::getLanguage()) + ->and_where('name', '=', $record_name) + ->get(0) + ; + + if ($record) { + $slider_enabled = $category->slider_enabled!==null ? $category->slider_enabled : Zira\Config::get('slider_enabled', 1); + $gallery_enabled = $category->gallery_enabled!==null ? $category->gallery_enabled : Zira\Config::get('gallery_enabled', 1); + + if (!$record->access_check || Zira\Permission::check(Zira\Permission::TO_VIEW_RECORD)) { +// static::setRecordId($record->id); +// static::setRecordUrl(static::generateRecordUrl(null, $record->name)); + + if ($slider_enabled) { + $slides = Zira\Models\Slide::getCollection() + ->where('record_id', '=', $record->id) + ->order_by('id', 'asc') + ->get(); + } else { + $slides = null; + } + + if ($gallery_enabled) { + $images = Zira\Models\Image::getCollection() + ->where('record_id', '=', $record->id) + ->order_by('id', 'asc') + ->get(); + } else { + $images = null; + } + + if (!empty($slides) && $slider_enabled) static::setSlider($slides); + if (!empty($images) && $gallery_enabled) static::setGallery($images); + + if (!empty($slides) && $slider_enabled) $record->image = null; + } else { + $record = null; + } + } + } + return $record; + } +} \ No newline at end of file diff --git a/zira/content/index.php b/zira/content/index.php new file mode 100644 index 0000000..ea47a70 --- /dev/null +++ b/zira/content/index.php @@ -0,0 +1,212 @@ + $layout != Zira\View::LAYOUT_ALL_SIDEBARS, + 'categories' => $categories + ), 'zira/home'); + } + + // adding meta tags + $title = Zira\Config::get('home_title'); + $meta_title = Zira\Config::get('home_window_title'); + $meta_keywords = Zira\Config::get('home_keywords'); + $meta_description = Zira\Config::get('home_description'); + $thumb = null; + if ($record) { + if (!$title) $title = $record->title; + if (!$meta_title) { + if ($record->meta_title) $meta_title = $record->meta_title; + else $meta_title = $record->title; + } + if (!$meta_description) { + if ($record->meta_description) $meta_description = $record->meta_description; + else $meta_description = $record->description; + } + if (!$meta_keywords) $meta_keywords = $record->meta_keywords; + if ($record->thumb) $thumb = $record->thumb; + } else { + if (!$title) $title = Zira\Config::get('site_name'); + if (!$meta_title) $meta_title = Zira\Config::get('site_title'); + if (!$meta_keywords) $meta_keywords = Zira\Config::get('site_keywords'); + if (!$meta_description) $meta_description = Zira\Config::get('site_description'); + } + + static::setTitle(Zira\Locale::t($meta_title)); + static::setKeywords(Zira\Locale::t($meta_keywords)); + static::setDescription(Zira\Locale::t($meta_description)); + static::addOpenGraphTags(Zira\Locale::t($meta_title), Zira\Locale::t($meta_description), '', $thumb); + + //Zira\View::setRenderBreadcrumbs(false); + + $data = array( + static::VIEW_PLACEHOLDER_TITLE => Zira\Locale::t($title) + ); + + if ($record) { + $data[static::VIEW_PLACEHOLDER_IMAGE] = $record->image; + $data[static::VIEW_PLACEHOLDER_CONTENT] = $record->content; + $data[static::VIEW_PLACEHOLDER_CLASS] = 'parse-content'; + Zira\View::addParser(); + } else { + $data[static::VIEW_PLACEHOLDER_DESCRIPTION] = Zira\Locale::t($meta_description); + } + + parent::render($data); + } + + public static function record() { + $record = null; + $record_name = Zira\Config::get('home_record_name'); + if (!empty($record_name)) { + $record = Zira\Models\Record::getCollection() + ->select(Zira\Models\Record::getFields()) + ->where('category_id', '=', Zira\Category::ROOT_CATEGORY_ID) + ->and_where('language', '=', Zira\Locale::getLanguage()) + ->and_where('name', '=', $record_name) + ->get(0) + ; + + if ($record) { + $slider_enabled = Zira\Config::get('slider_enabled', 1); + $gallery_enabled = Zira\Config::get('gallery_enabled', 1); + + if (!$record->access_check || Zira\Permission::check(Zira\Permission::TO_VIEW_RECORD)) { + static::setRecordId($record->id); + static::setRecordUrl(static::generateRecordUrl(null, $record->name)); + + if ($slider_enabled) { + $slides = Zira\Models\Slide::getCollection() + ->where('record_id', '=', $record->id) + ->order_by('id', 'asc') + ->get(); + } else { + $slides = null; + } + + if ($gallery_enabled) { + $images = Zira\Models\Image::getCollection() + ->where('record_id', '=', $record->id) + ->order_by('id', 'asc') + ->get(); + } else { + $images = null; + } + + if (!empty($slides) && $slider_enabled) static::setSlider($slides); + if (!empty($images) && $gallery_enabled) static::setGallery($images); + + if (!empty($slides) && $slider_enabled) $record->image = null; + } else { + $record = null; + } + } + } + return $record; + } + + public static function categories() { + $limit = Zira\Config::get('home_records_limit'); + if (!$limit) $limit = Zira\Config::get('records_limit', 10); + + $categories = array(); + if (Zira\Config::get('home_records_enabled', true)) { + $categories_cache_key = 'home.categories.'.Zira\Locale::getLanguage(); + $cached_categories = Zira\Cache::getArray($categories_cache_key); + if ($cached_categories!==false) { + $categories = $cached_categories; + } else { + // root category records + $records = Zira\Models\Record::getCollection() + ->select('id', 'name', 'author_id', 'title', 'description', 'thumb', 'creation_date', 'rating', 'comments') + ->join(Zira\Models\User::getClass(), array('author_username' => 'username', 'author_firstname' => 'firstname', 'author_secondname' => 'secondname')) + ->where('category_id', '=', Zira\Category::ROOT_CATEGORY_ID) + ->and_where('language', '=', Zira\Locale::getLanguage()) + ->and_where('published', '=', Zira\Models\Record::STATUS_PUBLISHED) + ->and_where('front_page', '=', Zira\Models\Record::STATUS_FRONT_PAGE) + ->order_by('id', 'desc') + ->limit($limit) + ->get(); + + if ($records) { + for ($i = 0; $i < count($records); $i++) { + $records[$i]->category_name = ''; + $records[$i]->category_title = ''; + } + $categories [] = array( + 'title' => '', + 'url' => '', + 'records' => $records, + 'settings' => array( + 'comments_enabled' => Zira\Config::get('comments_enabled', 1), + 'rating_enabled' => Zira\Config::get('rating_enabled', 0), + 'display_author' => Zira\Config::get('display_author', 0), + 'display_date' => Zira\Config::get('display_date', 0) + ) + ); + } + + // top level category records + $order_by = 'id'; + $sort = 'asc'; + $order = Zira\Config::get('home_categories_order', 'asc'); + if ($order == 'desc') $sort = 'desc'; + else if ($order == 'name') $order_by = 'name'; + $top_categories = Zira\Models\Category::getTopCategories($order_by, $sort); + $includeChilds = Zira\Config::get('category_childs_list', true); + if ($includeChilds && CACHE_CATEGORIES_LIST) { + $all_categories = Zira\Category::getAllCategories(); + } + foreach ($top_categories as $category) { + if ($category->access_check && !Zira\Permission::check(Zira\Permission::TO_VIEW_RECORDS)) continue; + + $comments_enabled = $category->comments_enabled !== null ? $category->comments_enabled : Zira\Config::get('comments_enabled', 1); + $rating_enabled = $category->rating_enabled !== null ? $category->rating_enabled : Zira\Config::get('rating_enabled', 0); + $display_author = $category->display_author !== null ? $category->display_author : Zira\Config::get('display_author', 0); + $display_date = $category->display_date !== null ? $category->display_date : Zira\Config::get('display_date', 0); + + $childs = null; + if ($includeChilds && CACHE_CATEGORIES_LIST && isset($all_categories)) { + $childs = array(); + foreach($all_categories as $_category) { + if (mb_strpos($_category->name, $category->name . '/', null, CHARSET) === 0) { + $childs []= $_category; + } + } + } + + $categories [] = array( + 'title' => Zira\Locale::t($category->title), + 'url' => static::generateCategoryUrl($category->name), + 'records' => static::getRecords($category, true, $limit, null, $includeChilds, $childs), + 'settings' => array( + 'comments_enabled' => $comments_enabled, + 'rating_enabled' => $rating_enabled, + 'display_author' => $display_author, + 'display_date' => $display_date + ) + ); + } + + Zira\Cache::setArray($categories_cache_key, $categories); + } + } + return $categories; + } +} \ No newline at end of file diff --git a/zira/content/page.php b/zira/content/page.php new file mode 100644 index 0000000..b5db4d5 --- /dev/null +++ b/zira/content/page.php @@ -0,0 +1,138 @@ +id; + else $category_id = Zira\Category::ROOT_CATEGORY_ID; + + // record options + if (!Zira\Category::current()) { + $slider_enabled = Zira\Config::get('slider_enabled', 1); + $gallery_enabled = Zira\Config::get('gallery_enabled', 1); + $comments_enabled = Zira\Config::get('comments_enabled', 1); + $rating_enabled = Zira\Config::get('rating_enabled', 0); + $display_author = Zira\Config::get('display_author', 0); + $display_date = Zira\Config::get('display_date', 0); + } else { + $slider_enabled = Zira\Category::current()->slider_enabled!==null ? Zira\Category::current()->slider_enabled : Zira\Config::get('slider_enabled', 1); + $gallery_enabled = Zira\Category::current()->gallery_enabled!==null ? Zira\Category::current()->gallery_enabled : Zira\Config::get('gallery_enabled', 1); + $comments_enabled = Zira\Category::current()->comments_enabled!==null ? Zira\Category::current()->comments_enabled : Zira\Config::get('comments_enabled', 1); + $rating_enabled = Zira\Category::current()->rating_enabled!==null ? Zira\Category::current()->rating_enabled : Zira\Config::get('rating_enabled', 0); + $display_author = Zira\Category::current()->display_author!==null ? Zira\Category::current()->display_author : Zira\Config::get('display_author', 0); + $display_date = Zira\Category::current()->display_date!==null ? Zira\Category::current()->display_date : Zira\Config::get('display_date', 0); + } + + $query = Zira\Models\Record::getCollection() + ->select(Zira\Models\Record::getFields()) + ->where('category_id', '=', $category_id) + ->and_where('language', '=', Zira\Locale::getLanguage()) + ->and_where('name', '=', $param) + ; + + if (!$preview) { + $query->and_where('published', '=', Zira\Models\Record::STATUS_PUBLISHED); + } + + if ($display_author) { + $query->join(Zira\Models\User::getClass(), array('author_username'=>'username', 'author_firstname'=>'firstname', 'author_secondname'=>'secondname')); + } + + $row = $query->get(0); + + if (!$row) { + Zira\Response::notFound(); + } + + $home_page_name = Zira\Config::get('home_record_name'); + if ($home_page_name && $row->name == $home_page_name && $row->category_id == Zira\Category::ROOT_CATEGORY_ID) { + Zira\Response::redirect('/'); + } + + static::$_record_id = $row->id; + + if (Zira\Category::current()) static::$_record_url = static::generateRecordUrl(Zira\Category::current()->name, $row->name); + else static::$_record_url = static::generateRecordUrl(null, $row->name); + + // checking permission + if (((Zira\Category::current() && Zira\Category::current()->access_check) || $row->access_check) && + !Zira\Permission::check(Zira\Permission::TO_VIEW_RECORD) + ) { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login?redirect='.static::$_record_url, true); + } else { + Zira\Response::forbidden(); + } + } + + // adding meta tags + if ($row->meta_title) $meta_title = $row->meta_title; + else $meta_title = $row->title; + if ($row->meta_description) $meta_description = $row->meta_description; + else $meta_description = $row->description; + if ($row->thumb) $thumb = $row->thumb; + else $thumb = null; + + static::addTitle($meta_title); + static::setKeywords($row->meta_keywords); + static::setDescription($meta_description); + static::addOpenGraphTags($meta_title, $meta_description, static::$_record_url, $thumb); + + if ($display_author) { + $author = Zira\User::generateUserProfileLink($row->author_id, $row->author_firstname, $row->author_secondname, $row->author_username, 'author'); + } else { + $author = null; + } + + if ($slider_enabled) { + $slides = Zira\Models\Slide::getCollection() + ->where('record_id','=',$row->id) + ->order_by('id', 'asc') + ->get(); + } else { + $slides = null; + } + + if ($gallery_enabled) { + $images = Zira\Models\Image::getCollection() + ->where('record_id','=',$row->id) + ->order_by('id', 'asc') + ->get(); + } else { + $images = null; + } + + if (!empty($slides) && $slider_enabled) { + static::setSlider($slides); + } + if (!empty($images) && $gallery_enabled) { + static::setGallery($images); + } + if ($comments_enabled) { + static::setComments($row, $preview); + } + + Zira\View::addParser(); + + static::render(array( + static::VIEW_PLACEHOLDER_TITLE => $row->title, + static::VIEW_PLACEHOLDER_IMAGE => empty($slides) || !$slider_enabled ? $row->image : null, + static::VIEW_PLACEHOLDER_CONTENT => $row->content, + static::VIEW_PLACEHOLDER_DATE => $display_date ? $row->modified_date : null, + static::VIEW_PLACEHOLDER_AUTHOR => $author, + static::VIEW_PLACEHOLDER_RATING => $rating_enabled ? $row->rating : null, + static::VIEW_PLACEHOLDER_URL => static::$_record_url, + static::VIEW_PLACEHOLDER_CLASS => 'parse-content' + )); + } +} \ No newline at end of file diff --git a/zira/content/parse.php b/zira/content/parse.php new file mode 100644 index 0000000..490516d --- /dev/null +++ b/zira/content/parse.php @@ -0,0 +1,30 @@ +$1', $content); + } + if (stripos($content, '[quote')!==false) { + $content = preg_replace('/\[quote[^\]]*?\]([^\[\]]+?)[\s]*\[\/quote\]/i', '$1', $content); + } + if (stripos($content, '[code')!==false) { + $content = preg_replace('/\[code[^\]]*?\]([^\[\]]+?)[\s]*\[\/code\]/i', '$1', $content); + } + if (stripos($content, '[img')!==false) { + $content = preg_replace('/\[img[^\]]*?\][\s]*([^\[\]"]+?)[\s]*\[\/img\]/i', '', $content); + } + } + return $content; + } +} \ No newline at end of file diff --git a/zira/controller.php b/zira/controller.php new file mode 100644 index 0000000..c3fea96 --- /dev/null +++ b/zira/controller.php @@ -0,0 +1,19 @@ +$record_id, + 'comments'=>$comments, + 'limit'=>$limit, + 'page'=>$page, + 'total'=>Zira\Models\Comment::countComments($record_id, !$preview), + 'ajax'=>true + ), 'zira/comments'); + } + } + + /** + * Comment action + */ + public function comment() { + $form = new Zira\Forms\Comment(); + $commenting_allowed = Zira\Config::get('comments_allowed',true); + if (!Zira\Config::get('comment_anonymous',true) && + !Zira\User::isAuthorized() + ) { + $commenting_allowed = false; + } + if (Zira\Request::isPost() && $commenting_allowed) { + if ($form->isValid()) { + $record = new Zira\Models\Record($form->getValue('record_id')); + if (!$record->loaded()) { + $form->setError(Zira\Locale::t('An error occurred')); + } else { + $parent = null; + $parent_id = (int)$form->getValue('parent_id'); + if ($parent_id>0) { + $parent = new Zira\Models\Comment($parent_id); + if (!$parent->loaded()) { + $parent = null; + $parent_id = 0; + } + } + $comment = new Zira\Models\Comment(); + $comment->record_id = $record->id; + if (Zira\User::isAuthorized()) { + $comment->author_id = Zira\User::getCurrent()->id; + $comment->sender_name = Zira\User::getProfileName(); + } else { + $comment->author_id = 0; + $comment->sender_name = strip_tags($form->getValue('sender_name')); + } + $comment->parent_id = $parent_id; + if ($parent!==null) { + $comment->recipient_name = $parent->sender_name; + } + $path_offset = Zira\Models\Comment::getPathOffset($record->id, $parent); + $comment->path_offset = $path_offset+1; + $comment->sort_path = Zira\Models\Comment::getSortPath($path_offset, $parent); + $comment->content = strip_tags($form->getValue('comment')); + $comment->creation_date = date('Y-m-d H:i:s'); + if (Zira\Permission::check(Zira\Permission::TO_MODERATE_COMMENTS) || + !Zira\Config::get('comment_moderate', true) + ) { + $comment->published = Zira\Models\Comment::STATUS_PUBLISHED; + } else { + $comment->published = Zira\Models\Comment::STATUS_NOT_PUBLISHED; + } + $comment->save(); + if ($comment->published != Zira\Models\Comment::STATUS_PUBLISHED) { + $form->setMessage(Zira\Locale::t('Thank you. Your message is awaiting moderation')); + } else { + $form->setMessage(Zira\Locale::t('Thank you. Your message was published')); + $record->comments++; + $record->save(); + if (Zira\User::isAuthorized()) { + Zira\User::increaseCommentsCount(); + } + } + try { + Zira\Models\Comment::notify($record, $comment); + } catch(\Exception $e) { + Zira\Log::exception($e); + } + } + } + } + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT => $form + )); + } +} \ No newline at end of file diff --git a/zira/controllers/contact.php b/zira/controllers/contact.php new file mode 100644 index 0000000..a7068a0 --- /dev/null +++ b/zira/controllers/contact.php @@ -0,0 +1,111 @@ +isValid()) { + if (Zira\User::isAuthorized()) { + $name = Zira\User::getProfileName(); + $email = Zira\User::getProfileEmail(); + $replyTo = $email; + } else { + $name = $form->getValue('name'); + if (empty($name)) $name= Zira\Locale::t('not specified'); + $email = $form->getValue('email'); + if (empty($email)) { + $email = Zira\Locale::t('not specified'); + $replyTo = null; + } else { + $replyTo = $email; + } + } + $message = $form->getValue('message'); + + $message_tpl = Zira\Config::get('feedback_message'); + if (!$message_tpl || strlen(trim($message_tpl)) == 0) { + $message_tpl = Zira\Locale::t('Message') . ':' . "\r\n"; + $message_tpl .= '$message' . "\r\n\r\n"; + $message_tpl .= Zira\Locale::t('Name: %s', '$name') . "\r\n"; + $message_tpl .= Zira\Locale::t('Email: %s', '$email') . "\r\n\r\n"; + $message_tpl .= Zira\Locale::t('You recieved this message, because your Email address is specified as a contact email on %s', '$site'); + } else { + $message_tpl = Zira\Locale::t($message_tpl); + } + $message_tpl = str_replace('$name', $name, $message_tpl); + $message_tpl = str_replace('$email', $email, $message_tpl); + $message_tpl = str_replace('$message', $message, $message_tpl); + $message_tpl = str_replace('$site', Zira\Helper::url('/', true, true), $message_tpl); + + try { + Zira\Mail::send(Zira\Config::get('feedback_email'), Zira\Locale::t('Feedback'), Zira\Helper::html($message_tpl), null, $replyTo); + $form->setMessage(Zira\Locale::t('Thank you. Your message was sent')); + $form->setFill(false); + } catch (\Exception $e) { + $form->setError(Zira\Locale::t('Sorry, could not send your message. Try later')); + } + } + if (Zira\Config::get('contact_email_public')) { + $contacts['email'] = Zira\Config::get('feedback_email'); + } + } else { + $form = ''; + } + + $contact_name = Zira\Config::get('contact_name'); + if ($contact_name) $contacts['name'] = $contact_name; + $contact_address = Zira\Config::get('contact_address'); + if ($contact_address) $contacts['address'] = $contact_address; + $contact_image = Zira\Config::get('contact_image'); + if ($contact_image) $contacts['image'] = $contact_image; + $contact_phone = Zira\Config::get('contact_phone'); + if ($contact_phone) $contacts['phone'] = $contact_phone; + $contact_info = Zira\Config::get('contact_info'); + if ($contact_info) $contacts['info'] = $contact_info; + $contact_fb = Zira\Config::get('contact_fb'); + if ($contact_fb) $contacts['facebook'] = $contact_fb; + $contact_gp= Zira\Config::get('contact_gp'); + if ($contact_gp) $contacts['google'] = $contact_gp; + $contact_tw= Zira\Config::get('contact_tw'); + if ($contact_tw) $contacts['twitter'] = $contact_tw; + $contact_vk= Zira\Config::get('contact_vk'); + if ($contact_vk) $contacts['vkontakte'] = $contact_vk; + $contact_yandex_map = Zira\Config::get('contact_yandex_map'); + if ($contact_yandex_map && $contact_address) $contacts['yandex_map'] = $contact_yandex_map; + $contact_google_map = Zira\Config::get('contact_google_map'); + if ($contact_google_map && $contact_address) $contacts['google_map'] = $contact_google_map; + + if (empty($form) && empty($contacts)) { + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_TITLE => Zira\Locale::t('Contacts'), + Zira\Page::VIEW_PLACEHOLDER_CONTENT => Zira\Locale::t('Sorry, contacts are not specified') + )); + } else if (!empty($form) && empty($contacts)) { + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_TITLE => Zira\Locale::t('Contacts'), + Zira\Page::VIEW_PLACEHOLDER_CONTENT => $form + )); + } else { + if (!empty($form)) $contacts['form'] = $form; + Zira\Page::setView('zira/contact'); + Zira\Page::render($contacts); + } + } +} \ No newline at end of file diff --git a/zira/controllers/cron.php b/zira/controllers/cron.php new file mode 100644 index 0000000..75aa492 --- /dev/null +++ b/zira/controllers/cron.php @@ -0,0 +1,51 @@ +run(); + } catch (\Exception $e) { + $response = Zira\Locale::t('An error occurred') . ': ' . $e->getMessage(); + Zira\Log::exception($e); + } + $output .= "\t" . $co . '. ' . $response . "\r\n"; + } + } + Zira\Models\Option::write('cron_run', time()); + } + if (Zira\View::isAjax()) { + echo json_encode(explode("\r\n",$output)); + } else { + header('Content-Type: text/plain; charset='.CHARSET); + echo $output; + } + } +} \ No newline at end of file diff --git a/zira/controllers/index.php b/zira/controllers/index.php new file mode 100644 index 0000000..ba67318 --- /dev/null +++ b/zira/controllers/index.php @@ -0,0 +1,86 @@ +layout) { + Zira\Page::setLayout(Zira\Category::current()->layout); + } + Zira\Content\Page::content($param, Zira\Page::allowPreview()); + } else if (Zira\Category::current()) { + if (Zira\Category::current()->layout) { + Zira\Page::setLayout(Zira\Category::current()->layout); + } + Zira\Content\Category::content(); + } else { + Zira\Response::notFound(); + } + } + + /** + * 403 page + */ + public function forbidden() { + Zira\Response::forbidden(); + } + + /** + * 404 page + */ + public function notfound() { + Zira\Response::notFound(); + } + + /** + * Displays CAPTCHA image + */ + public function captcha() { + header('Content-Type: image/jpeg'); + Zira\Form\Form::generateCaptcha(); + } + + /** + * Site map page + */ + public function map() { + $categories = Zira\Category::getCategoriesMap(); + + Zira\Page::addTitle(Zira\Locale::t('Site map')); + Zira\Page::addBreadcrumb('sitemap', Zira\Locale::t('Site map')); + + Zira\View::addPlaceholderView(Zira\View::VAR_CONTENT, array('categories'=>$categories), 'zira/map'); + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_TITLE => Zira\Locale::t('Site map'), + Zira\Page::VIEW_PLACEHOLDER_CONTENT => '' + )); + } +} diff --git a/zira/controllers/poll.php b/zira/controllers/poll.php new file mode 100644 index 0000000..15b32bf --- /dev/null +++ b/zira/controllers/poll.php @@ -0,0 +1,111 @@ +id : 0; + $anonymous_id = Zira\User::getAnonymousUserId(); + if (empty($user_id) && empty($anonymous_id)) return; + + if ($type == 'record' && $value==1) { + $record = new Zira\Models\Record($id); + if (!$record->loaded()) return; + + $query = Zira\Models\Like::getCollection() + ->count() + ->where('record_id','=',$record->id); + + if (!empty($user_id)) { + $query->and_where(); + $query->open_where(); + $query->where('user_id','=',$user_id); + $query->or_where('anonymous_id','=',$anonymous_id); + $query->close_where(); + } else if (!empty($anonymous_id)) { + $query->and_where('anonymous_id','=',$anonymous_id); + } + + $co = $query->get('co'); + + if ($co==0) { + $like = new Zira\Models\Like(); + $like->record_id = $record->id; + $like->user_id = $user_id; + $like->anonymous_id = $anonymous_id; + $like->creation_date = date('Y-m-d H:i:s'); + $like->save(); + + $record->rating++; + $record->save(); + } + + Zira\Page::render(array('rating'=>$record->rating)); + } else if ($type == 'comment' && ($value==1 || $value==-1)) { + $comment = new Zira\Models\Comment($id); + if (!$comment->loaded()) return; + + $query = Zira\Models\Commentlike::getCollection() + ->where('comment_id','=',$comment->id); + + if (!empty($user_id)) { + $query->and_where(); + $query->open_where(); + $query->where('user_id','=',$user_id); + $query->or_where('anonymous_id','=',$anonymous_id); + $query->close_where(); + } else if (!empty($anonymous_id)) { + $query->and_where('anonymous_id','=',$anonymous_id); + } + + $exists = $query->get(0, true); + + if (!$exists || $exists['rate'] != $value) { + $like = new Zira\Models\Commentlike(); + if (!$exists) { + $like->comment_id = $comment->id; + $like->user_id = $user_id; + $like->anonymous_id = $anonymous_id; + $like->creation_date = date('Y-m-d H:i:s'); + } else { + $like->loadFromArray($exists); + if ($exists['rate']>0) $comment->likes--; + else $comment->dislikes--; + } + $like->rate = $value; + $like->save(); + + if ($value>0) $comment->likes++; + else $comment->dislikes++; + $comment->save(); + } + + if ($value>0) + Zira\Page::render(array('rating'=>$comment->likes)); + else + Zira\Page::render(array('rating'=>$comment->dislikes)); + } + } +} \ No newline at end of file diff --git a/zira/controllers/records.php b/zira/controllers/records.php new file mode 100644 index 0000000..92b23c5 --- /dev/null +++ b/zira/controllers/records.php @@ -0,0 +1,32 @@ +loaded()) return; + + Zira\Category::setCurrent($category); + Zira\Category::setChilds(null); + Zira\Content\Category::content($last_id, true); + } + } +} \ No newline at end of file diff --git a/zira/controllers/search.php b/zira/controllers/search.php new file mode 100644 index 0000000..88d078f --- /dev/null +++ b/zira/controllers/search.php @@ -0,0 +1,68 @@ +setExtended(true); + $data = array(); + $found = false; + if ($form->getValue('text') && $offset>=0 && $form->isValid()) { + if (!$is_simple) { + $records = Zira\Models\Search::getRecords($form->getValue('text'), $limit + 1, $offset); + } else { + $records = Zira\Models\Search::getRecordsSorted($form->getValue('text'), $limit); + } + if (!empty($records)) { + $found = true; + $_data = array( + Zira\Page::VIEW_PLACEHOLDER_CLASS => 'search-list'.($is_ajax ? ' xhr-list' : ''), + Zira\Page::VIEW_PLACEHOLDER_RECORDS => $records, + Zira\Page::VIEW_PLACEHOLDER_SETTINGS => array( + 'limit' => $limit, + 'text' => $form->getValue('text'), + 'offset' => $offset, + 'simple' => $is_simple + ) + ); + + if (!$is_ajax) { + Zira\View::addPlaceholderView(Zira\View::VAR_CONTENT, $_data, 'zira/search-results'); + Zira\View::preloadThemeLoader(); + $data[Zira\Page::VIEW_PLACEHOLDER_TITLE] = Zira\Locale::t('Search results'); + $data[Zira\Page::VIEW_PLACEHOLDER_CONTENT] = ''; + } else { + Zira\View::renderView($_data, 'zira/search-results'); + } + } else { + $form->setValue('text',''); + $form->setError(Zira\Locale::t('Your search did not match any documents')); + } + } else { + $form->setValue('text',''); + } + + if (!$is_ajax) { + Zira\Page::addTitle(Zira\Locale::t('Search')); + Zira\Page::addBreadcrumb('search', Zira\Locale::t('Search')); + + Zira\View::addPlaceholderView(Zira\View::VAR_CONTENT_TOP, array('form' => $form, 'found' => $found), 'zira/search'); + Zira\Page::render($data); + } + } +} \ No newline at end of file diff --git a/zira/controllers/user.php b/zira/controllers/user.php new file mode 100644 index 0000000..285dbc8 --- /dev/null +++ b/zira/controllers/user.php @@ -0,0 +1,1024 @@ +0) { + Zira\Response::redirect('user/login'.'?redirect=user/'.$id); + } else { + Zira\Response::redirect('user/login'); + } + return; + } + if (!$id) { + $category = Zira\Category::current(); + if ($category && $category->name==Zira\Router::getController()) { + Zira\Page::category(); + } else if (Zira\User::isAuthorized()) { + Zira\Response::redirect('user/profile'); + } else { + Zira\Response::redirect('user/login'); + } + return; + } + $user = Zira\Models\User::findUser($id); + if (!$user || !$user->active) { + Zira\Response::notFound(); + return; + } + + Zira\Page::addTitle(Zira\Locale::t('User profile')); + Zira\Page::addTitle(Zira\User::getProfileName($user)); + Zira\Page::addBreadcrumb(Zira\User::getProfileUrlPath($user),Zira\Locale::t('User profile')); + + Zira\View::addLightbox(); + Zira\View::render(array( + 'id' => $user->id, + 'title' => Zira\User::getProfileName($user), + 'email' => Zira\User::getProfileEmail($user), + 'phone' => Zira\User::getProfilePhone($user), + 'photo' => Zira\User::getProfilePhoto($user), + 'thumb' => Zira\User::getProfilePhotoThumb($user), + 'location' => Zira\User::getProfileLocation($user), + 'dob' => Zira\User::getProfileDob($user), + 'group' => Zira\User::getProfileGroup($user), + 'date_created' => Zira\User::getProfileSignupDate($user), + 'date_logged' => Zira\User::getProfileLoginDate($user), + 'comments' => Zira\User::getProfileComments($user), + 'is_owner' => Zira\User::isSelf($user), + 'verified' => Zira\User::isProfileVerified($user) + ),'zira/user/profile'); + } + + public function signup() { + if (!Zira\Config::get(Zira\User::CONFIG_ALLOW_SIGNUP, true)) { + Zira\Response::forbidden(); + return; + } + if (Zira\User::isAuthorized()) { + Zira\Response::redirect('user/profile'); + } + $form = new Zira\Forms\User\Register(); + + if (Zira\Request::isPost() && $form->isValid()) { + $user = new Zira\Models\User(); + $user->firstname = $form->getValue('firstname'); + $user->secondname = $form->getValue('secondname'); + $user->email = $form->getValue('email'); + $user->username = $form->getValue('username'); + $user->password = Zira\User::generatePasswordHash($form->getValue('password')); + $user->group_id = Zira\User::GROUP_USER; + $user->date_created = date('Y-m-d H:i:s'); + $user->date_logged = date('Y-m-d H:i:s'); + $user->verified = Zira\Models\User::STATUS_NOT_VERIFIED; + $user->active = Zira\Models\User::STATUS_ACTIVE; + $vcode = Zira\User::generateEmailConfirmationCode(); + $user->vcode = Zira\User::getHashedConfirmationCode($vcode); + $user->code = Zira\User::generateRememberCode($user->username, $user->email); + + try { + $user->save(); + if (Zira\Config::get(Zira\User::CONFIG_VERIFY_EMAIL, true)) { + Zira\User::sendConfirmEmail($user->email, Zira\User::getProfileName($user), $vcode); + Zira\User::rememberConfirmEmail($user->email); + Zira\Response::redirect('user/confirm'); + } else { + Zira\Response::redirect('user/login'); + } + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('User Signup')); + Zira\Page::addBreadcrumb('user/signup',Zira\Locale::t('Sign Up')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function login() { + if (Zira\User::isAuthorized()) { + Zira\Response::redirect('user/profile'); + } + $form = new Zira\Forms\User\Login(); + + $email = Zira\User::getRememberedConfirmEmail(); + if (!empty($email)) { + $form->setValues(array('login'=>$email)); + } + + if (Zira\Request::isPost() && $form->isValid()) { + if (Zira\User::isAllowedToLogin()) { + Zira\User::onUserLogin($form->getValue('rememberme')); + $redirect = Zira\Request::get('redirect'); + if (!empty($redirect) && strpos($redirect,'//')===false && strpos($redirect, '.')===false) { + if ($redirect=='dash') Zira\Helper::setAddingLanguageToUrl(false); + Zira\Response::redirect($redirect); + } else { + Zira\Response::redirect('user/profile'); + } + } else { + Zira\Response::redirect('user/confirm'); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Sign In')); + Zira\Page::addBreadcrumb('user/login',Zira\Locale::t('Sign In')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function logout() { + if (Zira\User::isAuthorized()) { + Zira\User::forgetAuthorizedUserId(); + Zira\User::forgetUser(); + Zira\User::onUserLogout(); + } + Zira\Response::redirect('user/login'); + } + + public function confirm() { + if (Zira\User::isVerified()) { + Zira\Response::redirect('user/profile'); + return; + } + $form = new Zira\Forms\User\Confirm(); + + if (!Zira\User::isAuthorized()) { + $email = Zira\User::getRememberedConfirmEmail(); + if (!empty($email)) { + $form->setValues(array('login'=>$email)); + } + } + + if (Zira\Request::isPost() && $form->isValid()) { + if (!Zira\User::isAuthorized()) { + $current = Zira\User::getCurrent(); + $user = new Zira\Models\User($current->id); + } else { + $user = Zira\User::getCurrent(); + } + $user->verified = Zira\Models\User::STATUS_VERIFIED; + $user->vcode = ''; + + try { + $user->save(); + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } else { + Zira\Response::redirect('user/profile'); + } + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Email confirmation')); + if (Zira\User::isAuthorized()) { + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + } + Zira\Page::addBreadcrumb('user/confirm',Zira\Locale::t('Verification')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function send() { + if (Zira\User::isVerified()) { + Zira\Response::redirect('user/profile'); + return; + } + $form = new Zira\Forms\User\Send(); + + if (!Zira\User::isAuthorized()) { + $email = Zira\User::getRememberedConfirmEmail(); + if (!empty($email)) { + $form->setValues(array('login'=>$email)); + } + } else { + $current = Zira\User::getCurrent(); + $form->setValues(array('login'=>$current->email)); + } + + if (Zira\Request::isPost() && $form->isValid()) { + if (!Zira\User::isAuthorized()) { + $current = Zira\User::getCurrent(); + $user = new Zira\Models\User($current->id); + } else { + $user = Zira\User::getCurrent(); + } + $vcode = Zira\User::generateEmailConfirmationCode(); + $user->vcode = Zira\User::getHashedConfirmationCode($vcode); + + try { + $user->save(); + Zira\User::sendConfirmEmail($user->email, Zira\User::getProfileName($user), $vcode); + Zira\Response::redirect('user/confirm'); + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Send confirmation code')); + if (Zira\User::isAuthorized()) { + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + } + Zira\Page::addBreadcrumb('user/send',Zira\Locale::t('Verification')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function recover() { + if (Zira\User::isAuthorized()) { + Zira\Response::redirect('user/profile'); + } + $form = new Zira\Forms\User\Recover(); + + $email = Zira\User::getRememberedConfirmEmail(); + if (!empty($email)) { + $form->setValues(array('login'=>$email)); + } + + if (Zira\Request::isPost() && $form->isValid()) { + $current = Zira\User::getCurrent(); + $user = new Zira\Models\User($current->id); + $vcode = Zira\User::generatePasswordRecoveryCode(); + $user->vcode = Zira\User::getHashedPasswordRecoveryCode($vcode); + + try { + $user->save(); + Zira\User::sendRecoverEmail($user->email, Zira\User::getProfileName($user), $vcode); + Zira\User::rememberConfirmEmail($user->email); + Zira\Response::redirect('user/password'); + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Password recovery')); + Zira\Page::addBreadcrumb('user/recover',Zira\Locale::t('Recovery')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function password() { + if (Zira\User::isAuthorized()) { + Zira\Response::redirect('user/pwd'); + } + $form = new Zira\Forms\User\Password(); + + $email = Zira\User::getRememberedConfirmEmail(); + if (!empty($email)) { + $form->setValues(array('login'=>$email)); + } + + if (Zira\Request::isPost() && $form->isValid()) { + $current = Zira\User::getCurrent(); + $user = new Zira\Models\User($current->id); + $user->vcode = ''; + $password = Zira\User::generateUserToken(); + $user->password = Zira\User::getHashedUserToken($password); + + try { + $user->save(); + Zira\User::sendPasswordEmail($user->email, Zira\User::getProfileName($user), $password); + Zira\Response::redirect('user/login'); + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Password recovery')); + Zira\Page::addBreadcrumb('user/password',Zira\Locale::t('Recovery')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function pwd() { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/recover'); + } + $form = new Zira\Forms\User\Pwd(); + + if (Zira\Request::isPost() && $form->isValid()) { + $user = Zira\User::getCurrent(); + $password = $form->getValue('password'); + $user->password = Zira\User::getHashedUserToken($password); + + try { + $user->save(); + $form->setMessage(Zira\Locale::t('Successfully saved')); + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Change password')); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + Zira\Page::addBreadcrumb('user/pwd',Zira\Locale::t('Password')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function email() { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } + $form = new Zira\Forms\User\Email(); + + $user = Zira\User::getCurrent(); + + if (Zira\Request::isPost() && $form->isValid()) { + $e_updated = false; + if ($user->email != $form->getValue('email')) { + $user->email = $form->getValue('email'); + $user->verified = Zira\Models\User::STATUS_NOT_VERIFIED; + $vcode = Zira\User::generateEmailConfirmationCode(); + $user->vcode = Zira\User::getHashedConfirmationCode($vcode); + $e_updated = true; + } + $s_updated = false; + $subscribed = $form->getValue('subscribed') ? Zira\Models\User::STATUS_SUBSCRIBED : Zira\Models\User::STATUS_NOT_SUBSCRIBED; + if ($user->subscribed != $subscribed) { + $user->subscribed = $subscribed; + $s_updated = true; + } + try { + if ($e_updated || $s_updated) { + $user->save(); + } + if ($e_updated) { + Zira\User::sendConfirmEmail($user->email, Zira\User::getProfileName($user), $vcode); + } + Zira\Response::redirect('user/confirm'); + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } else { + $form->setValues(array( + 'email'=> $user->email, + 'subscribed'=>$user->subscribed + )); + } + + Zira\Page::addTitle(Zira\Locale::t('Change email')); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + Zira\Page::addBreadcrumb('user/email',Zira\Locale::t('Email')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function name() { + if (!Zira\Config::get(Zira\User::CONFIG_ALLOW_LOGIN_CHANGE, true)) { + Zira\Response::forbidden(); + return; + } + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } + $form = new Zira\Forms\User\Name(); + + $user = Zira\User::getCurrent(); + $form->setValue('login', $user->username); + + if (Zira\Request::isPost() && $form->isValid()) { + $user->username = $form->getValue('login'); + + try { + $user->save(); + $form->setMessage(Zira\Locale::t('Successfully saved')); + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Change username')); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + Zira\Page::addBreadcrumb('user/name',Zira\Locale::t('Username')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function edit() { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } + $form = new Zira\Forms\User\Edit(); + + $user = Zira\User::getCurrent(); + + $form->setValues(array( + 'firstname' => $user->firstname, + 'secondname' => $user->secondname, + 'country' => $user->country, + 'city' => $user->city, + 'street' => $user->address, + 'phone' => $user->phone, + 'dob' => $user->dob ? $form->prepareDatepickerDate($user->dob) : '' + )); + + if (Zira\Request::isPost() && $form->isValid()) { + $user->firstname = $form->getValue('firstname'); + $user->secondname = $form->getValue('secondname'); + $user->country = $form->getValue('country'); + $user->city = $form->getValue('city'); + $user->address = $form->getValue('street'); + $user->phone = $form->getValue('phone'); + $dob = $form->getValue('dob'); + if (!empty($dob)) $user->dob = $form->parseDatepickerDate($dob); + else $user->dob = null; + try { + $user->save(); + $form->setMessage(Zira\Locale::t('Successfully saved')); + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Change profile')); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + Zira\Page::addBreadcrumb('user/edit',Zira\Locale::t('Information')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function photo() { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } + $form = new Zira\Forms\User\Photo(); + + $user = Zira\User::getCurrent(); + + if (Zira\Request::isPost() && $form->isValid()) { + try { + $image = Zira\User::savePhoto($user, $form->getValue('photo')); + if (!$image) { + $form->setError(Zira\Locale::t('An error occurred')); + } else { + $user->image = $image; + $user->save(); + Zira\Response::redirect('user/avatar'); + } + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Change photo')); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + Zira\Page::addBreadcrumb('user/photo',Zira\Locale::t('Photo')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function avatar() { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } + + $user = Zira\User::getCurrent(); + if (!$user->image) { + Zira\Response::redirect('user/photo'); + } + + $form = new Zira\Forms\User\Avatar(); + + $form->setValue('image', $user->image); + + if (Zira\Request::isPost() && $form->isValid()) { + $width = floatval($form->getValue('cropper_w')); + $height = floatval($form->getValue('cropper_h')); + $left = floatval($form->getValue('cropper_x')); + $top = floatval($form->getValue('cropper_y')); + + try { + $image = Zira\User::saveAvatar($user, $width, $height, $left, $top); + if (!$image) { + $form->setError(Zira\Locale::t('An error occurred')); + } else { + $user->image = $image; + $user->save(); + Zira\Response::redirect('user/profile'); + } + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Change avatar')); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + Zira\Page::addBreadcrumb('user/avatar',Zira\Locale::t('Avatar')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function nophoto() { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } + + $user = Zira\User::getCurrent(); + if (!$user->image) { + Zira\Response::redirect('user/profile'); + } + + $form = new Zira\Forms\User\Nophoto(); + + if (Zira\Request::isPost() && $form->isValid()) { + try { + Zira\User::deletePhoto($user); + $user->image = ''; + $user->save(); + Zira\Response::redirect('user/profile'); + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('Remove photo')); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + Zira\Page::addBreadcrumb('user/nophoto',Zira\Locale::t('Photo')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function profile() { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } + + Zira\Page::addTitle(Zira\Locale::t('User profile')); + Zira\Page::addTitle(Zira\User::getProfileName()); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + + Zira\View::addLightbox(); + Zira\View::render(array( + 'title' => Zira\User::getProfileName(), + 'email' => Zira\User::getProfileEmail(), + 'phone' => Zira\User::getProfilePhone(), + 'photo' => Zira\User::getProfilePhoto(), + 'thumb' => Zira\User::getProfilePhotoThumb(), + 'location' => Zira\User::getProfileLocation(), + 'dob' => Zira\User::getProfileDob(), + 'group' => Zira\User::getProfileGroup(), + 'date_created' => Zira\User::getProfileSignupDate(), + 'date_logged' => Zira\User::getProfileLoginDate(), + 'comments' => Zira\User::getProfileComments(), + 'is_owner' => true, + 'verified' => Zira\User::isVerified() + )); + } + + public function message($recipient_id) { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } + + if (empty($recipient_id)) { + Zira\Response::notFound(); + } + if ($recipient_id == Zira\User::getCurrent()->id) { + Zira\Response::forbidden(); + } + $recipient = new Zira\Models\User($recipient_id); + if (!$recipient->loaded() || !$recipient->active) { + Zira\Response::notFound(); + } + + $form = new Zira\Forms\User\Conversation($recipient); + + if (Zira\Request::isPost() && $form->isValid()) { + try { + if (!Zira\Permission::check(Zira\Permission::TO_ACCESS_DASHBOARD) && + ($blocked = Zira\User::isCurrentBlocked($recipient->id, true)) + ) { + $form->setError(Zira\Locale::t('Sorry, you were added to black list. Reason: %s', Zira\Helper::html($blocked->message))); + } else { + $conversation_id = Zira\Models\Conversation::createConversation(Zira\User::getCurrent()->id, $recipient->id, $form->getValue('subject')); + if ($conversation_id) { + $message = new Zira\Models\Message(); + $message->conversation_id = $conversation_id; + $message->user_id = Zira\User::getCurrent()->id; + $message->content = $form->getValue('content'); + $message->creation_date = date('Y-m-d H:i:s'); + $message->save(); + } + Zira\User::increaseMessagesCount($recipient); + try { + Zira\Models\Message::notify($recipient, Zira\User::getCurrent()); + } catch (\Exception $e) { + Zira\Log::exception($e); + } + $form->setMessage(Zira\Locale::t('Message sent')); + $form->setFill(false); + } + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('New message')); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + Zira\Page::addBreadcrumb('user/messages',Zira\Locale::t('Messages')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function compose() { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } + + $form = new Zira\Forms\User\Compose(); + + if (Zira\Request::isPost() && $form->isValid()) { + try { + $users = $form->getUsers(); + $recipients = array(); + foreach($users as $recipient) { + if (!Zira\Permission::check(Zira\Permission::TO_ACCESS_DASHBOARD) && + ($blocked = Zira\User::isCurrentBlocked($recipient->id, true)) + ) { + $form->setError(Zira\Locale::t('Sorry, you are in %s\'s black list', Zira\User::getProfileName($recipient))); + $recipients = array(); + break; + } else { + $recipients []= $recipient->id; + } + } + if (!empty($recipients)) { + $conversation_id = Zira\Models\Conversation::createGroupConversation(Zira\User::getCurrent()->id, $recipients, $form->getValue('subject')); + if ($conversation_id) { + $message = new Zira\Models\Message(); + $message->conversation_id = $conversation_id; + $message->user_id = Zira\User::getCurrent()->id; + $message->content = $form->getValue('content'); + $message->creation_date = date('Y-m-d H:i:s'); + $message->save(); + + foreach($users as $recipient) { + Zira\User::increaseMessagesCount($recipient); + try { + Zira\Models\Message::notify($recipient, Zira\User::getCurrent()); + } catch (\Exception $e) { + Zira\Log::exception($e); + } + } + $form->setMessage(Zira\Locale::t('Message sent')); + $form->setFill(false); + } + } + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + Zira\Page::addTitle(Zira\Locale::t('New message')); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + Zira\Page::addBreadcrumb('user/messages',Zira\Locale::t('Messages')); + + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT=>$form + )); + } + + public function messages($conversation_id) { + if (!Zira\User::isAuthorized()) { + Zira\Response::redirect('user/login'); + } + + Zira\Page::addTitle(Zira\Locale::t('Messages')); + Zira\Page::addBreadcrumb('user/profile',Zira\Locale::t('Profile')); + Zira\Page::addBreadcrumb('user/messages',Zira\Locale::t('Messages')); + + $limit = 10; + if (empty($conversation_id)) { + $total = Zira\Models\Conversation::getCollection() + ->count() + ->where('user_id','=',Zira\User::getCurrent()->id) + ->get('co'); + + $page = (int)Zira\Request::get('page'); + $pages = ceil($total/$limit); + if ($page>$pages) $page = $pages; + if ($page<1) $page = 1; + + $rows = Zira\Models\Conversation::getCollection() + ->where('user_id','=',Zira\User::getCurrent()->id) + ->order_by('modified_date','desc') + ->limit($limit, $limit * ($page-1)) + ->get(); + + $pagination = new Zira\Pagination(); + $pagination->setLimit($limit); + $pagination->setTotal($total); + $pagination->setPages($pages); + $pagination->setPage($page); + + Zira\Page::setView('zira/user/conversations'); + Zira\Page::render(array( + 'items'=>$rows, + 'pagination'=>$pagination + )); + } else { + $_conversation = Zira\Models\Conversation::getCollection() + ->where('conversation_id','=',$conversation_id) + ->and_where('user_id','=',Zira\User::getCurrent()->id) + ->get(0, true); + if (!$_conversation) { + Zira\Response::forbidden(); + } + + $conversation = new Zira\Models\Conversation(); + $conversation->loadFromArray($_conversation); + if ($conversation->highlight) { + $conversation->highlight = 0; + $conversation->save(); + Zira\User::decreaseMessagesCount(); + } + + $form = new Zira\Forms\User\Message(); + + if (Zira\Request::isPost() && $form->isValid()) { + try { + $message = new Zira\Models\Message(); + $message->conversation_id = $conversation_id; + $message->user_id = Zira\User::getCurrent()->id; + $message->content = $form->getValue('content'); + $message->creation_date = date('Y-m-d H:i:s'); + $message->save(); + + $user_conversations = Zira\Models\Conversation::getCollection() + ->where('conversation_id','=',$conversation_id) + ->get(null, true); + + foreach($user_conversations as $user_conversation) { + if ($user_conversation['highlight']) continue; + $_user_conversation = new Zira\Models\Conversation(); + $_user_conversation->loadFromArray($user_conversation); + if ($_user_conversation->user_id!=Zira\User::getCurrent()->id) { + $_user_conversation->highlight = 1; + $recipient = new Zira\Models\User($_user_conversation->user_id); + if (!$recipient->loaded()) continue; + Zira\User::increaseMessagesCount($recipient); + try { + Zira\Models\Message::notify($recipient, Zira\User::getCurrent()); + } catch(\Exception $e) { + Zira\Log::exception($e); + } + } + $_user_conversation->modified_date = date('Y-m-d H:i:s'); + $_user_conversation->save(); + } + + $form->setFill(false); + + if (Zira\View::isAjax()) { + $form->setMessage(Zira\Locale::t('Message sent')); + } + } catch(\Exception $e) { + Zira::getInstance()->exception($e); + $form->setError($e->getMessage()); + } + } + + if (Zira\Request::isPost() && Zira\View::isAjax()) { + Zira\Page::render(array( + Zira\Page::VIEW_PLACEHOLDER_CONTENT => $form + )); + return; + } + + $total = Zira\Models\Message::getCollection() + ->count() + ->where('conversation_id','=',$conversation_id) + ->get('co'); + + $page = (int)Zira\Request::get('page'); + $pages = ceil($total/$limit); + if ($page>$pages) $page = $pages; + if ($page<1) $page = 1; + + $rows = Zira\Models\Message::getCollection() + ->select('id', 'user_id', 'content', 'creation_date') + ->where('conversation_id','=',$conversation_id) + ->left_join(Zira\Models\User::getClass(), array('username', 'firstname', 'secondname', 'image')) + ->order_by('id','desc') + ->limit($limit, $limit * ($page-1)) + ->get(); + + $users = Zira\Models\Conversation::getCollection() + ->where('conversation_id','=',$conversation_id) + ->and_where('user_id','<>',Zira\User::getCurrent()->id) + ->join(Zira\Models\User::getClass(),array('id','username','firstname','secondname','image')) + ->get(); + + $pagination = new Zira\Pagination(); + $pagination->setLimit($limit); + $pagination->setTotal($total); + $pagination->setPages($pages); + $pagination->setPage($page); + + Zira\View::addParser(); + Zira\Page::setView('zira/user/messages'); + Zira\Page::render(array( + 'conversation' => $conversation, + 'users' => $users, + 'items'=>$rows, + 'pagination'=>$pagination, + 'form'=>$form + )); + } + } + + public function ajax() { + Zira\View::setAjax(true); + if (!Zira\User::isAuthorized()) return; + $response = array(); + if (Zira\Request::isPost() && Zira\User::checkToken(Zira\Request::post('token'))) { + $action = Zira\Request::post('action'); + if ($action == 'conversation-mark-read') { + $items = Zira\Request::post('items'); + if (!empty($items) && is_array($items)) { + $updated = array(); + foreach($items as $item) { + $conversation = new Zira\Models\Conversation($item); + if (!$conversation->loaded()) continue; + if ($conversation->user_id != Zira\User::getCurrent()->id) continue; + if (!$conversation->highlight) continue; + $conversation->highlight = 0; + $conversation->save(); + Zira\User::getCurrent()->messages--; + $updated []= $conversation->id; + } + if (Zira\User::getCurrent()->messages<0) Zira\User::getCurrent()->messages = 0; + Zira\User::getCurrent()->save(); + $response['items'] = $updated; + } + } else if ($action == 'conversation-mark-all-read') { + Zira\Models\Conversation::getCollection() + ->update(array('highlight'=>0)) + ->where('user_id','=',Zira\User::getCurrent()->id) + ->execute(); + Zira\User::getCurrent()->messages = 0; + Zira\User::getCurrent()->save(); + } else if ($action == 'conversation-delete') { + $items = Zira\Request::post('items'); + if (!empty($items) && is_array($items)) { + $updated = array(); + foreach($items as $item) { + $conversation = new Zira\Models\Conversation($item); + if (!$conversation->loaded()) continue; + if ($conversation->user_id != Zira\User::getCurrent()->id) continue; + $conversation->delete(); + if ($conversation->highlight) { + Zira\User::getCurrent()->messages--; + } + $updated []= $conversation->id; + } + if (Zira\User::getCurrent()->messages<0) Zira\User::getCurrent()->messages = 0; + Zira\User::getCurrent()->save(); + $response['items'] = $updated; + } + } else if ($action == 'black-list') { + $user_id = Zira\Request::post('user_id'); + $user = new Zira\Models\User($user_id); + if ($user->loaded() && $user->active && !Zira\User::isSelf($user)) { + $row = Zira\User::isUserBlocked($user_id, true); + if (!$row) { + $blocked = new Zira\Models\Blacklist(); + $blocked->user_id = Zira\User::getCurrent()->id; + $blocked->blocked_user_id = $user_id; + $blocked->message = Zira\Request::post('message'); + $blocked->creation_date = date('Y-m-d H:i:s'); + $blocked->save(); + } else { + Zira\Models\Blacklist::getCollection() + ->delete() + ->where('id', '=', $row->id) + ->execute(); + } + $response['success'] = 1; + } else { + $response['success'] = 0; + } + } + } else { + $response['error'] = Zira\Locale::t('Invalid token'); + } + Zira\Page::render($response); + } + + public function autocomplete() { + Zira\View::setAjax(true); + if (!Zira\User::isAuthorized()) return; + $response = array(); + if (Zira\Request::isPost() && Zira\User::checkToken(Zira\Request::post('token'))) { + $items = array(); + $text = Zira\Request::post('text'); + $text = trim(preg_replace('/[\x20]+/',' ', $text)); + if (strlen($text)>0) { + $rows = false; + if (is_numeric($text)) { + $user = new Zira\Models\User($text); + if ($user->loaded() && $user->active) { + $rows = array($user->toArray()); + } + } else if (strpos($text, ' ')>0) { + $parts = explode(' ', $text); + if (count($parts)==2) { + $rows = Zira\Models\User::getCollection() + ->where('firstname', 'like', $parts[0].'%') + ->and_where('secondname', 'like', $parts[1].'%') + ->and_where('active', '=', Zira\Models\User::STATUS_ACTIVE) + ->order_by('id','asc') + ->limit(10) + ->get(null, true); + } + } else { + $rows = Zira\Models\User::getCollection() + ->open_where() + ->where('username','like',$text.'%') + ->or_where('firstname','like',$text.'%') + ->or_where('secondname','like',$text.'%') + ->close_where() + ->and_where('active','=',Zira\Models\User::STATUS_ACTIVE) + ->order_by('id','asc') + ->limit(10) + ->get(null, true); + } + + if ($rows) { + foreach($rows as $row) { + $user = new Zira\Models\User(); + $user->loadFromArray($row); + if (Zira\User::isSelf($user)) continue; + $items[$user->id] = Zira\User::getProfileName($user); + } + } + } + $response['items'] = $items; + } else { + $response['error'] = Zira\Locale::t('Invalid token'); + } + Zira\Page::render($response); + } +} \ No newline at end of file diff --git a/zira/controllers/xml.php b/zira/controllers/xml.php new file mode 100644 index 0000000..27e470a --- /dev/null +++ b/zira/controllers/xml.php @@ -0,0 +1,119 @@ +1) { + Zira\Helper::setAddingLanguageToUrl(false); + $sitemaps = array(); + foreach(Zira\Config::get('languages') as $language) { + $sitemaps []= Zira\Helper::url($language . '/sitemap.xml', true, true); + } + Zira\View::renderView(array('sitemaps'=>$sitemaps), 'zira/xml/sitemap-index'); + } else { + $rows = Zira\Models\Record::getCollection() + ->select(Zira\Models\Record::getFields()) + ->left_join(Zira\Models\Category::getClass(), array('category_name'=>'name', 'category_access_check'=>'access_check')) + ->where('language','=',Zira\Locale::getLanguage()) + ->and_where('published','=',Zira\Models\Record::STATUS_PUBLISHED) + ->order_by('id','desc') + ->limit(50000) + ->get(); + + $urls = array(); + $home_page_name = Zira\Config::get('home_record_name'); + foreach($rows as $row) { + if ($row->access_check || $row->category_access_check) continue; + if ($home_page_name && $row->name == $home_page_name && $row->category_id == Zira\Category::ROOT_CATEGORY_ID) { + continue; + } + $urls []= Zira\Helper::url(Zira\Page::generateRecordUrl($row->category_name, $row->name), true, true); + } + + Zira\View::renderView(array('urls'=>$urls), 'zira/xml/sitemap'); + } + } + + /** + * RSS feed + */ + public function rss() { + header('Content-type: application/rss+xml; charset=utf-8'); + + if (Zira\Config::get('site_title')) { + $title = Zira\Locale::t(Zira\Config::get('site_title')); + } else if (Zira\Config::get('site_name')) { + $title = Zira\Locale::t(Zira\Config::get('site_name')); + } else { + $title = Zira\Locale::t(DEFAULT_TITLE); + } + if (Zira\Config::get('site_description')) { + $description = Zira\Locale::t(Zira\Config::get('site_description')); + } else if (Zira\Config::get('site_slogan')) { + $description = Zira\Locale::t(Zira\Config::get('site_slogan')); + } else if (Zira\Config::get('site_name')) { + $description = Zira\Locale::t(Zira\Config::get('site_name')); + } else { + $description = Zira\Locale::t(DEFAULT_TITLE); + } + + $rows = Zira\Models\Record::getCollection() + ->select(Zira\Models\Record::getFields()) + ->left_join(Zira\Models\Category::getClass(), array('category_name'=>'name', 'category_title'=>'title', 'category_access_check'=>'access_check')) + ->where('language','=',Zira\Locale::getLanguage()) + ->and_where('published','=',Zira\Models\Record::STATUS_PUBLISHED) + ->order_by('id','desc') + ->limit(20) + ->get(); + + $items = array(); + $home_page_name = Zira\Config::get('home_record_name'); + foreach($rows as $row) { + if ($row->access_check || $row->category_access_check) continue; + if ($home_page_name && $row->name == $home_page_name && $row->category_id == Zira\Category::ROOT_CATEGORY_ID) { + continue; + } + $image = array(); + if ($row->thumb && file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . $row->thumb)) { + $size = @getimagesize(ROOT_DIR . DIRECTORY_SEPARATOR . $row->thumb); + if ($size) { + $image = array( + 'url' => Zira\Helper::baseUrl($row->thumb, true, true), + 'length' => filesize(ROOT_DIR . DIRECTORY_SEPARATOR . $row->thumb), + 'type' => $size['mime'] + ); + } + } + $items []= array( + 'title' => $row->title, + 'url' => Zira\Helper::url(Zira\Page::generateRecordUrl($row->category_name, $row->name), true, true), + 'description' => $row->description, + 'image' => $image, + 'category' => $row->category_title, + 'date' => strtotime($row->creation_date) + ); + } + + Zira\View::renderView(array( + 'title' => $title, + 'url' => Zira\Helper::url('', true, true), + 'description' => $description, + 'logo' => Zira\Config::get('site_logo') ? Zira\Helper::baseUrl(Zira\Config::get('site_logo'),true,true) : '', + 'channel_url' => Zira\Helper::url('rss', true, true), + 'items' => $items + ), 'zira/xml/rss'); + } +} \ No newline at end of file diff --git a/zira/cookie.php b/zira/cookie.php new file mode 100644 index 0000000..9bdb506 --- /dev/null +++ b/zira/cookie.php @@ -0,0 +1,39 @@ +getOffset(); + } + + public static function getOffsetTime() { + return time() + self::getOffset(); + } +} \ No newline at end of file diff --git a/zira/db/implement/collection.php b/zira/db/implement/collection.php new file mode 100644 index 0000000..878317d --- /dev/null +++ b/zira/db/implement/collection.php @@ -0,0 +1,210 @@ + 'table_foreign_key') + * @return array + */ + public static function getReferences(); + + /** + * Loads model from array + * @param $arr + */ + public function loadFromArray($arr); + + /** + * Returns true if model is loaded + * @return mixed + */ + public function loaded(); + + /** + * Loads model from db + * @param $id + */ + public function load($id); + + /** + * Updates row in db + */ + public function save(); + + /** + * Deletes row from db + */ + public function delete(); + + /** + * Getter method + * @param $var + * @return mixed + */ + public function __get($var); + + /** + * Setter method + * @param $var + * @param $val + */ + public function __set($var, $val); + + /** + * Returns Collection object + * @return Collection + */ + public static function getCollection(); + + /** + * Finds first rows in collection + * @param $limit + * @param null $offset + * @param array|null $where + * @return mixed + */ + public static function getFirst($limit, $offset = null, array $where = null); + + /** + * Finds last rows in collection + * @param $limit + * @param null $offset + * @param array|null $where + * @return mixed + */ + public static function getLast($limit, $offset = null, array $where = null); + + /** + * Search rows in collection + * @param $field + * @param $word + * @param $limit + * @param null $offset + * @param array|null $where + * @return mixed + */ + public static function find($field, $word, $limit, $offset = null, array $where = null); + + /** + * Returns model data + * @return array + */ + public function toArray(); +} \ No newline at end of file diff --git a/zira/db/implement/table.php b/zira/db/implement/table.php new file mode 100644 index 0000000..f3682e3 --- /dev/null +++ b/zira/db/implement/table.php @@ -0,0 +1,63 @@ +','<=','>=','<>','LIKE','NOT LIKE','IS','IS NOT','IN'); + + public function __construct($class) { + $this->validClass($class); + $this->_class = $class; + $this->_table = DB_PREFIX . $class::getTable(); + $this->_pk = $class::getPk(); + $this->_alias = $class::getAlias(); + $this->_references = $class::getReferences(); + } + + protected function validClass($class) { + if ( + !method_exists($class,'getTable') || + !method_exists($class,'getPk') || + !method_exists($class,'getAlias') || + !method_exists($class,'getReferences') + ) { + throw new \Exception('Orm class should be passed'); + } + } + + public function select($args) { + if (!is_array($args)) { + $args = func_get_args(); + } + if (!empty($args)) { + foreach($args as $alias=>$arg) { + if (is_int($alias)) $alias = $arg; + $this->_fields []= Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($arg).' as '.Db::escapeIdentifier($alias); + } + } + return $this; + } + + public function update(array $fields) { + foreach($fields as $field=>$value) { + $alias = $this->_alias; +// if (is_int($field) && is_array($value) && (count($value)==2 || count($value)==3)) { +// if (count($value)==3) $alias = $value[2]; +// $field = $value[0]; +// $value = $value[1]; +// } + + $this->_update []= Db::escapeIdentifier($alias).'.'.Db::escapeIdentifier($field). ' = ?'; + $this->_update_data []= $value; + } + return $this; + } + + public function delete() { + $this->_delete = true; + return $this; + } + + public function count($alias = 'co') { + $this->_fields []= 'COUNT(*) as '.Db::escapeIdentifier($alias); + return $this; + } + + public function max($field, $alias = 'mx') { + $_alias = $this->_alias; + if (is_array($field) && count($field)==2) { + $_alias = $field[0]; + $field = $field[1]; + } + $this->_fields []= 'MAX('.Db::escapeIdentifier($_alias).'.'.Db::escapeIdentifier($field).') as '.Db::escapeIdentifier($alias); + return $this; + } + + public function min($field, $alias = 'mn') { + $_alias = $this->_alias; + if (is_array($field) && count($field)==2) { + $_alias = $field[0]; + $field = $field[1]; + } + $this->_fields []= 'MIN('.Db::escapeIdentifier($_alias).'.'.Db::escapeIdentifier($field).') as '.Db::escapeIdentifier($alias); + return $this; + } + + public function join($class, array $select = null) { + $this->validClass($class); + $this->_joins[$class]=array( + 'table' => DB_PREFIX . $class::getTable(), + 'pk' => $class::getPk(), + 'alias' => $class::getAlias(), + 'references' => $class::getReferences() + ); + if (!empty($select)) { + foreach($select as $alias=>$arg) { + if (is_int($alias)) $alias = $arg; + $this->_fields []= Db::escapeIdentifier($class::getAlias()).'.'.Db::escapeIdentifier($arg).' as '.Db::escapeIdentifier($alias); + } + } + return $this; + } + + public function left_join($class, array $select = null) { + $this->validClass($class); + $this->_left_joins[$class]=array( + 'table' => DB_PREFIX . $class::getTable(), + 'pk' => $class::getPk(), + 'alias' => $class::getAlias(), + 'references' => $class::getReferences() + ); + if (!empty($select)) { + foreach($select as $alias=>$arg) { + if (is_int($alias)) $alias = $arg; + $this->_fields []= Db::escapeIdentifier($class::getAlias()).'.'.Db::escapeIdentifier($arg).' as '.Db::escapeIdentifier($alias); + } + } + return $this; + } + + public function right_join($class, array $select = null) { + $this->validClass($class); + $this->_right_joins[$class]=array( + 'table' => DB_PREFIX . $class::getTable(), + 'pk' => $class::getPk(), + 'alias' => $class::getAlias(), + 'references' => $class::getReferences() + ); + if (!empty($select)) { + foreach($select as $alias=>$arg) { + if (is_int($alias)) $alias = $arg; + $this->_fields []= Db::escapeIdentifier($class::getAlias()).'.'.Db::escapeIdentifier($arg).' as '.Db::escapeIdentifier($alias); + } + } + return $this; + } + + public function limit($limit, $offset = null) { + $this->_limit = intval($limit); + if ($offset !== null) $this->_offset = intval($offset); + return $this; + } + + public function where($field, $sign, $value, $alias = null) { + if ($alias === null) $alias = $this->_alias; + if ($field === null) $field = $this->_pk; + $sign = strtoupper($sign); + if (!in_array($sign, $this->_allowed_signs)) { + throw new \Exception('Invalid sign passed'); + } + if ($value !== null) { + if (!is_array($value)) { + $this->_where .= Db::escapeIdentifier($alias) . '.' . Db::escapeIdentifier($field) . ' ' . $sign . ' ?'; + $this->_data[] = $value; + } else { + $this->_where .= Db::escapeIdentifier($alias) . '.' . Db::escapeIdentifier($field) . ' ' . $sign . ' '; + $_sign = ''; + $co = 0; + foreach($value as $_value) { + if ($co>0) $_sign .= ','; + $_sign .= '? '; + $this->_data[] = $_value; + $co++; + } + $this->_where .= '('.$_sign.')'; + } + } else { + $this->_where.=Db::escapeIdentifier($alias).'.'.Db::escapeIdentifier($field).' '.$sign.' NULL'; + } + return $this; + } + + public function and_where($field=null, $sign=null, $value=null, $alias = null) { + $this->_where.=' AND '; + if ($field!==null && $sign!==null) { + return $this->where($field, $sign, $value, $alias); + } + return $this; + } + + public function or_where($field=null, $sign=null, $value=null, $alias = null) { + $this->_where.=' OR '; + if ($field!==null && $sign!==null) { + return $this->where($field, $sign, $value, $alias); + } + return $this; + } + + public function open_where() { + $this->_where.=' ( '; + return $this; + } + + public function close_where() { + $this->_where.=' ) '; + return $this; + } + + public function open_query() { + $this->_query_prefix.=' ( '; + return $this; + } + + public function close_query() { + $this->_query_suffix.=' ) '; + return $this; + } + + public function order_by($field, $order = null) { + if ($field === null) $field = $this->_pk; + if ($order !== null) $order = strtoupper($order); + if ($order != 'DESC') $order = 'ASC'; + $this->_order_by[$field]= $order; + return $this; + } + + public function random() { + $this->_order_by['RAND()']= 'RAND()'; + return $this; + } + + public function group_by($field) { + if ($field === null) $field = $this->_pk; + $this->_group_by[]=$field; + return $this; + } + + public function toString() { + $query = $this->_query_prefix; + if (!empty($this->_update)) { + $query .= 'UPDATE '; + $query .= Db::escapeIdentifier($this->_table) . ' AS ' . Db::escapeIdentifier($this->_alias); + $query .= ' SET ' . implode(', ', $this->_update); + } else if ($this->_delete) { + $query .= 'DELETE '.Db::escapeIdentifier($this->_alias).' FROM '; + if (empty($this->_from)) $query .= Db::escapeIdentifier($this->_table) . ' AS ' . Db::escapeIdentifier($this->_alias); + else $query .= $this->_from; + } else { + $query .= 'SELECT '; + if (empty($this->_fields)) $query .= '*'; + else $query .= implode(', ', $this->_fields); + $query .= ' FROM '; + if (empty($this->_from)) $query .= Db::escapeIdentifier($this->_table) . ' AS ' . Db::escapeIdentifier($this->_alias); + else $query .= $this->_from; + } + $joined = array(); + if (!empty($this->_joins)) { + foreach($this->_joins as $class=>$info) { + $query .= ' LEFT JOIN '.Db::escapeIdentifier($info['table']).' AS '.Db::escapeIdentifier($info['alias']); + if (is_array($info['references']) && isset($info['references'][$this->_class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_pk).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['references'][$this->_class]); + $joined[]=Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['pk']); + } else if (is_array($this->_references) && isset($this->_references[$class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_references[$class]).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['pk']); + $joined[]=Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['pk']); + } else { + throw new \Exception('Failed to join class '.$class); + } + } + } + if (!empty($this->_left_joins)) { + foreach($this->_left_joins as $class=>$info) { + $query .= ' LEFT JOIN '.Db::escapeIdentifier($info['table']).' AS '.Db::escapeIdentifier($info['alias']); + if (is_array($info['references']) && isset($info['references'][$this->_class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_pk).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['references'][$this->_class]); + } else if (is_array($this->_references) && isset($this->_references[$class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_references[$class]).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['pk']); + } else { + throw new \Exception('Failed to join class '.$class); + } + } + } + if (!empty($this->_right_joins)) { + foreach($this->_right_joins as $class=>$info) { + $query .= ' RIGHT JOIN '.Db::escapeIdentifier($info['table']).' AS '.Db::escapeIdentifier($info['alias']); + if (is_array($info['references']) && isset($info['references'][$this->_class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_pk).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['references'][$this->_class]); + } else if (is_array($this->_references) && isset($this->_references[$class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_references[$class]).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['pk']); + } else { + throw new \Exception('Failed to join class '.$class); + } + } + } + $where = ''; + if (!empty($this->_where)) { + $where = ' WHERE ('.$this->_where.')'; + } + if (!empty($joined)) { + foreach($joined as $field) { + if (empty($where)) { + $where .= ' WHERE '.$field.' IS NOT NULL'; + } else { + $where .= ' AND '.$field.' IS NOT NULL'; + } + } + } + $query .= $where; + if (!empty($this->_group_by)) { + $_group = ''; + foreach($this->_group_by as $field) { + if (!empty($_group)) $_group.=', '; + $_group.=Db::escapeIdentifier($field); + } + $query .= ' GROUP BY '.$_group; + } + if (!empty($this->_order_by)) { + $_order = ''; + foreach($this->_order_by as $field=>$order) { + if (!empty($_order)) $_order.=', '; + if ($field == 'RAND()') { + $_order.=$field; + } else { + $_order.=Db::escapeIdentifier($field).' '.$order; + } + } + $query .= ' ORDER BY '.$_order; + } + if ($this->_limit !== null) { + $query .= ' LIMIT '.$this->_limit; + } + if ($this->_offset !== null) { + $query .= ' OFFSET '.$this->_offset; + } + $query .= $this->_query_suffix; + return $query; + } + + public function get($get = null, $as_array=false) { + $stmt = DB::query($this->toString(), $this->_data); + $result = array(); + while ($row=Db::fetch($stmt, $as_array)) { + $result[]=$row; + } + Db::free($stmt); + if ($get === null) { + return $result; + } else if (is_int($get) && isset($result[$get])) { + return $result[$get]; + } else if (is_string($get) && count($result)>0) { + return $result[0]->{$get}; + } else { + return null; + } + } + + public function execute() { + DB::query($this->toString(), array_merge($this->_update_data,$this->_data)); + } + + public function reset() { + $this->_fields = array(); + $this->_joins = array(); + $this->_ons = array(); + $this->_limit = null; + $this->_offset = null; + $this->_where = ''; + $this->_data = array(); + $this->_order_by = array(); + $this->_group_by = array(); + $this->_delete = false; + $this->_update = array(); + $this->_update_data = array(); + $this->_query_prefix = ''; + $this->_query_suffix = ''; + return $this; + } + + public function union() { + $query = $this->toString(); + $data = $this->_data; + $this->reset(); + $this->_data = $data; + $this->_query_prefix = $query . ' UNION '; + return $this; + } + + public function merge($alias = 'sub') { + $query = $this->toString(); + $data = $this->_data; + $this->reset(); + $this->_data = $data; + $this->_from = '(' . $query . ') AS ' . Db::escapeIdentifier($alias); + return $this; + } + + public function __toString() { + return $this->toString(); + } + + public function debug() { + return vsprintf(str_replace('?','\'%s\'',$this->toString()), $this->_data); + } +} \ No newline at end of file diff --git a/zira/db/mysql/db.php b/zira/db/mysql/db.php new file mode 100644 index 0000000..5e7b45a --- /dev/null +++ b/zira/db/mysql/db.php @@ -0,0 +1,94 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + static::$_db->exec('SET NAMES '.MYSQL_CHARSET); + } + + public static function close() { + static::$_db = null; + } + + public static function query($query, array $params = null) { + if ($params === null) $params = array(); + $stmt = static::$_db->prepare($query); + $stmt->execute($params); + self::$_total++; + return $stmt; + } + + public static function fetch($stmt, $as_array = false) { + if (!$as_array) { + return $stmt->fetch(PDO::FETCH_OBJ); + } else { + return $stmt->fetch(PDO::FETCH_ASSOC); + } + } + + public static function free($stmt) { + $stmt->closeCursor(); + } + + public static function lastId() { + return static::$_db->lastInsertId(); + } + + public static function begin() { + return static::$_db->beginTransaction(); + } + + public static function commit() { + return static::$_db->commit(); + } + + public static function rollback() { + return static::$_db->rollback(); + } + + public static function escape($field) { + return static::$_db->quote($field); + } + + public static function escapeIdentifier($identifier) { + return '`'.$identifier.'`'; + } + + public static function getTotal() { + return self::$_total; + } + + public static function version() { + return static::$_db->getAttribute(PDO::ATTR_DRIVER_NAME).' '.static::$_db->getAttribute(PDO::ATTR_SERVER_VERSION); + } + + public static function getTables() { + $stmt = self::query("SHOW TABLES"); + $result = array(); + while ($row=Db::fetch($stmt, true)) { + $result[]=array_values($row)[0]; + } + Db::free($stmt); + return $result; + } +} \ No newline at end of file diff --git a/zira/db/mysql/field.php b/zira/db/mysql/field.php new file mode 100644 index 0000000..9f26d1a --- /dev/null +++ b/zira/db/mysql/field.php @@ -0,0 +1,113 @@ +_table = DB_PREFIX . static::getTable(); + $this->_pk = static::getPk(); + $this->_alias = static::getAlias(); + $this->_id = $id>0 ? $id : null; + if ($this->_id !== null) $this->load($this->_id); + } + + public static function getClass() { + return get_called_class(); + } + + public function load($id) { + $stmt = Db::query('SELECT * FROM '.Db::escapeIdentifier($this->_table).' WHERE '.$this->_pk.'=?', array($id)); + $this->_data = Db::fetch($stmt, true); + if ($this->_data===false) { + $this->_loaded = false; + $this->_data = array(); + } else { + $this->_loaded = true; + } + } + + public function loadFromArray($arr) { + if (array_key_exists($this->_pk, $arr)) { + $this->_id = $arr[$this->_pk]; + $this->_loaded = true; + } else { + $this->_loaded = false; + } + $this->_data = $arr; + } + + public function loaded() { + return $this->_loaded; + } + + public function save() { + if ($this->_id === null) { + $fields = array(); + $values = array(); + $data = array(); + foreach($this->_data as $field=>$value) { + if ($field == $this->_pk) continue; + $fields[]=Db::escapeIdentifier($field); + $values[]='?'; + $data[]=$value; + } + $query = 'INSERT INTO '.Db::escapeIdentifier($this->_table).' ('.implode(', ',$fields).') VALUES ('.implode(', ',$values).')'; + Db::query($query, $data); + $this->_id = Db::lastId(); + $this->_data[$this->_pk] = $this->_id; + } else { + $fields = array(); + $data = array(); + foreach($this->_data as $field=>$value) { + if ($field == $this->_pk) continue; + $data[]=$value; + $fields[]=Db::escapeIdentifier($field).'=?'; + } + $data[]=$this->_id; + $query = 'UPDATE '.Db::escapeIdentifier($this->_table).' SET '.implode(', ',$fields).' WHERE '.$this->_pk.'=?'; + Db::query($query, $data); + } + } + + public function delete() { + if ($this->_id === null) throw new \Exception('Cannot delete object'); + $query = 'DELETE FROM '.Db::escapeIdentifier($this->_table).' WHERE '.$this->_pk.'=?'; + Db::query($query, array($this->_id)); + } + + public function __get($var) { + if (!isset($this->_data[$var])) return null; + return $this->_data[$var]; + } + + public function __set($var, $val) { + $this->_data[$var] = $val; + } + + public static function getCollection() { + return new Collection(get_called_class()); + } + + public static function getFirst($limit, $offset = null, array $where = null) { + $collection = static::getCollection()->limit($limit, $offset); + if ($where !== null) { + $i=0; + foreach($where as $field=>$value) { + if ($i==0) { + $collection->where($field,'=',$value); + } else { + $collection->and_where($field,'=',$value); + } + $i++; + } + } + return $collection->order_by(null, 'ASC')->get(); + } + + public static function getLast($limit, $offset = null, array $where = null) { + $collection = static::getCollection()->limit($limit, $offset); + if ($where !== null) { + $i=0; + foreach($where as $field=>$value) { + if ($i==0) { + $collection->where($field,'=',$value); + } else { + $collection->and_where($field,'=',$value); + } + $i++; + } + } + return $collection->order_by(null, 'DESC')->get(); + } + + public static function find($field, $word, $limit, $offset = null, array $where = null) { + $collection = static::getCollection()->where(static::getAlias().'.'.$field, 'LIKE', '%'.$word.'%'); + if ($where !== null) { + foreach($where as $field=>$value) { + $collection->and_where($field,'=',$value); + } + } + return $collection->limit($limit, $offset)->order_by(null, 'DESC')->get(); + } + + public function toArray() { + return $this->_data; + } +} \ No newline at end of file diff --git a/zira/db/mysql/table.php b/zira/db/mysql/table.php new file mode 100644 index 0000000..d360b31 --- /dev/null +++ b/zira/db/mysql/table.php @@ -0,0 +1,138 @@ +_table = DB_PREFIX . $table_name; + } + + public function getName() { + return $this->_table; + } + + public function getKeys() { + return array(); + } + + public function getUnique() { + return array(); + } + + public function getDefaults() { + return array(); + } + + public function getEngine() { + return $this->_engine; + } + + public function getCharset() { + return $this->_charset; + } + + public function setEngine($engine) { + $this->_engine = $engine; + } + + public function setCharset($charset) { + $this->_charset = $charset; + } + + public function __toString() { + $primary = null; + $fields = array(); + foreach((array)$this->getFields() as $name=>$type) { + if ($type == Field::primary()) $primary = $name; + $fields[]= Db::escapeIdentifier($name).' '.$type; + } + if ($primary!==null) { + $fields[]='PRIMARY KEY ('.Db::escapeIdentifier($primary).')'; + } + foreach((array)$this->getKeys() as $name=>$keys) { + $index='KEY '.Db::escapeIdentifier($name).' ( '; + if (is_string($keys)) $index .= Db::escapeIdentifier($keys); + else if (is_array($keys)) { + for($i=0; $igetUnique() as $name=>$keys) { + $index='UNIQUE KEY '.Db::escapeIdentifier($name).' ( '; + if (is_string($keys)) $index .= Db::escapeIdentifier($keys); + else if (is_array($keys)) { + for($i=0; $i_table).' ( '; + $sql .= implode(', ', $fields); + $sql .= ' ) ENGINE='.$this->getEngine().' DEFAULT CHARSET='.$this->getCharset(); + + return $sql; + } + + public function install() { + // creating table + $query = (string)$this; + Db::query($query); + // inserting default values + foreach((array)$this->getDefaults() as $insert) { + $fields = array(); + $values = array(); + $data = array(); + foreach($insert as $field=>$value) { + $fields[]=Db::escapeIdentifier($field); + $values[]='?'; + $data[]=$value; + } + $query = 'INSERT INTO '.Db::escapeIdentifier($this->_table).' ('.implode(', ',$fields).') VALUES ('.implode(', ',$values).')'; + Db::query($query, $data); + } + } + + public function uninstall() { + $query = 'DROP TABLE IF EXISTS '.DB::escapeIdentifier($this->_table); + Db::query($query); + } + + public function dump($delimiter) { + $sql = ''; + $stmt = DB::query('SELECT * FROM '.DB::escapeIdentifier($this->_table)); + while ($row=Db::fetch($stmt,true)) { + $columns = array_keys($row); + for($i=0; $i_table).' ('.implode(', ',$columns).') VALUES ('.implode(', ',$values).');'.$delimiter; + } + Db::free($stmt); + return $sql; + } +} \ No newline at end of file diff --git a/zira/db/sqlite.collection.php b/zira/db/sqlite.collection.php new file mode 100644 index 0000000..7cc576b --- /dev/null +++ b/zira/db/sqlite.collection.php @@ -0,0 +1,12 @@ +','<=','>=','<>','LIKE','NOT LIKE','IS','IS NOT','IN'); + + public function __construct($class) { + $this->validClass($class); + $this->_class = $class; + $this->_table = DB_PREFIX . $class::getTable(); + $this->_pk = $class::getPk(); + //$this->_alias = $class::getAlias(); + $this->_alias = $this->_table; + $this->_references = $class::getReferences(); + } + + protected function validClass($class) { + if ( + !method_exists($class,'getTable') || + !method_exists($class,'getPk') || + !method_exists($class,'getAlias') || + !method_exists($class,'getReferences') + ) { + throw new \Exception('Orm class should be passed'); + } + } + + public function select($args) { + if (!is_array($args)) { + $args = func_get_args(); + } + if (!empty($args)) { + foreach($args as $alias=>$arg) { + if (is_int($alias)) $alias = $arg; + $this->_fields []= Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($arg).' as '.Db::escapeIdentifier($alias); + } + } + return $this; + } + + public function update(array $fields) { + foreach($fields as $field=>$value) { +// $alias = $this->_alias; +// if (is_int($field) && is_array($value) && (count($value)==2 || count($value)==3)) { +// if (count($value)==3) $alias = $value[2]; +// $field = $value[0]; +// $value = $value[1]; +// } + $this->_update []= Db::escapeIdentifier($field). ' = ?'; + $this->_update_data []= $value; + } + return $this; + } + + public function delete() { + $this->_delete = true; + return $this; + } + + public function count($alias = 'co') { + $this->_fields []= 'COUNT(*) as '.Db::escapeIdentifier($alias); + return $this; + } + + public function max($field, $alias = 'mx') { + $_alias = $this->_alias; + if (is_array($field) && count($field)==2) { + $_alias = $field[0]; + $field = $field[1]; + } + $this->_fields []= 'MAX('.Db::escapeIdentifier($_alias).'.'.Db::escapeIdentifier($field).') as '.Db::escapeIdentifier($alias); + return $this; + } + + public function min($field, $alias = 'mn') { + $_alias = $this->_alias; + if (is_array($field) && count($field)==2) { + $_alias = $field[0]; + $field = $field[1]; + } + $this->_fields []= 'MIN('.Db::escapeIdentifier($_alias).'.'.Db::escapeIdentifier($field).') as '.Db::escapeIdentifier($alias); + return $this; + } + + public function join($class, array $select = null) { + $this->validClass($class); + $this->_joins[$class]=array( + 'table' => DB_PREFIX . $class::getTable(), + 'pk' => $class::getPk(), + 'alias' => $class::getAlias(), + 'references' => $class::getReferences() + ); + if (!empty($select)) { + foreach($select as $alias=>$arg) { + if (is_int($alias)) $alias = $arg; + $this->_fields []= Db::escapeIdentifier($class::getAlias()).'.'.Db::escapeIdentifier($arg).' as '.Db::escapeIdentifier($alias); + } + } + return $this; + } + + public function left_join($class, array $select = null) { + $this->validClass($class); + $this->_left_joins[$class]=array( + 'table' => DB_PREFIX . $class::getTable(), + 'pk' => $class::getPk(), + 'alias' => $class::getAlias(), + 'references' => $class::getReferences() + ); + if (!empty($select)) { + foreach($select as $alias=>$arg) { + if (is_int($alias)) $alias = $arg; + $this->_fields []= Db::escapeIdentifier($class::getAlias()).'.'.Db::escapeIdentifier($arg).' as '.Db::escapeIdentifier($alias); + } + } + return $this; + } + + public function right_join($class, array $select = null) { + $this->validClass($class); + $this->_right_joins[$class]=array( + 'table' => DB_PREFIX . $class::getTable(), + 'pk' => $class::getPk(), + 'alias' => $class::getAlias(), + 'references' => $class::getReferences() + ); + if (!empty($select)) { + foreach($select as $alias=>$arg) { + if (is_int($alias)) $alias = $arg; + $this->_fields []= Db::escapeIdentifier($class::getAlias()).'.'.Db::escapeIdentifier($arg).' as '.Db::escapeIdentifier($alias); + } + } + return $this; + } + + public function limit($limit, $offset = null) { + if ($this->_union_query_opened) return $this; + $this->_limit = intval($limit); + if ($offset !== null) $this->_offset = intval($offset); + return $this; + } + + public function where($field, $sign, $value, $alias = null) { + if ($alias === null) $alias = $this->_alias; + if ($field === null) $field = $this->_pk; + $sign = strtoupper($sign); + if (!in_array($sign, $this->_allowed_signs)) { + throw new \Exception('Invalid sign passed'); + } + if ($value !== null) { + if (!is_array($value)) { + $this->_where .= Db::escapeIdentifier($alias) . '.' . Db::escapeIdentifier($field) . ' ' . $sign . ' ?'; + $this->_data[] = $value; + } else { + $this->_where .= Db::escapeIdentifier($alias) . '.' . Db::escapeIdentifier($field) . ' ' . $sign . ' '; + $_sign = ''; + $co = 0; + foreach($value as $_value) { + if ($co>0) $_sign .= ','; + $_sign .= '? '; + $this->_data[] = $_value; + $co++; + } + $this->_where .= '('.$_sign.')'; + } + } else { + $this->_where.=Db::escapeIdentifier($alias).'.'.Db::escapeIdentifier($field).' '.$sign.' NULL'; + } + return $this; + } + + public function and_where($field=null, $sign=null, $value=null, $alias = null) { + $this->_where.=' AND '; + if ($field!==null && $sign!==null) { + return $this->where($field, $sign, $value, $alias); + } + return $this; + } + + public function or_where($field=null, $sign=null, $value=null, $alias = null) { + $this->_where.=' OR '; + if ($field!==null && $sign!==null) { + return $this->where($field, $sign, $value, $alias); + } + return $this; + } + + public function open_where() { + $this->_where.=' ( '; + return $this; + } + + public function close_where() { + $this->_where.=' ) '; + return $this; + } + + public function open_query() { + $this->_union_query_opened = true; + //$this->_query_prefix.=' ( '; + return $this; + } + + public function close_query() { + //$this->_query_suffix.=' ) '; + return $this; + } + + public function order_by($field, $order = null) { + if ($this->_union_query_opened) return $this; + if ($field === null) $field = $this->_pk; + if ($order !== null) $order = strtoupper($order); + if ($order != 'DESC') $order = 'ASC'; + $this->_order_by[$field]= $order; + return $this; + } + + public function random() { + $this->_order_by['RANDOM()']= 'RANDOM()'; + return $this; + } + + public function group_by($field) { + if ($this->_union_query_opened) return $this; + if ($field === null) $field = $this->_pk; + $this->_group_by[]=$field; + return $this; + } + + public function toString() { + $query = $this->_query_prefix; + if (!empty($this->_update)) { + $query .= 'UPDATE '; + $query .= Db::escapeIdentifier($this->_table); + $query .= ' SET ' . implode(', ', $this->_update); + } else if ($this->_delete) { + $query .= 'DELETE FROM '; + if (empty($this->_from)) $query .= Db::escapeIdentifier($this->_table); + else $query .= $this->_from; + } else { + $query .= 'SELECT '; + if (empty($this->_fields)) $query .= '*'; + else $query .= implode(', ', $this->_fields); + $query .= ' FROM '; + if (empty($this->_from)) $query .= Db::escapeIdentifier($this->_table) . ' AS ' . Db::escapeIdentifier($this->_alias); + else $query .= $this->_from; + } + $joined = array(); + if (!empty($this->_joins)) { + foreach($this->_joins as $class=>$info) { + $query .= ' LEFT JOIN '.Db::escapeIdentifier($info['table']).' AS '.Db::escapeIdentifier($info['alias']); + if (is_array($info['references']) && isset($info['references'][$this->_class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_pk).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['references'][$this->_class]); + $joined[]=Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['pk']); + } else if (is_array($this->_references) && isset($this->_references[$class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_references[$class]).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['pk']); + $joined[]=Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['pk']); + } else { + throw new \Exception('Failed to join class '.$class); + } + } + } + if (!empty($this->_left_joins)) { + foreach($this->_left_joins as $class=>$info) { + $query .= ' LEFT JOIN '.Db::escapeIdentifier($info['table']).' AS '.Db::escapeIdentifier($info['alias']); + if (is_array($info['references']) && isset($info['references'][$this->_class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_pk).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['references'][$this->_class]); + } else if (is_array($this->_references) && isset($this->_references[$class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_references[$class]).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['pk']); + } else { + throw new \Exception('Failed to join class '.$class); + } + } + } + if (!empty($this->_right_joins)) { + foreach($this->_right_joins as $class=>$info) { + $query .= ' RIGHT JOIN '.Db::escapeIdentifier($info['table']).' AS '.Db::escapeIdentifier($info['alias']); + if (is_array($info['references']) && isset($info['references'][$this->_class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_pk).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['references'][$this->_class]); + } else if (is_array($this->_references) && isset($this->_references[$class])) { + $query .= ' ON '.Db::escapeIdentifier($this->_alias).'.'.Db::escapeIdentifier($this->_references[$class]).' = '.Db::escapeIdentifier($info['alias']).'.'.Db::escapeIdentifier($info['pk']); + } else { + throw new \Exception('Failed to join class '.$class); + } + } + } + $where = ''; + if (!empty($this->_where)) { + $where = ' WHERE ('.$this->_where.')'; + } + if (!empty($joined)) { + foreach($joined as $field) { + if (empty($where)) { + $where .= ' WHERE '.$field.' IS NOT NULL'; + } else { + $where .= ' AND '.$field.' IS NOT NULL'; + } + } + } + $query .= $where; + if (!empty($this->_group_by)) { + $_group = ''; + foreach($this->_group_by as $field) { + if (!empty($_group)) $_group.=', '; + $_group.=Db::escapeIdentifier($field); + } + $query .= ' GROUP BY '.$_group; + } + if (!empty($this->_order_by)) { + $_order = ''; + foreach($this->_order_by as $field=>$order) { + if (!empty($_order)) $_order.=', '; + if ($field == 'RANDOM()') { + $_order.=$field; + } else { + $_order.=Db::escapeIdentifier($field).' '.$order; + } + } + $query .= ' ORDER BY '.$_order; + } + if ($this->_limit !== null) { + $query .= ' LIMIT '.$this->_limit; + } + if ($this->_offset !== null) { + $query .= ' OFFSET '.$this->_offset; + } + $query .= $this->_query_suffix; + return $query; + } + + public function get($get = null, $as_array=false) { + $stmt = DB::query($this->toString(), $this->_data); + $result = array(); + while ($row=Db::fetch($stmt, $as_array)) { + $result[]=$row; + } + Db::free($stmt); + if ($get === null) { + return $result; + } else if (is_int($get) && isset($result[$get])) { + return $result[$get]; + } else if (is_string($get) && count($result)>0) { + return $result[0]->{$get}; + } else { + return null; + } + } + + public function execute() { + DB::query($this->toString(), array_merge($this->_update_data,$this->_data)); + } + + public function reset() { + $this->_fields = array(); + $this->_joins = array(); + $this->_ons = array(); + $this->_limit = null; + $this->_offset = null; + $this->_where = ''; + $this->_data = array(); + $this->_order_by = array(); + $this->_group_by = array(); + $this->_delete = false; + $this->_update = array(); + $this->_update_data = array(); + $this->_query_prefix = ''; + $this->_query_suffix = ''; + return $this; + } + + public function union() { + $query = $this->toString(); + $data = $this->_data; + $this->reset(); + $this->_data = $data; + $this->_query_prefix = $query . ' UNION '; + $this->_union_query_opened = false; + return $this; + } + + public function merge($alias = 'sub') { + $query = $this->toString(); + $data = $this->_data; + $this->reset(); + $this->_data = $data; + $this->_from = '(' . $query . ') AS ' . Db::escapeIdentifier($alias); + $this->_union_query_opened = false; + return $this; + } + + public function __toString() { + return $this->toString(); + } + + public function debug() { + return vsprintf(str_replace('?','\'%s\'',$this->toString()), $this->_data); + } +} \ No newline at end of file diff --git a/zira/db/sqlite/db.php b/zira/db/sqlite/db.php new file mode 100644 index 0000000..8a0052f --- /dev/null +++ b/zira/db/sqlite/db.php @@ -0,0 +1,88 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } + + public static function close() { + static::$_db = null; + } + + public static function query($query, array $params = null) { + if ($params === null) $params = array(); + $stmt = static::$_db->prepare($query); + $stmt->execute($params); + self::$_total++; + return $stmt; + } + + public static function fetch($stmt, $as_array = false) { + if (!$as_array) { + return $stmt->fetch(PDO::FETCH_OBJ); + } else { + return $stmt->fetch(PDO::FETCH_ASSOC); + } + } + + public static function free($stmt) { + $stmt->closeCursor(); + } + + public static function lastId() { + return static::$_db->lastInsertId(); + } + + public static function begin() { + return static::$_db->beginTransaction(); + } + + public static function commit() { + return static::$_db->commit(); + } + + public static function rollback() { + return static::$_db->rollback(); + } + + public static function escape($field) { + return static::$_db->quote($field); + } + + public static function escapeIdentifier($identifier) { + return '"'.$identifier.'"'; + } + + public static function getTotal() { + return self::$_total; + } + + public static function version() { + return static::$_db->getAttribute(PDO::ATTR_DRIVER_NAME).' '.static::$_db->getAttribute(PDO::ATTR_SERVER_VERSION); + } + + public static function getTables() { + $stmt = self::query("SELECT name FROM sqlite_master WHERE type='table'"); + $result = array(); + while ($row=Db::fetch($stmt, true)) { + $result[]=array_values($row)[0]; + } + Db::free($stmt); + return $result; + } +} \ No newline at end of file diff --git a/zira/db/sqlite/field.php b/zira/db/sqlite/field.php new file mode 100644 index 0000000..2734e75 --- /dev/null +++ b/zira/db/sqlite/field.php @@ -0,0 +1,93 @@ +_table = DB_PREFIX . static::getTable(); + $this->_pk = static::getPk(); + $this->_alias = static::getAlias(); + $this->_id = $id>0 ? $id : null; + if ($this->_id !== null) $this->load($this->_id); + } + + public static function getClass() { + return get_called_class(); + } + + public function load($id) { + $stmt = Db::query('SELECT * FROM '.Db::escapeIdentifier($this->_table).' WHERE '.$this->_pk.'=?', array($id)); + $this->_data = Db::fetch($stmt, true); + if ($this->_data===false) { + $this->_loaded = false; + $this->_data = array(); + } else { + $this->_loaded = true; + } + } + + public function loadFromArray($arr) { + if (array_key_exists($this->_pk, $arr)) { + $this->_id = $arr[$this->_pk]; + $this->_loaded = true; + } else { + $this->_loaded = false; + } + $this->_data = $arr; + } + + public function loaded() { + return $this->_loaded; + } + + public function save() { + if ($this->_id === null) { + $fields = array(); + $values = array(); + $data = array(); + foreach($this->_data as $field=>$value) { + if ($field == $this->_pk) continue; + $fields[]=Db::escapeIdentifier($field); + $values[]='?'; + $data[]=$value; + } + $query = 'INSERT INTO '.Db::escapeIdentifier($this->_table).' ('.implode(', ',$fields).') VALUES ('.implode(', ',$values).')'; + Db::query($query, $data); + $this->_id = Db::lastId(); + $this->_data[$this->_pk] = $this->_id; + } else { + $fields = array(); + $data = array(); + foreach($this->_data as $field=>$value) { + if ($field == $this->_pk) continue; + $data[]=$value; + $fields[]=Db::escapeIdentifier($field).'=?'; + } + $data[]=$this->_id; + $query = 'UPDATE '.Db::escapeIdentifier($this->_table).' SET '.implode(', ',$fields).' WHERE '.$this->_pk.'=?'; + Db::query($query, $data); + } + } + + public function delete() { + if ($this->_id === null) throw new \Exception('Cannot delete object'); + $query = 'DELETE FROM '.Db::escapeIdentifier($this->_table).' WHERE '.$this->_pk.'=?'; + Db::query($query, array($this->_id)); + } + + public function __get($var) { + if (!isset($this->_data[$var])) return null; + return $this->_data[$var]; + } + + public function __set($var, $val) { + $this->_data[$var] = $val; + } + + public static function getCollection() { + return new Collection(get_called_class()); + } + + public static function getFirst($limit, $offset = null, array $where = null) { + $collection = static::getCollection()->limit($limit, $offset); + if ($where !== null) { + $i=0; + foreach($where as $field=>$value) { + if ($i==0) { + $collection->where($field,'=',$value); + } else { + $collection->and_where($field,'=',$value); + } + $i++; + } + } + return $collection->order_by(null, 'ASC')->get(); + } + + public static function getLast($limit, $offset = null, array $where = null) { + $collection = static::getCollection()->limit($limit, $offset); + if ($where !== null) { + $i=0; + foreach($where as $field=>$value) { + if ($i==0) { + $collection->where($field,'=',$value); + } else { + $collection->and_where($field,'=',$value); + } + $i++; + } + } + return $collection->order_by(null, 'DESC')->get(); + } + + public static function find($field, $word, $limit, $offset = null, array $where = null) { + $collection = static::getCollection()->where(static::getAlias().'.'.$field, 'LIKE', '%'.$word.'%'); + if ($where !== null) { + foreach($where as $field=>$value) { + $collection->and_where($field,'=',$value); + } + } + return $collection->limit($limit, $offset)->order_by(null, 'DESC')->get(); + } + + public function toArray() { + return $this->_data; + } +} \ No newline at end of file diff --git a/zira/db/sqlite/table.php b/zira/db/sqlite/table.php new file mode 100644 index 0000000..406e5fa --- /dev/null +++ b/zira/db/sqlite/table.php @@ -0,0 +1,143 @@ +_table = DB_PREFIX . $table_name; + } + + public function getName() { + return $this->_table; + } + + public function getKeys() { + return array(); + } + + public function getUnique() { + return array(); + } + + public function getDefaults() { + return array(); + } + + public function getCharset() { + return $this->_charset; + } + + public function setCharset($charset) { + $this->_charset = $charset; + } + + protected function _getCreateTableSQL() { + $fields = array(); + foreach((array)$this->getFields() as $name=>$type) { + $fields[]= Db::escapeIdentifier($name).' '.$type; + } + + $sql = 'CREATE TABLE '.DB::escapeIdentifier($this->_table).' ( '; + $sql .= implode(', ', $fields); + $sql .= ' )'; + + return $sql; + } + + protected function _getCreateIndexSQL($name, $keys, $unique = false) { + $index=' ( '; + if (is_string($keys)) $index .= Db::escapeIdentifier($keys); + else if (is_array($keys)) { + for($i=0; $i_table.'_'.$name).' ON '.DB::escapeIdentifier($this->_table).$index; + + return $sql; + } + + public function createIndexes() { + foreach((array)$this->getKeys() as $name=>$keys) { + $sql = $this->_getCreateIndexSQL($name, $keys); + Db::query($sql); + } + foreach((array)$this->getUnique() as $name=>$keys) { + $sql = $this->_getCreateIndexSQL($name, $keys, true); + Db::query($sql); + } + } + + public function __toString() { + $sql = $this->_getCreateTableSQL().';'; + foreach((array)$this->getKeys() as $name=>$keys) { + $sql .= "\r\n". $this->_getCreateIndexSQL($name, $keys); + } + foreach((array)$this->getUnique() as $name=>$keys) { + $sql .= "\r\n". $this->_getCreateIndexSQL($name, $keys, true); + } + return $sql; + } + + public function install() { + // setting encoding + Db::query('PRAGMA encoding = "'.$this->getCharset().'"'); + // creating table + $query = $this->_getCreateTableSQL(); + Db::query($query); + // creating indexes + $this->createIndexes(); + // inserting default values + foreach((array)$this->getDefaults() as $insert) { + $fields = array(); + $values = array(); + $data = array(); + foreach($insert as $field=>$value) { + $fields[]=Db::escapeIdentifier($field); + $values[]='?'; + $data[]=$value; + } + $query = 'INSERT INTO '.Db::escapeIdentifier($this->_table).' ('.implode(', ',$fields).') VALUES ('.implode(', ',$values).')'; + Db::query($query, $data); + } + } + + public function uninstall() { + $query = 'DROP TABLE IF EXISTS '.DB::escapeIdentifier($this->_table); + Db::query($query); + } + + public function dump($delimiter) { + $sql = ''; + $stmt = DB::query('SELECT * FROM '.DB::escapeIdentifier($this->_table)); + while ($row=Db::fetch($stmt,true)) { + $columns = array_keys($row); + for($i=0; $i_table).' ('.implode(', ',$columns).') VALUES ('.implode(', ',$values).');'.$delimiter; + } + Db::free($stmt); + return $sql; + } +} \ No newline at end of file diff --git a/zira/file.php b/zira/file.php new file mode 100644 index 0000000..f7f588a --- /dev/null +++ b/zira/file.php @@ -0,0 +1,86 @@ +$tmp_name) { + if (empty($tmp_name)) continue; + if (!isset($file['name'][$i]) || empty($file['name'][$i])) continue; + $files[$tmp_name] = $file['name'][$i]; + } + } else if (is_string($file['name']) && is_string($file['tmp_name'])) { + $files[$file['tmp_name']] = $file['name']; + } else { + return false; + } + + if (empty($files)) return false; + + $savedir = self::getAbsolutePath($dir); + + $_files = array(); + foreach($files as $path=>$name) { + $prefix = 0; + do { + $_f = self::getFileName($name, $prefix); + $f = $savedir . DIRECTORY_SEPARATOR . $_f; + $prefix++; + } while(file_exists($f)); + + if (!copy($path, $f)) return false; + $_files[$f] = $_f; + } + + return $_files; + } + + public static function getFileArray($path) { + return array( + 'name' => basename($path), + 'tmp_name' => $path + ); + } +} \ No newline at end of file diff --git a/zira/form.php b/zira/form.php new file mode 100644 index 0000000..79dddf3 --- /dev/null +++ b/zira/form.php @@ -0,0 +1,75 @@ +_init(); + + if ($this->_ajax) { + View::addScript('upload.inc.js'); + View::addScript('upload.js'); + } + } + + abstract protected function _init(); + abstract protected function _render(); + abstract protected function _validate(); + + protected function _update_values() { + if ($this->_method == Request::GET) { + $this->_request_values = Request::get(); + } else if ($this->_method == Request::POST) { + if (!$this->_multipart) { + $this->_request_values = Request::post(); + } else { + $this->_request_values = array_merge(Request::post(), Request::file()); + } + } + } + + public function getValue($name, $default = null) { + $_name = $this->getFieldName($name); + $request_value = isset($this->_request_values[$_name]) ? $this->_request_values[$_name] : null; + if ($request_value !== null) return $request_value; + if (isset($this->_values[$name])) return $this->_values[$name]; + return $default; + } + + public function setValue($name, $value) { + $_name = Form\Form::getFieldName($this->_token, $name); + if (isset($this->_request_values[$_name])) $this->_request_values[$_name] = $value; + $this->_values[$name] = $value; + } + + public function updateValues(array $values) { + foreach($values as $key=>$value) { + $this->setValue($key, $value); + $_name = Form\Form::getFieldName($this->_token, $key); + if ($this->_method == Request::POST) { + Request::setPost($_name, $value); + } else if ($this->_method == Request::GET) { + Request::setGet($_name, $value); + } + } + } + + public function isValid() { + $this->_update_values(); + $this->_validate(); + $result = $this->validate(); + return $result; + } + + public function __toString() { + return $this->_render(); + } +} \ No newline at end of file diff --git a/zira/form/factory.php b/zira/form/factory.php new file mode 100644 index 0000000..569075b --- /dev/null +++ b/zira/form/factory.php @@ -0,0 +1,709 @@ +_id = $id; + $this->_url = $url; + $this->_method = $method; + $this->_token = Form::getToken($this->_id, $this->_is_token_unique); + $this->_validator = new Validator(); + $this->_validator->setToken($this->_token); + if ($this->_multipart) $this->_validator->setMultipart(true); + } + + public function setValues(array $values) { + $this->_values = $values; + } + + public function setAjax($ajax) { + $this->_ajax = (bool) $ajax; + } + + public function setUrl($url) { + $this->_url = $url; + } + + public function setMethod($method) { + $this->_method = $method; + } + + public function setMultipart($multipart) { + $this->_multipart = (bool)$multipart; + $this->_validator->setMultipart($multipart); + } + + public function setFill($fill) { + $this->_fill = (bool) $fill; + } + + public function getToken() { + return $this->_token; + } + + public function setTitle($title) { + $this->_title = $title; + } + + public function setMessage($message) { + $this->_message = $message; + } + + public function setError($error) { + $this->_error = $error; + } + + public function setInfo($info) { + $this->_info = $info; + } + + public function setDescription($description) { + $this->_description = $description; + } + + public function getUrl() { + return $this->_url; + } + + public function getMethod() { + return $this->_method; + } + + public function getTitle() { + return $this->_title; + } + + public function getMessage() { + return $this->_message; + } + + public function getError() { + return $this->_error; + } + + public function getInfo() { + return $this->_info; + } + + public function getDescription() { + return $this->_description; + } + + public function setRenderPanel ($render_panel) { + $this->_render_panel = $render_panel; + } + + public function setWrapElements ($wrap_elements) { + $this->_wrap_elements = $wrap_elements; + } + + public function setFormClass($class) { + $this->_form_class = $class; + } + + public function setGroupClass($class) { + $this->_group_class = $class; + } + + public function setInputGroupClass($class) { + $this->_input_group_class = $class; + } + + public function setInputGroupAddonClass($class) { + $this->_input_group_addon_class = $class; + } + + public function setInputGroupButtonClass($class) { + $this->_input_group_button_class = $class; + } + + public function setInputClass($class) { + $this->_input_class = $class; + } + + public function setLabelClass($class) { + $this->_label_class = $class; + } + + public function setInputWrapClass($class) { + $this->_input_wrap_class = $class; + } + + public function setInputOffsetWrapClass($class) { + $this->_input_offset_wrap_class = $class; + } + + public function setCheckboxWrapClass($class) { + $this->_checkbox_wrap_class = $class; + } + + public function setRadioWrapClass($class) { + $this->_radio_wrap_class = $class; + } + + public function setButtonGroupClass($class) { + $this->_button_group_class = $class; + } + + public function setButtonClass($class) { + $this->_button_class = $class; + } + + public function setSubmitClass($class) { + $this->_submit_class = $class; + } + + public function setSelectWrapClass($class) { + $this->_select_wrapper_class = $class; + } + + public function setDropdownClass($class) { + $this->_dropdown_class = $class; + } + + public function setDropdownMenuClass($class) { + $this->_dropdown_menu_class = $class; + } + + public function setCaptchaWrapClass($class) { + $this->_captcha_wrapper_class = $class; + } + + public function setCaptchaImageWrapClass($class) { + $this->_captcha_image_wrapper_class = $class; + } + + public function setCaptchaRefreshWrapClass($class) { + $this->_captcha_refresh_wrapper_class = $class; + } + + public function setCaptchaInputWrapClass($class) { + $this->_captcha_input_wrapper_class = $class; + } + + public function setCaptchaRefreshIcoClass($class) { + $this->_captcha_refresh_ico_class = $class; + } + + public function setPanelClass($class) { + $this->_panel_class = $class; + } + + public function setPanelHeadingClass($class) { + $this->_panel_heading_class = $class; + } + + public function setPanelTitleClass($class) { + $this->_panel_title_class = $class; + } + + public function setPanelBodyClass($class) { + $this->_panel_body_class = $class; + } + + public function setPanelFooterClass($class) { + $this->_panel_footer_class = $class; + } + + public function setAlertSuccessClass($class) { + $this->_alert_success_class = $class; + } + + public function setAlertErrorClass($class) { + $this->_alert_error_class = $class; + } + + public function setAlertInfoClass($class) { + $this->_alert_info_class = $class; + } + + public function setAjaxFormClass($class) { + $this->_ajax_form_class = $class; + } + + public function getValidator() { + return $this->_validator; + } + + public function isErrorField($field) { + $error_field = $this->getValidator()->getErrorField(); + if (!empty($error_field) && $error_field==$field) return true; + return false; + } + + public function getId() { + return 'form-'.$this->_id; + } + + public function getFieldName($name) { + return Form::getFieldName($this->_token, $name); + } + + public function open(array $attributes = null) { + if (!$this->_url) $this->_url = Zira\Router::getRequest(); + + if ($this->_ajax) { + $this->_form_class .= ' '.$this->_ajax_form_class; + + if (strpos($this->_url,'?')!==false) $this->_url .= '&'; + else $this->_url .= '?'; + + $this->_url .= FORMAT_GET_VAR.'='.FORMAT_JSON; + } + $prefix = ''; + $prefix .= $this->get_alerts(); + if ($this->_render_panel) { + $prefix .= Helper::tag_open('div', array('class'=>$this->_panel_class)); + $prefix .= Helper::tag_open('div', array('class'=>$this->_panel_heading_class)); + if (!empty($this->_title)) { + $prefix .= Helper::tag('h2', $this->_title, array('class'=>$this->_panel_title_class)); + } + $prefix .= Helper::tag_close('div'); + $prefix .= Helper::tag_open('div', array('class'=>$this->_panel_body_class)); + if (!empty($this->_description)) { + $prefix .= Helper::html($this->_description); + } + $prefix .= Helper::tag_close('div'); + $prefix .= Helper::tag_open('div', array('class'=>$this->_panel_footer_class)); + } + + if (!$attributes) $attributes = array(); + if (!isset($attributes['class'])) $attributes['class'] = $this->_form_class; + $attributes['id'] = $this->getId(); + return $prefix.Form::open($this->_url,$this->_method, $this->_multipart, $attributes); + } + + protected function get_alerts() { + $html = ''; + if (!empty($this->_message)) { + $html .= Helper::tag('div',$this->_message,array('class'=>$this->_alert_success_class)); + } + if (!empty($this->_error)) { + $html .= Helper::tag('div',$this->_error,array('class'=>$this->_alert_error_class)); + } + if (!empty($this->_info)) { + $html .= Helper::tag('div',$this->_info,array('class'=>$this->_alert_info_class)); + } + return $html; + } + + public function close() { + $prefix = ''; + if ($this->_render_panel) { + $prefix .= Helper::tag_close('div'); + $prefix .= Helper::tag_close('div'); + } + return $prefix.Form::close(); + } + + public function wrap($element, $class = null) { + if (!$this->_wrap_elements) return $element; + if (!$class) $class = $this->_group_class; + $html = Helper::tag_open('div',array('class'=>$class)); + $html .= $element; + $html .= Helper::tag_close('div'); + return $html; + } + + public function input($label, $name, array $attributes = null) { + $value = isset($this->_values[$name]) ? $this->_values[$name] : null; + if (!$attributes) $attributes = array(); + if (!isset($attributes['class'])) $attributes['class'] = $this->_input_class; + if ($this->isErrorField($name)) $attributes['class'] .= ' '.$this->_field_error_class; + $label = Form::label($label, $name, array('class'=>$this->_label_class)); + $field = Form::input($this->_token, $name, $value, $attributes, $this->_fill); + if (isset($attributes['title'])) { + $field .= Helper::tag('p', $attributes['title'], array('class'=>$this->_help_class)); + } + return $this->wrap($label.$this->wrap($field,$this->_input_wrap_class)); + } + + public function password($label, $name, array $attributes = null) { + $value = isset($this->_values[$name]) ? $this->_values[$name] : null; + if (!$attributes) $attributes = array(); + if (!isset($attributes['class'])) $attributes['class'] = $this->_input_class; + if ($this->isErrorField($name)) $attributes['class'] .= ' '.$this->_field_error_class; + $label = Form::label($label, $name, array('class'=>$this->_label_class)); + $field = Form::password($this->_token, $name, $value, $attributes); + if (isset($attributes['title'])) { + $field .= Helper::tag('p', $attributes['title'], array('class'=>$this->_help_class)); + } + return $this->wrap($label.$this->wrap($field,$this->_input_wrap_class)); + } + + public function hidden($name, array $attributes = null) { + $value = isset($this->_values[$name]) ? $this->_values[$name] : null; + if (!$attributes) $attributes = array(); + if (!isset($attributes['class'])) $attributes['class'] = $this->_input_class; + return Form::hidden($this->_token, $name, $value, $attributes, $this->_fill); + } + + public function token($value, array $attributes = null) { + return Form::token($value, $attributes); + } + + public function file($label, $name, array $attributes = null, $multiple = false) { + if ($this->isErrorField($name)) { + if ($attributes === null) $attributes = array(); + if (!isset($attributes['class'])) + $attributes['class'] = ' '.$this->_field_error_class; + else + $attributes['class'] .= ' '.$this->_field_error_class; + } + $label = Form::label($label, $name, array('class'=>$this->_label_class)); + $field = Form::file($this->_token, $name, $attributes, $multiple); + if (isset($attributes['title'])) { + $field .= Helper::tag('p', $attributes['title'], array('class'=>$this->_help_class)); + } + return $this->wrap($label.$this->wrap($field,$this->_file_wrap_class)); + } + + public function fileButton($label, $name, array $attributes = null, $multiple = false, $text = null) { + $_name = Form::getFieldName($this->_token, $name); + if ($attributes === null) $attributes = array(); + $attributes['id'] = $_name; + if ($text==null) $text = Zira\Locale::t('Browse'); + $label = Form::label($label, $name, array('class'=>$this->_label_class)); + $field = Form::file($this->_token, $name, $attributes, $multiple); + $field = $this->wrap($text.$field,$this->_button_class.' form-file-button'); + $html = $this->wrap($text.$field,$this->_input_group_button_class); + $html .= Helper::tag_short('input', array('type'=>'text','class'=>$this->_input_class,'id'=>$_name.'-text','readonly'=>'readonly')); + $error_class = ''; + if ($this->isErrorField($name)) $error_class=' '.$this->_field_error_class; + $elems = $this->wrap($html,$this->_input_group_class.$error_class); + if (isset($attributes['title'])) { + $elems .= Helper::tag('p', $attributes['title'], array('class'=>$this->_help_class)); + } + return $this->wrap($label.$this->wrap($elems,$this->_file_wrap_class)); + } + + public function datepicker($label, $name, array $attributes = null) { + $value = isset($this->_values[$name]) ? $this->_values[$name] : null; + $id = $name.'-datepicker'; + if ($attributes === null) $attributes = array(); + if (!isset($attributes['class'])) $attributes['class'] = $this->_input_class; + $error_class = ''; + if ($this->isErrorField($name)) $error_class=' '.$this->_field_error_class; + $label = Form::label($label, $name, array('class'=>$this->_label_class)); + $html = Helper::tag_open('div', array('class'=>$this->_input_group_class.' '.$this->_date_wrap_class.$error_class,'id'=>$id)); + $html .= Form::input($this->_token, $name, $value, $attributes, $this->_fill); + $html .= Helper::tag_open('span', array('class'=>$this->_input_group_addon_class)); + $html .= Helper::tag('span', null, array('class'=>$this->_icon_time_class)); + $html .= Helper::tag_close('span'); + $html .= Helper::tag_close('div'); + if (isset($attributes['title'])) { + $html .= Helper::tag('p', $attributes['title'], array('class'=>$this->_help_class)); + } + return $this->wrap($label.$this->wrap($html,$this->_input_wrap_class)); + } + + /** + * @param $name + * @param string $viewMode - accepts 'decades','years','months','days' + * @param null $maxDate - format 'Y-m-d' + */ + public function initDatepicker($name, $viewMode = null, $maxDate = null) { + Zira\View::addDatepicker($viewMode, $maxDate); + $script = Helper::tag_open('script',array('type'=>'text/javascript')); + $script .= "jQuery(document).ready(function(){"; + $script .= "zira_datepicker(jQuery('#".$name."'))"; + $script .= "});"; + $script .= Helper::tag_close('script'); + Zira\View::addHTML($script, Zira\View::VAR_BODY_BOTTOM); + } + + public function parseDatepickerDate($value) { + $date = ''; + $format = Zira\Config::get('datepicker_date_format'); + if (preg_match_all('/(?:DD|MM|YYYY)/', $format, $m) && !empty($m[0])) { + $days = -1; $months = -1; $years = -1; + foreach($m[0] as $i=>$_m) { + if ($_m == 'DD') $days=$i; + if ($_m == 'MM') $months=$i; + if ($_m == 'YYYY') $years=$i; + } + if (preg_match_all('/[\d]+/', $value, $m1) && !empty($m1[0])) { + $day = ''; $month = ''; $year = ''; + foreach($m1[0] as $i=>$_m1) { + if ($i == $days) $day .= $_m1; + else if ($i == $months) $month .= $_m1; + else if ($i == $years) $year .= $_m1; + } + if (!empty($day) && !empty($month) && !empty($year)) { + $date=date('Y-m-d',mktime(0,0,0,intval($month),intval($day),intval($year))); + } + } + } + return $date; + } + + public function prepareDatepickerDate($value) { + if (empty($value)) return $value; + $time = strtotime($value); + $format = Zira\Config::get('datepicker_date_format'); + $format = str_replace('DD','%1$s',$format); + $format = str_replace('MM','%2$s',$format); + $format = str_replace('YYYY','%3$s',$format); + $day = date('d', $time); + $month = date('m', $time); + $year = date('Y', $time); + return sprintf($format,$day,$month,$year); + } + + public function checkbox($label, $name, array $attributes = null, $fill=true) { + $checked = !empty($this->_values[$name]); + if (!$attributes) $attributes = array(); + if ($checked) $attributes['checked'] = 'checked'; + + if ($this->_checkbox_inline_label) { + if (!isset($attributes['class'])) $attributes['class'] = $this->_input_class; + if (!isset($attributes['style'])) $attributes['style'] = 'width:auto;height:auto;outline:none'; + $field = Form::checkbox($this->_token, $name, null, $attributes, ($fill ? $this->_fill : false)); + $html = Helper::tag_open('label', array('for' => $name, 'class'=>$this->_label_class, 'style'=>'width:auto;padding-top:0px')); + $html .= $field . $label; + $html .= Helper::tag_close('label'); + $elems = $this->wrap($html,$this->_checkbox_wrap_class.' '.$this->_checkbox_inline_wrap_class); + return $this->wrap($this->wrap($elems,$this->_input_offset_wrap_class)); + } else { + $label = Form::label($label, $name, array('class'=>$this->_label_class)); + if (!isset($attributes['class'])) $attributes['class'] = $this->_input_class; + if (!isset($attributes['style'])) $attributes['style'] = 'width:auto;outline:none'; + $field = Form::checkbox($this->_token, $name, null, $attributes, ($fill ? $this->_fill : false)); + return $this->wrap($label.$this->wrap($field,$this->_input_wrap_class)); + } + } + + public function checkboxButton($label, $name, array $attributes = null, $fill=true) { + $checked = !empty($this->_values[$name]); + if (!$attributes) $attributes = array(); + if ($checked) $attributes['checked'] = 'checked'; + $field = Form::checkbox($this->_token, $name, null, $attributes, ($fill ? $this->_fill : false)); + $active = strpos($field,' checked="checked"') ? ' active' : ''; + $html = Helper::tag_open('div',array('class'=>$this->_button_group_class,'data-toggle'=>'buttons')); + $html .= Helper::tag_open('label',array('class'=>$this->_button_class.$active)); + $html .= $field.$label; + $html .= Helper::tag_close('label'); + $html .= Helper::tag_close('div'); + return $this->wrap($this->wrap($html,$this->_input_offset_wrap_class)); + } + + public function radio($label, $name, array $value_titles, array $attributes = null, $fill=true) { + $checked = isset($this->_values[$name]) ? $this->_values[$name] : null; + if (!$attributes) $attributes = array(); + $elems = ''; + foreach ($value_titles as $value=>$title) { + $_attributes = array(); + if ($checked!==null && $checked==$value) { + $_attributes['checked'] = 'checked'; + } + $field = Form::radio($this->_token, $name, $value, array_merge($attributes,$_attributes), ($fill ? $this->_fill : false)); + $html = Helper::tag_open('label'); + $html .= $field.$title; + $html .= Helper::tag_close('label'); + $elems .= $this->wrap($html,$this->_radio_wrap_class); + } + $label = Form::label($label, null, array('class'=>$this->_label_class)); + return $this->wrap($label.$this->wrap($elems,$this->_input_wrap_class)); + } + + public function radioButton($label, $name, array $value_titles, array $attributes = null, $fill=true) { + $checked = isset($this->_values[$name]) ? $this->_values[$name] : null; + if (!$attributes) $attributes = array(); + $elems = Helper::tag_open('div',array('class'=>$this->_button_group_class,'data-toggle'=>'buttons')); + foreach ($value_titles as $value=>$title) { + $_attributes = array(); + if ($checked!==null && $checked==$value) { + $_attributes['checked'] = 'checked'; + } + $field = Form::radio($this->_token, $name, $value, array_merge($attributes,$_attributes), ($fill ? $this->_fill : false)); + $active = strpos($field,' checked="checked"') ? ' active' : ''; + + $html = Helper::tag_open('label',array('class'=>$this->_button_class.$active)); + $html .= $field.$title; + $html .= Helper::tag_close('label'); + $elems .= $html; + } + $elems .= Helper::tag_close('div'); + $label = Form::label($label, null, array('class'=>$this->_label_class)); + return $this->wrap($label.$this->wrap($elems,$this->_input_wrap_class)); + } + + public function textarea($label, $name, array $attributes = null) { + $value = isset($this->_values[$name]) ? $this->_values[$name] : null; + if (!$attributes) $attributes = array(); + if (!isset($attributes['class'])) $attributes['class'] = $this->_input_class; + if ($this->isErrorField($name)) $attributes['class'] .= ' '.$this->_field_error_class; + $label = Form::label($label, $name, array('class'=>$this->_label_class)); + $field = Form::textarea($this->_token, $name, $value, $attributes, $this->_fill); + if (isset($attributes['title'])) { + $field .= Helper::tag('p', $attributes['title'], array('class'=>$this->_help_class)); + } + return $this->wrap($label.$this->wrap($field,$this->_input_wrap_class)); + } + + public function select($label, $name, array $options=null, array $attributes = null) { + $selected = isset($this->_values[$name]) ? $this->_values[$name] : null; + if (!$attributes) $attributes = array(); + if (!isset($attributes['class'])) $attributes['class'] = $this->_input_class; + $label = Form::label($label, $name, array('class'=>$this->_label_class)); + $field = Form::select($this->_token, $name, $options, $selected, $attributes, $this->_fill); + if (isset($attributes['title'])) { + $field .= Helper::tag('p', $attributes['title'], array('class'=>$this->_help_class)); + } + return $this->wrap($label.$this->wrap($field,$this->_select_wrapper_class)); + } + + public function selectDropdown($label, $name, array $options=null, array $attributes = null) { + $_name = Form::getFieldName($this->_token, $name); + $selected = isset($this->_values[$name]) ? $this->_values[$name] : null; + $label = Form::label($label, $name, array('class'=>$this->_label_class)); + + if ($this->_fill) { + if ($this->_fill == Request::POST && Request::isPost()) $_value = Request::post($_name); + else if ($this->_fill == Request::GET) $_value = Request::get($_name); + } + + if (isset($_value)) $selected = $_value; + if ($selected===null && $options!==null && count($options)>0) { + $selected = array_keys($options)[0]; + } + + $field = Form::hidden($this->_token, $name, $selected, $attributes, $this->_fill); + + $button_id = $_name.'-dropdown-label'; + if (!empty($options)) { + $button_label = $selected!==null && isset($options[$selected]) ? $options[$selected] : reset($options); + } else { + $button_label = ''; + } + $dropdown = Helper::tag_open('div',array('class'=>$this->_dropdown_class)); + $dropdown .= Helper::tag_open('button',array('class'=>$this->_button_class,'id'=>$button_id,'type'=>'button','data-toggle'=>'dropdown','aria-haspopup'=>'true','aria-expanded'=>'false')); + $dropdown .= Helper::html($button_label.' '); + $dropdown .= Helper::tag('span','',array('class'=>'caret')); + $dropdown .= Helper::tag_close('button'); + $dropdown .= Helper::tag_open('ul',array('class'=>$this->_dropdown_menu_class,'aria-labelledby'=>$button_id,'rel'=>$_name)); + foreach ($options as $option_value=>$option_name) { + $dropdown .= Helper::tag_open('li'); + $dropdown .= Helper::tag('a',$option_name,array('href'=>'javascript:void(0)','rel'=>$option_value)); + $dropdown .= Helper::tag_close('li'); + } + $dropdown .= Helper::tag_close('ul'); + $dropdown .= Helper::tag_close('div'); + if (isset($attributes['title'])) { + $dropdown .= Helper::tag('p', $attributes['title'], array('class'=>$this->_help_class)); + } + + return $this->wrap($label.$this->wrap($field.$dropdown,$this->_input_wrap_class)); + } + + public function button($label, array $attributes = null) { + if (!$attributes) $attributes = array(); + if (!isset($attributes['class'])) $attributes['class'] = $this->_button_class; + $field = Form::button($label,$attributes); + return $this->wrap($this->wrap($field,$this->_input_offset_wrap_class)); + } + + public function submit($label, array $attributes = null) { + if (!$attributes) $attributes = array(); + if (!isset($attributes['class'])) $attributes['class'] = $this->_submit_class; + $field = Form::submit($label,$attributes); + return $this->wrap($this->wrap($field,$this->_input_offset_wrap_class)); + } + + public function captcha($label) { + $error_class = ''; + if ($this->isErrorField(CAPTCHA_NAME)) $error_class=' '.$this->_field_error_class; + $label = Form::label($label, null, array('class'=>$this->_label_class)); + $captcha = Form::captcha( + $this->_token, + $this->_captcha_image_wrapper_class, + $this->_captcha_input_wrapper_class.$error_class, + $this->_input_class, + $this->_captcha_refresh_wrapper_class, + Helper::tag('span',null,array('class'=>$this->_captcha_refresh_ico_class)) + ); + return $this->wrap($label.$this->wrap($captcha,$this->_captcha_wrapper_class)); + } + + public function captchaLazy($label) { + if (!Zira\Models\Captcha::isActive($this->_id)) return ''; + return $this->captcha($label); + } + + public function validate() { + if (!$this->getValidator()->validate()) { + $this->setError($this->getValidator()->getMessage()); + return false; + } + return true; + } +} \ No newline at end of file diff --git a/zira/form/form.php b/zira/form/form.php new file mode 100644 index 0000000..3f7dab4 --- /dev/null +++ b/zira/form/form.php @@ -0,0 +1,310 @@ +*
    ',Helper::html($text)); + $html = Helper::tag_open('label',$attributes); + $html .= $text; + $html .= Helper::tag_close('label'); + return $html; + } + } + + public static function input($token, $name, $value=null, array $attributes = null, $fill=Request::POST) { + $_name = self::getFieldName($token, $name); + if (!$attributes) $attributes = array(); + if (!isset($attributes['type'])) $attributes['type'] = 'text'; + if (!isset($attributes['id'])) $attributes['id'] = $name; + $attributes['name'] = $_name; + + if ($fill) { + if ($fill == Request::POST && Request::isPost()) $_value = Request::post($_name); + else if($fill == Request::GET) $_value = Request::get($_name); + } + + if (isset($_value)) $attributes['value'] = $_value; + else if ($value!==null) $attributes['value'] = $value; + else if (!isset($attributes['value'])) $attributes['value'] = ''; + return Helper::tag_short('input',$attributes); + } + + public static function password($token, $name, $value=null, array $attributes = null) { + if (!$attributes) $attributes = array(); + $attributes['type'] = 'password'; + return self::input($token,$name,$value,$attributes,false); + } + + public static function hidden($token, $name, $value=null, array $attributes = null, $fill=Request::POST) { + if (!$attributes) $attributes = array(); + $attributes['type'] = 'hidden'; + return self::input($token,$name,$value,$attributes,$fill); + } + + public static function token($value, array $attributes = null) { + if (!$attributes) $attributes = array(); + $attributes['name'] = 'token'; + $attributes['type'] = 'hidden'; + $attributes['value'] = $value; + return Helper::tag_short('input',$attributes); + } + + public static function file($token, $name, array $attributes = null, $multiple = false) { + if (!$attributes) $attributes = array(); + $attributes['type'] = 'file'; + if ($multiple) { + $attributes['multiple'] = 'multiple'; + if (!isset($attributes['id'])) $attributes['id'] = $name; + $name .= '[]'; + } + + return self::input($token,$name,null,$attributes,false); + } + + public static function checkbox($token, $name, $value=null, array $attributes = null, $fill=Request::POST) { + if (!$attributes) $attributes = array(); + $attributes['type'] = 'checkbox'; + if ($value===null && !isset($attributes['value'])) $attributes['value'] = 1; + + if ($fill) { + $_name = $token . '-' . $name; + if ($fill == Request::POST && Request::isPost()) $_value = Request::post($_name, 0); + else if ($fill == Request::GET) $_value = Request::get($_name, 0); + + if (isset($_value) && !empty($_value)) { + $attributes['checked'] = 'checked'; + } else if (isset($_value) && empty($_value) && isset($attributes['checked'])) { + unset($attributes['checked']); + } + $fill = false; + } + + return self::input($token,$name,$value,$attributes,$fill); + } + + public static function radio($token, $name, $value=null, array $attributes = null, $fill=Request::POST) { + if (!$attributes) $attributes = array(); + $attributes['type'] = 'radio'; + if ($value===null && isset($attributes['value'])) $value = $attributes['value']; + + if ($fill) { + $_name = $token . '-' . $name; + if ($fill == Request::POST && Request::isPost()) $_value = Request::post($_name); + else if ($fill == Request::GET) $_value = Request::get($_name); + + if (isset($_value) && $_value == $value) { + $attributes['checked'] = 'checked'; + } else if (isset($_value) && $_value != $value && isset($attributes['checked'])) { + unset($attributes['checked']); + } + $fill = false; + } + + return self::input($token,$name,$value,$attributes,$fill); + } + + public static function textarea($token, $name, $value=null, array $attributes = null, $fill=Request::POST) { + $_name = self::getFieldName($token, $name); + if (!$attributes) $attributes = array(); + if (!isset($attributes['id'])) $attributes['id'] = $name; + $attributes['name'] = $_name; + + if ($fill) { + if ($fill == Request::POST && Request::isPost()) $_value = Request::post($_name); + else if($fill == Request::GET) $_value = Request::get($_name); + } + + if (isset($_value)) $value = $_value; + + return Helper::tag('textarea',$value,$attributes); + } + + public static function select($token, $name, array $options=null, $selected = null, array $attributes = null, $fill=Request::POST) { + $_name = self::getFieldName($token, $name); + if (!$options) $options = array(); + if (!$attributes) $attributes = array(); + if (!isset($attributes['id'])) $attributes['id'] = $name; + $attributes['name'] = $_name; + + if ($fill) { + if ($fill == Request::POST && Request::isPost()) $_value = Request::post($_name); + else if ($fill == Request::GET) $_value = Request::get($_name); + } + + if (isset($_value)) $selected = $_value; + + $html = Helper::tag_open('select',$attributes); + foreach($options as $k=>$v) { + $_attributes = array(); + $_attributes['value'] = $k; + if ($k == $selected) $_attributes['selected'] = 'selected'; + $html .= Helper::tag('option',$v,$_attributes); + } + $html .= Helper::tag_close('select'); + return $html; + } + + public static function button($label, array $attributes = null) { + return Helper::tag('button',$label,$attributes); + } + + public static function submit($label, array $attributes = null) { + if (!$attributes) $attributes = array(); + $attributes['type'] = 'submit'; + $attributes['value'] = $label; + + return Helper::tag_short('input',$attributes); + } + + public static function captcha($token,$image_wrapper_class='captcha_image',$input_wrapper_class='captcha_input',$input_class='captcha',$refresh_wrapper_class='captcha_refresh',$refresh_value = 'Reload') { + $html = Helper::tag_open('div',array('class'=>$image_wrapper_class)); + $html .= Helper::tag_short('img',array('src'=>Helper::url('captcha').'?token='.$token.'&t='.time(),'width'=>CAPTCHA_WIDTH,'height'=>CAPTCHA_HEIGHT,'id'=>$token.'-'.CAPTCHA_NAME.'-image')); + $html .= Helper::tag_close('div'); + + $html .= Helper::tag_open('div',array('class'=>$input_wrapper_class)); + $html .= self::input($token,CAPTCHA_NAME, null, array('class'=>$input_class,'autocomplete'=>'off'), false); + + $html .= Helper::tag_open('div',array('class'=>$refresh_wrapper_class)); + $html .= Helper::tag_open('a',array('href'=>'javascript:void(0)','onclick'=>'document.getElementById(\''.$token.'-'.CAPTCHA_NAME.'-image'.'\').src+=Math.floor(Math.random()*10);')); + $html .= $refresh_value; + $html .= Helper::tag_close('a'); + $html .= Helper::tag_close('div'); + + $html .= Helper::tag_close('div'); + + return $html; + } + + public static function generateCaptcha() { + $token = Request::get('token'); + if (!$token) return; + + $digit1 = rand(1,9); + $digit2 = rand(1,9); + + $result = $digit1 + $digit2; + Session::set(self::getFieldName($token, CAPTCHA_NAME),$result); + + $image = imagecreatetruecolor(CAPTCHA_WIDTH,CAPTCHA_HEIGHT); + + $size = CAPTCHA_HEIGHT*.8; + putenv('GDFONTPATH=' . realpath(ROOT_DIR . DIRECTORY_SEPARATOR . ASSETS_DIR . DIRECTORY_SEPARATOR . FONTS_DIR)); + + $bg = imagecolorallocate($image, rand(160,255), rand(160,255), rand(160,255)); + imagefill($image,0,0,$bg); + + for ($i=0;$i<30;$i++) { + $color= imagecolorallocate($image, rand(160,255), rand(160,255), rand(160,255)); + imagefilledellipse($image,rand(0,CAPTCHA_WIDTH),rand(0,CAPTCHA_HEIGHT),CAPTCHA_HEIGHT/3,CAPTCHA_HEIGHT/3,$color); + } + + $captcha_font = CAPTCHA_FONT; + + $color= imagecolorallocate($image, rand(0,155), rand(0,155), rand(0,155)); + try { + imagettftext($image,$size,rand(-15,15),CAPTCHA_WIDTH/5+(CAPTCHA_WIDTH/5-$size)/2,CAPTCHA_HEIGHT-(CAPTCHA_HEIGHT-$size)/2,$color,$captcha_font,$digit1); + } catch(\Exception $e) { + imagestring($image,$size,CAPTCHA_WIDTH/5+(CAPTCHA_WIDTH/5-$size)/2,(CAPTCHA_HEIGHT-$size)/2+$size/4,$digit1,$color); + } + + $sign = '+'; + $color= imagecolorallocate($image, rand(0,155), rand(0,155), rand(0,155)); + try { + imagettftext($image,$size,rand(-5,5),CAPTCHA_WIDTH*2/5+(CAPTCHA_WIDTH/5-$size)/2,CAPTCHA_HEIGHT-(CAPTCHA_HEIGHT-$size)/2,$color,$captcha_font,$sign); + } catch(\Exception $e) { + imagestring($image,$size,CAPTCHA_WIDTH*2/5+(CAPTCHA_WIDTH/5-$size)/2,(CAPTCHA_HEIGHT-$size)/2+$size/4,$sign,$color); + } + + $color= imagecolorallocate($image, rand(0,155), rand(0,155), rand(0,155)); + try { + imagettftext($image,$size,rand(-15,15),CAPTCHA_WIDTH*3/5+(CAPTCHA_WIDTH/5-$size)/2,CAPTCHA_HEIGHT-(CAPTCHA_HEIGHT-$size)/2,$color,$captcha_font,$digit2); + } catch(\Exception $e) { + imagestring($image,$size,CAPTCHA_WIDTH*3/5+(CAPTCHA_WIDTH/5-$size)/2,(CAPTCHA_HEIGHT-$size)/2+$size/4,$digit2,$color); + } + + $sign = '='; + $color= imagecolorallocate($image, rand(0,155), rand(0,155), rand(0,155)); + try { + imagettftext($image,$size,rand(-5,5),CAPTCHA_WIDTH*4/5+(CAPTCHA_WIDTH/5-$size)/2,CAPTCHA_HEIGHT-(CAPTCHA_HEIGHT-$size)/2,$color,$captcha_font,$sign); + } catch(\Exception $e) { + imagestring($image,$size,CAPTCHA_WIDTH*4/5+(CAPTCHA_WIDTH/5-$size)/2,(CAPTCHA_HEIGHT-$size)/2+$size/4,$sign,$color); + } + + imagejpeg($image,null,90); + } + + public static function isCaptchaValid($token,$method=Request::POST) { + $value = self::getValue($token,CAPTCHA_NAME,$method); + if (!$value) return false; + $captcha = Session::get(self::getFieldName($token, CAPTCHA_NAME)); + if (!$captcha) return false; + return $value == $captcha; + } + + public static function getValue($token,$name,$method=Request::POST) { + $_name = self::getFieldName($token, $name); + if ($method == Request::POST) { + return Request::post($_name); + } else if ($method == Request::FILES) { + return Request::file($_name); + } else if ($method == Request::GET) { + return Request::get($_name); + } else { + return null; + } + } +} \ No newline at end of file diff --git a/zira/form/validator.php b/zira/form/validator.php new file mode 100644 index 0000000..f9cb853 --- /dev/null +++ b/zira/form/validator.php @@ -0,0 +1,454 @@ +_token = $token; + } + + public function getToken() { + return $this->_token; + } + + public function setMethod($method) { + $this->_method = $method; + } + + public function setMultipart($multipart) { + $this->_multipart = (bool)$multipart; + } + + public function getMessage() { + return $this->_message; + } + + public function getErrorField() { + return $this->_error_field; + } + + protected function getValue(array $field, $method = null) { + if (!$method) $method = $this->_method; + $value = Form::getValue($field['token'],$field['name'],$method); + if ($value===null && $method == Request::POST && $this->_multipart) { + $value = Form::getValue($field['token'],$field['name'],Request::FILES); + } + return $value; + } + + public function registerString($field,$min_length,$max_length,$required,$message) { + $this->_fields []= array( + 'type' => self::TYPE_STRING, + 'token' => $this->_token, + 'name' => $field, + 'min' => $min_length, + 'max' => $max_length, + 'required' => $required, + 'message' => $message + ); + } + + protected function validateString(array $field) { + $value = $this->getValue($field); + $value = trim($value); + if ($field['required'] && empty($value)) return false; + if (!empty($value) && !is_string($value)) return false; + if (!empty($value) && $field['min']>0 && mb_strlen($value,CHARSET)<$field['min']) return false; + if (!empty($value) && $field['max']>0 && mb_strlen($value,CHARSET)>$field['max']) return false; + return true; + } + + public function registerNoTags($field,$message) { + $this->_fields []= array( + 'type' => self::TYPE_NO_TAGS, + 'token' => $this->_token, + 'name' => $field, + 'message' => $message + ); + } + + protected function validateNoTags(array $field) { + $value = $this->getValue($field); + if (empty($value)) return true; + if (strpos($value, '<')!==false || strpos($value, '>')!==false) return false; + return true; + } + + public function registerNumber($field,$min_value,$max_value,$required,$message) { + $this->_fields []= array( + 'type' => self::TYPE_NUMBER, + 'token' => $this->_token, + 'name' => $field, + 'min' => $min_value, + 'max' => $max_value, + 'required' => $required, + 'message' => $message + ); + } + + protected function validateNumber(array $field) { + $value = $this->getValue($field); + if ($field['required'] && $value===null) return false; + if ($value!==null && !is_numeric($value)) return false; + if ($value!==null && $field['min']!==null && $value<$field['min']) return false; + if ($value!==null && $field['max']!==null && $value>$field['max']) return false; + return true; + } + + public function registerEmail($field,$required,$message) { + $this->_fields []= array( + 'type' => self::TYPE_EMAIL, + 'token' => $this->_token, + 'name' => $field, + 'required' => $required, + 'message' => $message + ); + } + + protected function validateEmail(array $field) { + $value = $this->getValue($field); + if ($field['required'] && empty($value)) return false; + if (!empty($value)) { + return (boolean)preg_match( + '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' . + '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD', + $value + ); + } else { + return true; + } + } + + public function registerDate($field,$required,$message) { + $this->_fields []= array( + 'type' => self::TYPE_DATE, + 'token' => $this->_token, + 'name' => $field, + 'required' => $required, + 'message' => $message + ); + } + + protected function validateDate(array $field) { + $value = $this->getValue($field); + if ($field['required'] && empty($value)) return false; + if (!empty($value)) { + $format = Zira\Config::get('datepicker_date_format'); + $format = preg_quote($format); + $format = str_replace('M','[\d]', $format); + $format = str_replace('D','[\d]', $format); + $format = str_replace('Y','[\d]', $format); + return (boolean)preg_match( + '/^'.$format.'$/', + $value + ); + } else { + return true; + } + } + + public function registerPhone($field,$required,$message) { + $this->_fields []= array( + 'type' => self::TYPE_PHONE, + 'token' => $this->_token, + 'name' => $field, + 'required' => $required, + 'message' => $message + ); + } + + protected function validatePhone(array $field) { + $value = $this->getValue($field); + $value = str_replace(' ','',$value); + $value = str_replace('-','',$value); + if ($field['required'] && empty($value)) return false; + if (!empty($value)) { + return (boolean)preg_match( + '/^[+][\d]+$/', + $value + ); + } else { + return true; + } + } + + public function registerMatch($field1,$field2,$message) { + $this->_fields []= array( + 'type' => self::TYPE_MATCH, + 'name' => $field2, + 'fields' => array( + array( + 'token' => $this->_token, + 'name' => $field1 + ), + array( + 'token' => $this->_token, + 'name' => $field2 + ) + ), + 'message' => $message + ); + } + + protected function validateMatch(array $field) { + $value1 = $this->getValue($field['fields'][0]); + $value2 = $this->getValue($field['fields'][1]); + return $value1 == $value2; + } + + public function registerRegexp($field,$regexp,$message) { + $this->_fields []= array( + 'type' => self::TYPE_REGEXP, + 'token' => $this->_token, + 'name' => $field, + 'regexp' => $regexp, + 'message' => $message + ); + } + + protected function validateRegexp(array $field) { + $value = $this->getValue($field); + return (boolean)preg_match( + $field['regexp'], + $value + ); + } + + public function registerText($field,$min_length,$required,$message) { + $this->_fields []= array( + 'type' => self::TYPE_TEXT, + 'token' => $this->_token, + 'name' => $field, + 'min' => $min_length, + 'required' => $required, + 'message' => $message + ); + } + + protected function validateText(array $field) { + $value = $this->getValue($field); + $value = trim($value); + if ($field['required'] && empty($value)) return false; + if (!empty($value) && !is_string($value)) return false; + if (!empty($value) && $field['min']>0 && mb_strlen($value,CHARSET)<$field['min']) return false; + return true; + } + + public function registerFile($field,$max_size,array $extensions,$required,$message) { + $this->_fields []= array( + 'type' => self::TYPE_FILE, + 'token' => $this->_token, + 'name' => $field, + 'max' => $max_size, + 'extensions' => $extensions, + 'required' => $required, + 'message' => $message + ); + } + + protected function validateFile(array $field) { + $value = $this->getValue($field,Request::FILES); + $files = array(); + if (!empty($value) && !empty($value['name']) && !empty($value['tmp_name'])) { + if (is_array($value['tmp_name'])) { + foreach($value['tmp_name'] as $i=>$tmp_name) { + if (empty($tmp_name)) continue; + if (!isset($value['name'][$i])) return false; + if (empty($value['name'][$i])) continue; + $files[$tmp_name] = $value['name'][$i]; + } + } else { + $files[$value['tmp_name']] = $value['name']; + } + } + + if (!$field['required'] && empty($files)) return true; + if ($field['required'] && empty($files)) return false; + + foreach($files as $tmp_name=>$name) { + if (!file_exists($tmp_name)) return false; + if ($field['max']>0 && filesize($tmp_name)>$field['max']) return false; + + if (!empty($field['extensions'])) { + $ext = preg_replace('/^.+\.(.+?)$/iu','$1',$name); + if (!in_array($ext,$field['extensions'])) return false; + } + } + + return true; + } + + public function registerImage($field,$max_size,$required,$message) { + $this->_fields []= array( + 'type' => self::TYPE_IMAGE, + 'token' => $this->_token, + 'name' => $field, + 'max' => $max_size, + 'extensions' => array('jpg','jpeg','png','gif','JPG','JPEG','PNG','GIF'), + 'required' => $required, + 'message' => $message + ); + } + + protected function validateImage(array $field) { + if (!$this->validateFile($field)) return false; + + $value = $this->getValue($field,Request::FILES); + if (!empty($value) && !empty($value['name']) && !empty($value['tmp_name'])) { + if (is_array($value['tmp_name'])) { + foreach($value['tmp_name'] as $tmp_name) { + if (empty($tmp_name)) continue; + if (!@getimagesize($tmp_name)) return false; + } + } else if (!@getimagesize($value['tmp_name'])) return false; + } + return true; + } + + public function registerCaptcha($message) { + $this->_fields []= array( + 'type' => self::TYPE_CAPTCHA, + 'name' => CAPTCHA_NAME, + 'token' => $this->_token, + 'message' => $message + ); + } + + protected function validateCaptcha(array $field) { + return Form::isCaptchaValid($field['token'], $this->_method); + } + + public function registerCaptchaLazy($form_id, $message) { + $this->_fields []= array( + 'type' => self::TYPE_CAPTCHA_LAZY, + 'name' => CAPTCHA_NAME, + 'token' => $this->_token, + 'form_id' => $form_id, + 'message' => $message + ); + } + + protected function validateCaptchaLazy(array $field) { + if ($this->getValue($field)===null && !Zira\Models\Captcha::isActive($field['form_id'])) { + Zira\Models\Captcha::register($field['form_id']); + return true; + } else { + Zira\Models\Captcha::register($field['form_id']); + return Form::isCaptchaValid($field['token'], $this->_method); + } + } + + public function registerExists($field,$class,$property,$message) { + $this->_fields []= array( + 'type' => self::TYPE_EXISTS, + 'token' => $this->_token, + 'name' => $field, + 'class' => $class, + 'property' => $property, + 'message' => $message + ); + } + + protected function validateExists(array $field) { + $value = $this->getValue($field); + try { + $collection = new Zira\Db\Collection($field['class']); + $co = $collection->count() + ->where($field['property'],'=',$value) + ->get('co'); + return $co==0; + } catch (\Exception $e) { + Zira::getInstance()->exception($e); + return false; + } + } + + public function registerCustom(array $class_method,$fields,$message) { + if (is_array($fields)) $name = reset($fields); + else $name = (string)$fields; + $this->_fields []= array( + 'type' => self::TYPE_CUSTOM, + 'class_method' => $class_method, + 'token' => $this->_token, + 'name' => $name, + 'fields' => $fields, + 'message' => $message + ); + } + + protected function validateCustom($field) { + $fields = $field['fields']; + if (!is_array($fields)) { + $value = $this->getValue($field); + return call_user_func($field['class_method'],$value); + } else { + $args = array(); + foreach($fields as $name) { + $field['name'] = $name; + $args[]=$this->getValue($field); + } + return call_user_func_array($field['class_method'],$args); + } + } + + public function validate() { + foreach($this->_fields as $field) { + if (!$this->validateField($field)) { + $this->_message = $field['message']; + $this->_error_field = $field['name']; + return false; + } + } + return true; + } + + protected function validateField(array $field) { + if ($field['type']==self::TYPE_STRING && !$this->validateString($field)) return false; + if ($field['type']==self::TYPE_NO_TAGS && !$this->validateNoTags($field)) return false; + if ($field['type']==self::TYPE_NUMBER && !$this->validateNumber($field)) return false; + if ($field['type']==self::TYPE_EMAIL && !$this->validateEmail($field)) return false; + if ($field['type']==self::TYPE_DATE && !$this->validateDate($field)) return false; + if ($field['type']==self::TYPE_MATCH && !$this->validateMatch($field)) return false; + if ($field['type']==self::TYPE_PHONE && !$this->validatePhone($field)) return false; + if ($field['type']==self::TYPE_REGEXP && !$this->validateRegexp($field)) return false; + if ($field['type']==self::TYPE_TEXT && !$this->validateText($field)) return false; + if ($field['type']==self::TYPE_FILE && !$this->validateFile($field)) return false; + if ($field['type']==self::TYPE_IMAGE && !$this->validateImage($field)) return false; + if ($field['type']==self::TYPE_EXISTS && !$this->validateExists($field)) return false; + if ($field['type']==self::TYPE_CAPTCHA && !$this->validateCaptcha($field)) return false; + if ($field['type']==self::TYPE_CAPTCHA_LAZY && !$this->validateCaptchaLazy($field)) return false; + if ($field['type']==self::TYPE_CUSTOM && !$this->validateCustom($field)) return false; + return true; + } +} \ No newline at end of file diff --git a/zira/forms/comment.php b/zira/forms/comment.php new file mode 100644 index 0000000..1be5cbd --- /dev/null +++ b/zira/forms/comment.php @@ -0,0 +1,84 @@ +_id); + } + + protected function _init() { + $this->setAjax(true); + $this->setUrl('comment'); + $this->setTitle(Locale::t('Leave a comment')); + $this->setDescription(Locale::t('Message should contain at least %s characters', Config::get('comment_min_chars', 10))); + $script = Helper::tag_open('script', array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){ jQuery(\'#'.$this->getId().'\').bind(\'xhr-submit-success\', function(){ zira_reset_comments_form(true); }); });'; + $script .= Helper::tag_close('script'); + View::addHTML($script, View::VAR_BODY_BOTTOM); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->hidden('record_id'); + $html .= $this->hidden('parent_id'); + $html .= Helper::tag('div',null,array('class'=>'form-group comment-reply-preview')); + if(!User::isAuthorized()) { + $html .= $this->input(Locale::t('Name'), 'sender_name'); + } else { + $html .= $this->hidden('sender_name'); + } + + $extra_items = \Zira\Hook::run(\Zira\Page::USER_TEXTAREA_HOOK); + if (!empty($extra_items)) { + $html .= Helper::tag_open('div',array('class'=>'user-text-form-extra-items')); + foreach($extra_items as $item) { + $html .= Helper::tag_open('div',array('class'=>'user-text-form-extra-item')); + $html .= $item; + $html .= Helper::tag_close('div'); + } + $html .= Helper::tag_close('div'); + } + + $html .= $this->textarea(Locale::t('Message').'*','comment'); + if (Config::get('comments_captcha',true)) { + $html .= $this->captcha(Locale::t('Enter result').'*'); + } else { + $html .= $this->captchaLazy(Locale::t('Enter result') . '*'); + } + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + if (Config::get('comments_captcha',true)) { + $validator->registerCaptcha(Locale::t('Wrong CAPTCHA result')); + } else { + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + } + $validator->registerNumber('record_id', null, null, true, Locale::t('An error occurred')); + $validator->registerString('sender_name', 2, 255, false, Locale::t('Invalid name')); + $validator->registerNoTags('sender_name', Locale::t('Invalid name')); + $validator->registerText('comment', Config::get('comment_min_chars', 10), true, Locale::t('Message should contain at least %s characters', Config::get('comment_min_chars', 10))); + $validator->registerString('comment', null, self::MAX_CHARS, true, Locale::t('Sorry, your comment is too big')); + $validator->registerNoTags('comment', Locale::t('Message contains bad character')); + } +} \ No newline at end of file diff --git a/zira/forms/contact.php b/zira/forms/contact.php new file mode 100644 index 0000000..9451f28 --- /dev/null +++ b/zira/forms/contact.php @@ -0,0 +1,57 @@ +_id); + } + + protected function _init() { + $this->setUrl('contact'); + $this->setTitle(Locale::t('Send message')); + if (!User::isAuthorized()) { + $this->setDescription(Locale::t('Please specify your name and Email address')); + } else { + $this->setDescription(Locale::t('Message should contain at least %s characters', self::MIN_CHARS)); + } + } + + protected function _render() { + $html = $this->open(); + if (!User::isAuthorized()) { + $html .= $this->input(Locale::t('Name'), 'name'); + $html .= $this->input(Locale::t('Email'), 'email'); + } + $html .= $this->textarea(Locale::t('Message').'*','message'); + $html .= $this->captcha(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptcha(Locale::t('Wrong CAPTCHA result')); + $validator->registerString('name', 2, 255, false, Locale::t('Invalid name')); + $validator->registerNoTags('name', Locale::t('Invalid name')); + $validator->registerEmail('email', false, Locale::t('Invalid email')); + $validator->registerText('message', self::MIN_CHARS, true, Locale::t('Message should contain at least %s characters', self::MIN_CHARS)); + $validator->registerString('message', null, self::MAX_CHARS, true, Locale::t('Sorry, your message is too big')); + $validator->registerNoTags('message', Locale::t('Message contains bad character')); + } +} \ No newline at end of file diff --git a/zira/forms/search.php b/zira/forms/search.php new file mode 100644 index 0000000..0a77588 --- /dev/null +++ b/zira/forms/search.php @@ -0,0 +1,134 @@ +_is_token_unique = true; + parent::__construct($this->_id); + } + + public function setExtended($extended) { + $this->_extended = $extended; + } + + protected function _init() { + $this->setUrl('search'); + $this->setMethod(Request::GET); + $this->setRenderPanel(false); + if (!$this->_extended) { + $script = Helper::tag_open('script', array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){ zira_init_search(jQuery(\'#'.$this->getId().'\')); });'; + $script .= Helper::tag_close('script'); + View::addHTML($script, View::VAR_BODY_BOTTOM); + } + } + + public function getValue($name, $default = NULL) { + return Request::get($name, $default); + } + + public function setValue($name, $value) { + Request::setGet($name, $value); + } + + public function input($label, $name, array $attributes = NULL) { + if (!$attributes) $attributes = array(); + $attributes['type'] = 'text'; + $attributes['id'] = $name; + $attributes['name'] = $name; + + $_value = trim($this->getValue($name)); + + if (isset($_value)) $attributes['value'] = $_value; + else if (!isset($attributes['value'])) $attributes['value'] = ''; + + return Helper::tag_short('input',$attributes); + } + + protected function _render() { + if (!$this->_extended) { + return $this->_renderSimple(); + } else { + return $this->_renderExtended(); + } + } + + protected function _renderSimple() { + $html = $this->open(array('class'=>'search-simple-form navbar-form navbar-right','role'=>'search')); + $html .= Helper::tag_open('div',array('class'=>'form-group input-group')); + $html .= $this->input(null,'text', array('class'=>$this->_input_class, 'placeholder'=>Locale::t('Search'),'autocomplete'=>'off')); + $html .= Helper::tag_open('span',array('class'=>'input-group-btn')); + $html .= Helper::tag_open('button',array('type'=>'submit','class'=>'btn btn-default')); + $html .= Helper::tag('span', null, array('class'=>'glyphicon glyphicon-search')); + $html .= Helper::tag_close('button'); + $html .= Helper::tag_close('span'); + $html .= Helper::tag_close('div'); + $html .= $this->close(); + return $html; + } + + protected function _renderExtended() { + $html = $this->open(array('class'=>'search-extended-form','role'=>'search')); + $html .= Helper::tag_open('div',array('class'=>'form-group input-group')); + $html .= Helper::tag_open('span',array('class'=>'input-group-addon')); + $html .= Helper::tag('span', null, array('class'=>'glyphicon glyphicon-search')); + $html .= Helper::tag_close('span'); + $html .= $this->input(null,'text', array('class'=>$this->_input_class)); + $html .= Helper::tag_open('span',array('class'=>'input-group-btn')); + $html .= Helper::tag_open('button',array('type'=>'submit','class'=>'btn btn-default')); + $html .= Locale::t('Search'); + $html .= Helper::tag_close('button'); + $html .= Helper::tag_close('span'); + $html .= Helper::tag_close('div'); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->setMethod(Request::GET); + $validator->registerCustom(array(get_class(), 'validateString'), 'text', Locale::t('Invalid search text')); + $validator->registerCustom(array(get_class(), 'validateNoTags'), 'text', Locale::t('Search text contains bad character')); + } + + public static function validateString($ignore) { + return self::_validateString('text', \Zira\Models\Search::MIN_CHARS, 255, false); + } + + public static function _validateString($name, $min, $max, $required) { + $value = Request::get($name); + $value = trim($value); + if ($required && empty($value)) return false; + if (!empty($value) && !is_string($value)) return false; + if (!empty($value) && $min>0 && mb_strlen($value,CHARSET)<$min) return false; + if (!empty($value) && $max>0 && mb_strlen($value,CHARSET)>$max) return false; + return true; + } + + public static function validateNoTags($ignore) { + return self::_validateNoTags('text'); + } + + public static function _validateNoTags($name) { + $value = Request::get($name); + if (empty($value)) return true; + if (strpos($value, '<')!==false || strpos($value, '>')!==false) return false; + if (strpos($value, '%')!==false) return false; + return true; + } +} \ No newline at end of file diff --git a/zira/forms/user/avatar.php b/zira/forms/user/avatar.php new file mode 100644 index 0000000..c6716a4 --- /dev/null +++ b/zira/forms/user/avatar.php @@ -0,0 +1,120 @@ +_id); + } + + protected function _init() { + $w = intval(Config::get('user_thumb_width')); + $h = intval(Config::get('user_thumb_height')); + + View::addCropper($this->_cropper_id, array( + 'dst_w' => $w, + 'dst_h' => $h, + 'sel_w' => $w, + 'sel_h' => $h, + 'sel_mw' => $w, + 'sel_mh' => $h, + 'fixed' => true, + 'preview' => true, + 'previewer' => $this->_previewer_id, + 'input_w'=>'cropper_w', + 'input_h'=>'cropper_h', + 'input_x'=>'cropper_x', + 'input_y'=>'cropper_y' + )); + $this->setTitle(Locale::t('Change avatar')); + $this->setDescription(Locale::t('Select your desired area')); + } + + protected function _render() { + $image = $this->getValue('image'); + $filename = User::getUserPhotoFilename($image); + $url = Helper::baseUrl(UPLOADS_DIR . '/' . USERS_DIR . '/' . $filename); + $size = @getimagesize(File::getAbsolutePath(USERS_DIR). DIRECTORY_SEPARATOR . $filename); + if ($size[0]>$size[1]) { + $height = $this->_cropper_width; + $width = round($height * $size[0] / $size[1]); + } else { + $width = $this->_cropper_width; + $height = round($width * $size[1] / $size[0]); + } + + $html = $this->open(); + $html .= Helper::tag_open('div',array('class'=>$this->_group_class)); + $html .= Helper::tag('label', Locale::t('Photo'), array('class'=>$this->_label_class)); + $html .= Helper::tag_open('div',array('class'=>$this->_input_wrap_class)); + $html .= Helper::tag_short('img', array('src'=>$url,'width'=>$width,'height'=>$height,'id'=>$this->_cropper_id)); + $html .= Helper::tag_close('div'); + $html .= Helper::tag_close('div'); + $html .= Helper::tag_open('div',array('class'=>$this->_group_class)); + $html .= Helper::tag('label', Locale::t('Avatar'), array('class'=>$this->_label_class)); + $html .= Helper::tag_open('div',array('class'=>$this->_input_wrap_class)); + $html .= Helper::tag('div', null, array('id'=>$this->_previewer_id)); + $html .= Helper::tag_close('div'); + $html .= Helper::tag_close('div'); + $html .= $this->hidden('cropper_w'); + $html .= $this->hidden('cropper_h'); + $html .= $this->hidden('cropper_x'); + $html .= $this->hidden('cropper_y'); + if (!User::isUserPasswordChecked()) { + $html .= $this->password(Locale::t('Current password').'*','password-current'); + } + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + if (!User::isUserPasswordChecked()) { + $validator->registerString('password-current',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerCustom(array(get_class(), 'checkPassword'), 'password-current', Locale::t('Current password incorrect')); + } + $width = floatval($this->getValue('cropper_w')); + $height = floatval($this->getValue('cropper_h')); + $left = floatval($this->getValue('cropper_x')); + $top = floatval($this->getValue('cropper_y')); + + $this->updateValues(array( + 'cropper_w' => $width, + 'cropper_h' => $height, + 'cropper_x' => $left, + 'cropper_y' => $top + )); + } + + public static function checkPassword($password) { + $user = User::getCurrent(); + if (!$user || !User::isAuthorized()) return false; + $success = User::isPasswordCorrect($user->username, $password); + if ($success) { + User::setUserPasswordChecked(); + } + return $success; + } +} \ No newline at end of file diff --git a/zira/forms/user/compose.php b/zira/forms/user/compose.php new file mode 100644 index 0000000..6f3a60b --- /dev/null +++ b/zira/forms/user/compose.php @@ -0,0 +1,148 @@ +_id); + } + + public function getUsers() { + return self::$_users; + } + + protected function _init() { + $this->setAjax(true); + $this->setTitle(Locale::t('New message')); + $this->setDescription(Locale::t('Please enter user login, full name or ID')); + $script = Helper::tag_open('script', array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){'; + $script .= 'jQuery(\'#'.$this->getId().'\').bind(\'xhr-submit-success\', function(){'; + $script .= 'jQuery(\'#'.$this->getId().'\').get(0).reset();'; + $script .= '});'; + $script .= 'jQuery(\'#'.$this->getId().'\').bind(\'xhr-submit-error\', function(){'; + $script .= 'jQuery(\'.zira_form_compose_add_recipient_input\').each(function(){'; + $script .= 'var text = jQuery(this).data(\'autocomplete_text\');'; + $script .= 'if (typeof(text)!="undefined" && text) jQuery(this).val(text);'; + $script .= '});'; + $script .= '});'; + $script .= 'jQuery(\'.zira_form_compose_add_recipient_input\').parent().append(\'\');'; + $script .= 'jQuery(\'.zira_form_compose_add_recipient_btn\').click(function(e){'; + $script .= 'e.stopPropagation(); e.preventDefault();'; + $script .= 'if (jQuery(\'.zira_form_compose_add_recipient_input\').length>='.self::MAX_RECIPIENTS.') return;'; + $script .= 'var con = jQuery(\'.zira_form_compose_add_recipient_input\').last().parents(\'.form-group\');'; + $script .= '$(con).after(\'
    \'+$(con).html()+\'
    \');'; + $script .= 'if (jQuery(\'.zira_form_compose_add_recipient_input\').length>='.self::MAX_RECIPIENTS.'){'; + $script .= 'jQuery(\'.zira_form_compose_add_recipient_btn\').attr(\'disabled\',\'disabled\');'; + $script .= '}'; + $script .= '});'; + $script .= 'jQuery(\'.container #content\').on(\'click\', \'.zira_form_compose_remove_recipient_input\', function(e){'; + $script .= 'jQuery(this).parents(\'.form-group\').remove();'; + $script .= 'if (jQuery(\'.zira_form_compose_add_recipient_input\').length<'.self::MAX_RECIPIENTS.'){'; + $script .= 'jQuery(\'.zira_form_compose_add_recipient_btn\').removeAttr(\'disabled\');'; + $script .= '}'; + $script .= '});'; + $script .= 'jQuery(\'#'.$this->getId().'\').submit(function(){'; + $script .= 'jQuery(\'.zira_form_compose_add_recipient_input\').each(function(){'; + $script .= 'var id = jQuery(this).data(\'autocomplete_id\');'; + $script .= 'if (typeof(id)!="undefined" && id) jQuery(this).val(id);'; + $script .= '});'; + $script .= '});'; + $script .= '});'; + $script .= Helper::tag_close('script'); + View::addHTML($script, View::VAR_BODY_BOTTOM); + View::addAutoCompleter(); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('Recipient').'*','users[]',array('class'=>'form-control form-input-autocomplete zira_form_compose_add_recipient_input','data-url'=>Zira\Helper::url('user/autocomplete'),'data-token'=>Zira\User::getToken())); + $html .= $this->button(Locale::t('Add recipient'), array('class'=>'btn btn-default zira_form_compose_add_recipient_btn','type'=>'button')); + $html .= $this->input(Locale::t('Subject').'*','subject'); + + $extra_items = \Zira\Hook::run(\Zira\Page::USER_TEXTAREA_HOOK); + if (!empty($extra_items)) { + $html .= Helper::tag_open('div',array('class'=>'user-text-form-extra-items')); + foreach($extra_items as $item) { + $html .= Helper::tag_open('div',array('class'=>'user-text-form-extra-item')); + $html .= $item; + $html .= Helper::tag_close('div'); + } + $html .= Helper::tag_close('div'); + } + + $html .= $this->textarea(Locale::t('Message').'*', 'content'); + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + $validator->registerString('subject', null, 255, true, Locale::t('Please specify the subject of your message')); + $validator->registerNoTags('subject', Locale::t('Subject contains bad character')); + $validator->registerText('content', \Zira\Models\Message::MIN_CHARS, true, Locale::t('Message should contain at least %s characters', \Zira\Models\Message::MIN_CHARS)); + $validator->registerNoTags('content', Locale::t('Message contains bad character')); + $validator->registerCustom(array(get_class(), 'checkUsers'), 'users', Locale::t('Please enter correct user login, full name or ID')); + } + + public static function checkUsers($users) { + if (!is_array($users) || empty($users)) return false; + if (count($users)>self::MAX_RECIPIENTS) return false; + $added = array(); + foreach($users as $user_id) { + if (empty($user_id)) { + return false; + } else if (is_numeric($user_id)) { + $user = new Zira\Models\User($user_id); + if (!$user->loaded() || !$user->active) return false; + } else if (strpos($user_id, ' ')>0) { + $parts = explode(' ', $user_id); + if (count($parts)!=2) return false; + $_user = Zira\Models\User::getCollection() + ->where('firstname','=',$parts[0]) + ->and_where('secondname','=',$parts[1]) + ->and_where('active','=',Zira\Models\User::STATUS_ACTIVE) + ->order_by('id','asc') + ->limit(1) + ->get(0, true); + if (!$_user) return false; + $user = new Zira\Models\User(); + $user->loadFromArray($_user); + } else { + $_user = Zira\Models\User::getCollection() + ->where('username','=',$user_id) + ->and_where('active','=',Zira\Models\User::STATUS_ACTIVE) + ->limit(1) + ->order_by('id','asc') + ->get(0, true); + if (!$_user) return false; + $user = new Zira\Models\User(); + $user->loadFromArray($_user); + } + if (Zira\User::isSelf($user)) return false; + if (in_array($user->id, $added)) continue; + self::$_users []= $user; + $added []= $user->id; + } + return true; + } +} \ No newline at end of file diff --git a/zira/forms/user/confirm.php b/zira/forms/user/confirm.php new file mode 100644 index 0000000..e2f4c84 --- /dev/null +++ b/zira/forms/user/confirm.php @@ -0,0 +1,69 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('Email confirmation')); + $this->setDescription(Locale::t('Verification code was sent to your Email address')); + } + + protected function _render() { + $html = $this->open(); + if (!User::isAuthorized()) { + $html .= $this->input(Locale::t('Username or Email').'*','login'); + } + $html .= $this->input(Locale::t('Verification code').'*','code'); + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= Helper::tag_open('p',array('class'=>'text-right')); + $html .= Helper::tag('a', Locale::t('Did not recieve verification code ?'), array('href'=>Helper::url('user/send'))); + $html .= Helper::tag_close('p'); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + $validator->registerString('code', 0, 0, true, Locale::t('Incorrect verification code')); + if (!User::isAuthorized()) { + $login = (string)$this->getValue('login'); + $is_email = strpos($login, '@') !== false; + + if (!$is_email) { + $validator->registerString('login',User::LOGIN_MIN_CHARS,User::LOGIN_MAX_CHARS,true,Locale::t('Invalid username')); + $validator->registerRegexp('login', User::REGEXP_LOGIN, Locale::t('Login must contain only letters and numbers')); + } else { + $validator->registerEmail('login',true,Locale::t('Invalid email')); + } + $validator->registerCustom(array(get_class(), 'checkVerificationCode'), array('code','login'), Locale::t('Incorrect verification code')); + } else { + $validator->registerCustom(array(get_class(), 'checkVerificationCode'), array('code'), Locale::t('Incorrect verification code')); + } + } + + public static function checkVerificationCode($code, $login=null) { + if (User::isAuthorized()) { + $current = User::getCurrent(); + $login = $current->username; + } + return User::isVerificationCodeCorrect($login, $code); + } +} \ No newline at end of file diff --git a/zira/forms/user/conversation.php b/zira/forms/user/conversation.php new file mode 100644 index 0000000..6cd8256 --- /dev/null +++ b/zira/forms/user/conversation.php @@ -0,0 +1,54 @@ +_recipient = $recipient; + parent::__construct($this->_id); + } + + protected function _init() { + $this->setAjax(true); + $this->setTitle(Locale::t('New message')); + $this->setDescription(Locale::t('Message to: %s', User::getProfileName($this->_recipient))); + $script = Helper::tag_open('script', array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){ jQuery(\'#'.$this->getId().'\').bind(\'xhr-submit-success\', function(){ jQuery(\'#'.$this->getId().'\').get(0).reset(); }); });'; + $script .= Helper::tag_close('script'); + View::addHTML($script, View::VAR_BODY_BOTTOM); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('Subject').'*','subject'); + $html .= $this->textarea(Locale::t('Message').'*', 'content'); + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + $validator->registerString('subject', null, 255, true, Locale::t('Please specify the subject of your message')); + $validator->registerNoTags('subject', Locale::t('Subject contains bad character')); + $validator->registerText('content', \Zira\Models\Message::MIN_CHARS, true, Locale::t('Message should contain at least %s characters', \Zira\Models\Message::MIN_CHARS)); + $validator->registerNoTags('content', Locale::t('Message contains bad character')); + } +} \ No newline at end of file diff --git a/zira/forms/user/edit.php b/zira/forms/user/edit.php new file mode 100644 index 0000000..0726f47 --- /dev/null +++ b/zira/forms/user/edit.php @@ -0,0 +1,91 @@ +_id); + } + + protected function _init() { + $this->initDatepicker('dob', 'years', date('Y-m-d')); + $this->setTitle(Locale::t('Change profile')); + $this->setDescription(Locale::t('Please enter your first name and second name')); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('First name').'*','firstname'); + $html .= $this->input(Locale::t('Second name').'*','secondname'); + $html .= $this->input(Locale::t('Country'),'country'); + $html .= $this->input(Locale::t('City'),'city'); + $html .= $this->input(Locale::t('Street'),'street'); + $html .= $this->input(Locale::t('Phone'),'phone', array('placeholder'=>'+7...')); + $html .= $this->datepicker(Locale::t('Date of birth'), 'dob'); + if (!User::isUserPasswordChecked()) { + $html .= $this->password(Locale::t('Current password').'*','password-current'); + } + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + $validator->registerString('firstname',0,0,true,Locale::t('Please enter your first name')); + $validator->registerString('secondname',0,0,true,Locale::t('Please enter your second name')); + $validator->registerNoTags('firstname', Locale::t('Invalid character specified')); + $validator->registerNoTags('secondname', Locale::t('Invalid character specified')); + $validator->registerNoTags('country', Locale::t('Invalid character specified')); + $validator->registerNoTags('city', Locale::t('Invalid character specified')); + $validator->registerNoTags('street', Locale::t('Invalid character specified')); + $validator->registerPhone('phone', false, Locale::t('Phone should be specified in international format')); + $validator->registerDate('dob', false, Locale::t('Invalid date format')); + if (!User::isUserPasswordChecked()) { + $validator->registerString('password-current',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerCustom(array(get_class(), 'checkPassword'), 'password-current', Locale::t('Current password incorrect')); + } + + $firstname = trim((string)$this->getValue('firstname')); + $secondname = trim((string)$this->getValue('secondname')); + $country = trim((string)$this->getValue('country')); + $city = trim((string)$this->getValue('city')); + $street = trim((string)$this->getValue('street')); + $phone = trim((string)$this->getValue('phone')); + if (!empty($phone)) { + $phone = str_replace(' ','',$phone); + $phone = str_replace('-','',$phone); + } + $this->updateValues(array( + 'firstname' => $firstname, + 'secondname' => $secondname, + 'country' => $country, + 'city' => $city, + 'street' => $street, + 'phone' => $phone + )); + } + + public static function checkPassword($password) { + $user = User::getCurrent(); + if (!$user || !User::isAuthorized()) return false; + $success = User::isPasswordCorrect($user->username, $password); + if ($success) { + User::setUserPasswordChecked(); + } + return $success; + } +} \ No newline at end of file diff --git a/zira/forms/user/email.php b/zira/forms/user/email.php new file mode 100644 index 0000000..ba56314 --- /dev/null +++ b/zira/forms/user/email.php @@ -0,0 +1,72 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('Change email')); + $this->setDescription(Locale::t('Enter a valid email')); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('Email').'*','email'); + $html .= $this->checkbox(Locale::t('recieve notifications'), 'subscribed'); + if (!User::isUserPasswordChecked()) { + $html .= $this->password(Locale::t('Current password').'*','password-current'); + } + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + $validator->registerEmail('email',true,Locale::t('Invalid email')); + if (!User::isUserPasswordChecked()) { + $validator->registerString('password-current',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerCustom(array(get_class(), 'checkPassword'), 'password-current', Locale::t('Current password incorrect')); + } + //$validator->registerExists('email', \Zira\Models\User::getClass(), 'email', Locale::t('Specified email already exists')); + $validator->registerCustom(array(get_class(), 'checkEmailExists'), 'email', Locale::t('Specified email already exists')); + } + + public static function checkEmailExists($email) { + $user = User::getCurrent(); + if (!$user || !User::isAuthorized()) return false; + $exists = \Zira\Models\User::getCollection() + ->count() + ->where('email','=',$email) + ->and_where('id','<>',$user->id) + ->get('co'); + + return !(bool)$exists; + } + + public static function checkPassword($password) { + $user = User::getCurrent(); + if (!$user || !User::isAuthorized()) return false; + $success = User::isPasswordCorrect($user->username, $password); + if ($success) { + User::setUserPasswordChecked(); + } + return $success; + } +} \ No newline at end of file diff --git a/zira/forms/user/login.php b/zira/forms/user/login.php new file mode 100644 index 0000000..5c49475 --- /dev/null +++ b/zira/forms/user/login.php @@ -0,0 +1,93 @@ +_id); + } + + protected function _init() { + $action = 'user/login'; + $redirect = Request::get('redirect'); + if (!empty($redirect) && strpos($redirect, '//')===false && strpos($redirect, '.')===false) $action .= '?redirect='.$redirect; + $this->setUrl($action); + $this->setTitle(Locale::t('Sign In')); + $this->setDescription(Locale::t('Enter your username or email')); + $script = Helper::tag_open('script', array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){ jQuery(\'#'.$this->getId().'\').find(\'input[type=text]\').focus(); });'; + $script .= Helper::tag_close('script'); + View::addHTML($script, View::VAR_HEAD_BOTTOM); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('Username or Email').'*','login'); + $html .= $this->password(Locale::t('Password').'*','password'); + $html .= $this->checkbox(Locale::t('Remember me'), 'rememberme'); + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + + $extra_items = \Zira\Hook::run(self::HOOK_NAME); + if (!empty($extra_items)) { + $html .= Helper::tag_open('div',array('class'=>'user-login-form-extra-items')); + foreach($extra_items as $item) { + $html .= Helper::tag_open('div',array('class'=>'user-login-form-extra-item')); + $html .= $item; + $html .= Helper::tag_close('div'); + } + $html .= Helper::tag_close('div'); + } + + $html .= Helper::tag_open('p',array('class'=>'text-right')); + $html .= Helper::tag('a', Locale::t('Forgot password ?'), array('href'=>Helper::url('user/recover'))); + if (\Zira\Config::get('user_signup_allow')) { + $html .= ' | '; + $html .= Helper::tag('a', Locale::t('Sign Up'), array('href' => Helper::url('user/signup'))); + } + $html .= Helper::tag_close('p'); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $login = (string)$this->getValue('login'); + $is_email = strpos($login, '@') !== false; + + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + if (!$is_email) { + $validator->registerString('login',User::LOGIN_MIN_CHARS,User::LOGIN_MAX_CHARS,true,Locale::t('Invalid username')); + $validator->registerRegexp('login', User::REGEXP_LOGIN, Locale::t('Login must contain only letters and numbers')); + } else { + $validator->registerEmail('login',true,Locale::t('Invalid email')); + } + $validator->registerString('password',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerRegexp('password', User::REGEXP_PASSWORD, Locale::t('Password contain bad characters')); + $validator->registerCustom(array(get_class(), 'checkPassword'), array('login','password'), $is_email ? Locale::t('Email or password incorrect') : Locale::t('Username or password incorrect')); + } + + public static function checkPassword($login, $password) { + $success = User::isPasswordCorrect($login, $password); + if ($success) { + User::setUserPasswordChecked(); + } + return $success; + } +} \ No newline at end of file diff --git a/zira/forms/user/message.php b/zira/forms/user/message.php new file mode 100644 index 0000000..8cdc9d0 --- /dev/null +++ b/zira/forms/user/message.php @@ -0,0 +1,59 @@ +_id); + } + + protected function _init() { + $this->setAjax(true); + $this->setTitle(Locale::t('Reply')); + $this->setDescription(Locale::t('Message should contain at least %s characters', \Zira\Models\Message::MIN_CHARS)); + $script = Helper::tag_open('script', array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){ jQuery(\'#'.$this->getId().'\').bind(\'xhr-submit-success\', function(){ jQuery(\'#'.$this->getId().'\').get(0).reset(); }); });'; + $script .= Helper::tag_close('script'); + View::addHTML($script, View::VAR_BODY_BOTTOM); + } + + protected function _render() { + $html = $this->open(); + + $extra_items = \Zira\Hook::run(\Zira\Page::USER_TEXTAREA_HOOK); + if (!empty($extra_items)) { + $html .= Helper::tag_open('div',array('class'=>'user-text-form-extra-items')); + foreach($extra_items as $item) { + $html .= Helper::tag_open('div',array('class'=>'user-text-form-extra-item')); + $html .= $item; + $html .= Helper::tag_close('div'); + } + $html .= Helper::tag_close('div'); + } + + $html .= $this->textarea(Locale::t('Message').'*', 'content'); + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + $validator->registerText('content', \Zira\Models\Message::MIN_CHARS, true, Locale::t('Message should contain at least %s characters', \Zira\Models\Message::MIN_CHARS)); + $validator->registerNoTags('content', Locale::t('Message contains bad character')); + } +} \ No newline at end of file diff --git a/zira/forms/user/name.php b/zira/forms/user/name.php new file mode 100644 index 0000000..6769151 --- /dev/null +++ b/zira/forms/user/name.php @@ -0,0 +1,59 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('Change username')); + $this->setDescription(Locale::t('At least %s characters required',User::LOGIN_MIN_CHARS)); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('Username').'*','login'); + if (!User::isUserPasswordChecked()) { + $html .= $this->password(Locale::t('Current password').'*','password-current'); + } + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + $validator->registerString('login',User::LOGIN_MIN_CHARS,User::LOGIN_MAX_CHARS,true,Locale::t('Invalid username')); + $validator->registerRegexp('login', User::REGEXP_LOGIN, Locale::t('Login must contain only letters and numbers')); + if (!User::isUserPasswordChecked()) { + $validator->registerString('password-current',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerCustom(array(get_class(), 'checkPassword'), 'password-current', Locale::t('Current password incorrect')); + } + $validator->registerExists('login', \Zira\Models\User::getClass(), 'username', Locale::t('Specified login already exists')); + } + + public static function checkPassword($password) { + $user = User::getCurrent(); + if (!$user || !User::isAuthorized()) return false; + $success = User::isPasswordCorrect($user->username, $password); + if ($success) { + User::setUserPasswordChecked(); + } + return $success; + } +} \ No newline at end of file diff --git a/zira/forms/user/nophoto.php b/zira/forms/user/nophoto.php new file mode 100644 index 0000000..a3dd880 --- /dev/null +++ b/zira/forms/user/nophoto.php @@ -0,0 +1,51 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('Remove photo')); + $this->setDescription(Locale::t('Please enter your password')); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->password(Locale::t('Current password').'*','password-current'); + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + $validator->registerString('password-current',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerCustom(array(get_class(), 'checkPassword'), 'password-current', Locale::t('Current password incorrect')); + } + + public static function checkPassword($password) { + $user = User::getCurrent(); + if (!$user || !User::isAuthorized()) return false; + $success = User::isPasswordCorrect($user->username, $password); + if ($success) { + User::setUserPasswordChecked(); + } + return $success; + } +} \ No newline at end of file diff --git a/zira/forms/user/password.php b/zira/forms/user/password.php new file mode 100644 index 0000000..9b45e5e --- /dev/null +++ b/zira/forms/user/password.php @@ -0,0 +1,64 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('Password recovery')); + $this->setDescription(Locale::t('Verification code was sent to your Email address')); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('Username or Email').'*','login'); + $html .= $this->input(Locale::t('Verification code').'*','code'); + $html .= $this->captcha(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $login = (string)$this->getValue('login'); + $is_email = strpos($login, '@') !== false; + + $validator = $this->getValidator(); + $validator->registerCaptcha(Locale::t('Wrong CAPTCHA result')); + if (!$is_email) { + $validator->registerString('login',User::LOGIN_MIN_CHARS,User::LOGIN_MAX_CHARS,true,Locale::t('Invalid username')); + $validator->registerRegexp('login', User::REGEXP_LOGIN, Locale::t('Login must contain only letters and numbers')); + } else { + $validator->registerEmail('login',true,Locale::t('Invalid email')); + } + $validator->registerString('code', 0, 0, true, Locale::t('Incorrect verification code')); + $validator->registerCustom(array(get_class(), 'isUserExists'), 'login', Locale::t('User not found')); + $validator->registerCustom(array(get_class(), 'checkVerificationCode'), array('code','login'), Locale::t('Incorrect verification code')); + } + + public static function isUserExists($login) { + $user = \Zira\Models\User::findAuthUser($login); + if (!$user) return false; + if ($user->verified != \Zira\Models\User::STATUS_VERIFIED) return false; + User::setCurrent($user); + return true; + } + + public static function checkVerificationCode($code, $login) { + return User::isRecoveryCodeCorrect($login, $code); + } +} \ No newline at end of file diff --git a/zira/forms/user/photo.php b/zira/forms/user/photo.php new file mode 100644 index 0000000..3da3358 --- /dev/null +++ b/zira/forms/user/photo.php @@ -0,0 +1,67 @@ +_id); + } + + protected function _init() { + $this->setMultipart(true); + $this->setTitle(Locale::t('Change photo')); + $this->setDescription(Locale::t('Allowed file extensions: %s', 'jpg, png, gif')); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->fileButton(Locale::t('Photo').'*','photo'); + if (!User::isUserPasswordChecked()) { + $html .= $this->password(Locale::t('Current password').'*','password-current'); + } + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + $validator->registerImage('photo', 0, true, Locale::t('Invalid image file')); + $validator->registerCustom(array(get_class(), 'checkSize'), 'photo', Locale::t('Photo size should be at least %s pixels',Config::get('user_photo_min_width').'x'.config::get('user_photo_min_height'))); + if (!User::isUserPasswordChecked()) { + $validator->registerString('password-current',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerCustom(array(get_class(), 'checkPassword'), 'password-current', Locale::t('Current password incorrect')); + } + } + + public static function checkSize($photo) { + $size = @getimagesize($photo['tmp_name']); + if ($size[0]username, $password); + if ($success) { + User::setUserPasswordChecked(); + } + return $success; + } +} \ No newline at end of file diff --git a/zira/forms/user/pwd.php b/zira/forms/user/pwd.php new file mode 100644 index 0000000..dd27684 --- /dev/null +++ b/zira/forms/user/pwd.php @@ -0,0 +1,58 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('Change password')); + $this->setDescription(Locale::t('At least %s characters required',User::PASSWORD_MIN_CHARS)); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->password(Locale::t('New password').'*','password'); + $html .= $this->password(Locale::t('Repeat password').'*','password-match'); + $html .= $this->password(Locale::t('Current password').'*','password-current'); + $html .= $this->captchaLazy(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + + $validator->registerCaptchaLazy($this->_id, Locale::t('Wrong CAPTCHA result')); + $validator->registerString('password',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerString('password-match',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerMatch('password','password-match',Locale::t('Passwords do not match')); + $validator->registerRegexp('password', User::REGEXP_PASSWORD, Locale::t('Password contain bad characters')); + $validator->registerString('password-current',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerCustom(array(get_class(), 'checkPassword'), 'password-current', Locale::t('Current password incorrect')); + } + + public static function checkPassword($password) { + $user = User::getCurrent(); + if (!$user || !User::isAuthorized()) return false; + $success = User::isPasswordCorrect($user->username, $password); + if ($success) { + User::setUserPasswordChecked(); + } + return $success; + } +} \ No newline at end of file diff --git a/zira/forms/user/recover.php b/zira/forms/user/recover.php new file mode 100644 index 0000000..f70895f --- /dev/null +++ b/zira/forms/user/recover.php @@ -0,0 +1,57 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('Password recovery')); + $this->setDescription(Locale::t('Verification code will be sent to your Email address')); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('Username or Email').'*','login'); + $html .= $this->captcha(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $login = (string)$this->getValue('login'); + $is_email = strpos($login, '@') !== false; + + $validator = $this->getValidator(); + $validator->registerCaptcha(Locale::t('Wrong CAPTCHA result')); + if (!$is_email) { + $validator->registerString('login',User::LOGIN_MIN_CHARS,User::LOGIN_MAX_CHARS,true,Locale::t('Invalid username')); + $validator->registerRegexp('login', User::REGEXP_LOGIN, Locale::t('Login must contain only letters and numbers')); + } else { + $validator->registerEmail('login',true,Locale::t('Invalid email')); + } + $validator->registerCustom(array(get_class(), 'isUserExists'), 'login', Locale::t('User not found')); + } + + public static function isUserExists($login) { + $user = \Zira\Models\User::findAuthUser($login); + if (!$user) return false; + if ($user->verified != \Zira\Models\User::STATUS_VERIFIED) return false; + User::setCurrent($user); + return true; + } +} \ No newline at end of file diff --git a/zira/forms/user/register.php b/zira/forms/user/register.php new file mode 100644 index 0000000..aa28ced --- /dev/null +++ b/zira/forms/user/register.php @@ -0,0 +1,64 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('User Signup')); + $this->setDescription(Locale::t('Pick a username and password')); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('First name').'*','firstname',array('title'=>Locale::t('Please enter your first name'))); + $html .= $this->input(Locale::t('Second name').'*','secondname',array('title'=>Locale::t('Please enter your second name'))); + $html .= $this->input(Locale::t('Username').'*','username',array('title'=>Locale::t('At least %s characters required',User::LOGIN_MIN_CHARS))); + $html .= $this->input(Locale::t('Email').'*','email',array('title'=>Locale::t('Enter a valid email'))); + $html .= $this->password(Locale::t('Password').'*','password',array('title'=>Locale::t('At least %s characters required',User::PASSWORD_MIN_CHARS))); + $html .= $this->password(Locale::t('Repeat password').'*','password-match',array('title'=>Locale::t('Enter password again'))); + $html .= $this->captcha(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $validator = $this->getValidator(); + $validator->registerCaptcha(Locale::t('Wrong CAPTCHA result')); + $validator->registerString('firstname',0,0,true,Locale::t('Please enter your first name')); + $validator->registerString('secondname',0,0,true,Locale::t('Please enter your second name')); + $validator->registerNoTags('firstname', Locale::t('Invalid character specified')); + $validator->registerNoTags('secondname', Locale::t('Invalid character specified')); + $validator->registerString('username',User::LOGIN_MIN_CHARS,User::LOGIN_MAX_CHARS,true,Locale::t('Invalid username')); + $validator->registerEmail('email',true,Locale::t('Invalid email')); + $validator->registerString('password',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerString('password-match',User::PASSWORD_MIN_CHARS,User::PASSWORD_MAX_CHARS,true,Locale::t('Invalid password')); + $validator->registerRegexp('username', User::REGEXP_LOGIN, Locale::t('Login must contain only letters and numbers')); + $validator->registerMatch('password','password-match',Locale::t('Passwords do not match')); + $validator->registerRegexp('password', User::REGEXP_PASSWORD, Locale::t('Password contain bad characters')); + $validator->registerExists('username', \Zira\Models\User::getClass(), 'username', Locale::t('Specified login already exists')); + $validator->registerExists('email', \Zira\Models\User::getClass(), 'email', Locale::t('Specified email already exists')); + + $firstname = trim((string)$this->getValue('firstname')); + $secondname = trim((string)$this->getValue('secondname')); + $this->updateValues(array( + 'firstname' => $firstname, + 'secondname' => $secondname + )); + } +} \ No newline at end of file diff --git a/zira/forms/user/send.php b/zira/forms/user/send.php new file mode 100644 index 0000000..0abef82 --- /dev/null +++ b/zira/forms/user/send.php @@ -0,0 +1,58 @@ +_id); + } + + protected function _init() { + $this->setTitle(Locale::t('Send confirmation code')); + $this->setDescription(Locale::t('Enter your username or email')); + } + + protected function _render() { + $html = $this->open(); + $html .= $this->input(Locale::t('Username or Email').'*','login'); + $html .= $this->captcha(Locale::t('Enter result').'*'); + $html .= $this->submit(Locale::t('Submit')); + $html .= $this->close(); + return $html; + } + + protected function _validate() { + $login = (string)$this->getValue('login'); + $is_email = strpos($login, '@') !== false; + + $validator = $this->getValidator(); + $validator->registerCaptcha(Locale::t('Wrong CAPTCHA result')); + if (!$is_email) { + $validator->registerString('login',User::LOGIN_MIN_CHARS,User::LOGIN_MAX_CHARS,true,Locale::t('Invalid username')); + $validator->registerRegexp('login', User::REGEXP_LOGIN, Locale::t('Login must contain only letters and numbers')); + } else { + $validator->registerEmail('login',true,Locale::t('Invalid email')); + } + $validator->registerCustom(array(get_class(), 'isUserExists'), 'login', Locale::t('User not found')); + } + + public static function isUserExists($login) { + $user = \Zira\Models\User::findAuthUser($login); + if (!$user) return false; + if ($user->verified == \Zira\Models\User::STATUS_VERIFIED) return false; + User::setCurrent($user); + return true; + } +} \ No newline at end of file diff --git a/zira/helper.php b/zira/helper.php new file mode 100644 index 0000000..e994473 --- /dev/null +++ b/zira/helper.php @@ -0,0 +1,128 @@ +1 && + (Locale::getLanguage()!=Config::get('language') || !empty($path)) + ) { + $url .= '/'.Locale::getLanguage(); + } + + $url .= '/'.$path; + if ($url != '/') $url = rtrim($url,'/'); + + return $url; + } + + public static function baseUrl($url,$absolute=false,$detect_protocol=false) { + $prefix = ''; + if ($absolute && $detect_protocol) { + $port = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80; + $protocol = $port == 443 ? 'https:' : 'http:'; + $prefix .= $protocol; + } + if ($absolute) $prefix .= '//' . $_SERVER['HTTP_HOST']; + return $prefix . rtrim(BASE_URL,'/') . '/' .ltrim($url,'/'); + } + + public static function assetUrl($url) { + return rtrim(BASE_URL,'/') . '/' . ASSETS_DIR . '/' .$url; + } + + public static function assetThemeUrl($url) { + return rtrim(BASE_URL,'/') . '/' . THEMES_DIR . '/' . View::getTheme() . '/' . ASSETS_DIR . '/' .$url; + } + + public static function cssUrl($url) { + return rtrim(BASE_URL,'/') . '/' . ASSETS_DIR . '/' . CSS_DIR . '/' .$url; + } + + public static function cssThemeUrl($url) { + return rtrim(BASE_URL,'/') . '/' . THEMES_DIR . '/' . View::getTheme() . '/' . ASSETS_DIR . '/' . CSS_DIR . '/' .$url; + } + + public static function jsUrl($url) { + return rtrim(BASE_URL,'/') . '/' . ASSETS_DIR . '/' . JS_DIR . '/' .$url; + } + + public static function jsThemeUrl($url) { + return rtrim(BASE_URL,'/') . '/' . THEMES_DIR . '/' . View::getTheme() . '/' . ASSETS_DIR . '/' . JS_DIR . '/' .$url; + } + + public static function imgUrl($url) { + return rtrim(BASE_URL,'/') . '/' . ASSETS_DIR . '/' . IMAGES_DIR . '/' .$url; + } + + public static function imgThemeUrl($url) { + return rtrim(BASE_URL,'/') . '/' . THEMES_DIR . '/' . View::getTheme() . '/' . ASSETS_DIR . '/' . IMAGES_DIR . '/' .$url; + } + + public static function tag_short($name, array $attributes = null) { + if (!$attributes) $attributes = array(); + $html = '<'.self::html($name); + foreach($attributes as $k=>$v) { + $html .= ' '.self::html($k) . '="' . self::html($v) . '"'; + } + $html .= ' />'; + return $html; + } + + public static function tag_open($name, array $attributes = null) { + if (!$attributes) $attributes = array(); + $html = '<'.self::html($name); + foreach($attributes as $k=>$v) { + $html .= ' '.self::html($k) . '="' . self::html($v) . '"'; + } + $html .= '>'; + return $html; + } + + public static function tag_close($name) { + return ''; + } + + public static function tag($name, $value = null, array $attributes = null) { + $html = self::tag_open($name, $attributes); + if ($value!==null) $html .= self::html($value); + $html .= self::tag_close($name); + return $html; + } + + public static function nl2br($str) { + return nl2br(trim($str)); + } +} \ No newline at end of file diff --git a/zira/hook.php b/zira/hook.php new file mode 100644 index 0000000..bbfd2c1 --- /dev/null +++ b/zira/hook.php @@ -0,0 +1,26 @@ += $p) { + $_src_width = $src_height * $p; + $src_x = ($src_width - $_src_width) / 2; + $src_width = $_src_width; + } else { + $_src_height = $src_width / $p; + $src_y = ($src_height - $_src_height) / 2; + $src_height = $_src_height; + } + + $dst_image=imagecreatetruecolor($dst_width,$dst_height); + if (!$dst_image) return false; + + $bg_color=imagecolorallocate($dst_image, 255, 255, 255); + imagefill($dst_image, 0, 0, $bg_color); + + if (!imagecopyresampled($dst_image, $src_image, 0, 0, $src_x, $src_y, $dst_width, $dst_height, $src_width, $src_height)) return false; + + $result = self::_imagesave($dst_image, $dst_path, $type); + + imagedestroy($src_image); + imagedestroy($dst_image); + + return $result; + } + + public static function save(array $file, $dir = null, $create_thumb = false, $watermark = false) { + $savedir = IMAGES_DIR; + if (!empty($dir)) $savedir .= DIRECTORY_SEPARATOR . $dir; + $files = File::save($file, $savedir); + if (!$files) return false; + if ($create_thumb) { + $savedir = THUMBS_DIR; + if (!empty($dir)) $savedir .= DIRECTORY_SEPARATOR . $dir; + $save_path = File::getAbsolutePath($savedir); + foreach($files as $path=>$name) { + if (!self::createThumb($path, $save_path . DIRECTORY_SEPARATOR . $name, Config::get('thumbs_width'), Config::get('thumbs_height'))) return false; + } + } + if ($watermark) { + $savedir = IMAGES_DIR; + if (!empty($dir)) $savedir .= DIRECTORY_SEPARATOR . $dir; + $save_path = File::getAbsolutePath($savedir); + foreach($files as $name) { + if (!self::watermark($save_path . DIRECTORY_SEPARATOR . $name)) break; + } + } + return $files; + } + + public static function watermark($src_path, $margin = 10) { + $watermark_path = Config::get('watermark'); + if (empty($watermark_path)) return false; + else $watermark_path = ROOT_DIR . DIRECTORY_SEPARATOR . $watermark_path; + if (!file_exists($watermark_path)) return false; + + $type = false; + $src_image=null; + $size = false; + + if (!self::_imagecreate($src_path, $src_image, $type, $size)) return false; + + $src_width=$size[0]; + $src_height=$size[1]; + + $watermark_type = false; + $watermark_image=null; + $size = false; + + if (!self::_imagecreate($watermark_path, $watermark_image, $watermark_type, $size)) return false; + + $watermark_width=$size[0]; + $watermark_height=$size[1]; + + if (!imagecopy( + $src_image, + $watermark_image, + $src_width - $watermark_width - $margin, + $src_height - $watermark_height - $margin, + 0, + 0, + $watermark_width, + $watermark_height + )) return false; + + $result = self::_imagesave($src_image, $src_path, $type); + + imagedestroy($src_image); + imagedestroy($watermark_image); + + return $result; + } +} \ No newline at end of file diff --git a/zira/install/blacklist.php b/zira/install/blacklist.php new file mode 100644 index 0000000..4174df4 --- /dev/null +++ b/zira/install/blacklist.php @@ -0,0 +1,47 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'user_id' => Field::int(true, true), + 'blocked_user_id' => Field::int(true, true), + 'message' => Field::string(true), + 'creation_date' => Field::datetime(true) + ); + } + + public function getKeys() { + return array( + + ); + } + + public function getUnique() { + return array( + 'user' => array('user_id','blocked_user_id') + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/block.php b/zira/install/block.php new file mode 100644 index 0000000..b5cd918 --- /dev/null +++ b/zira/install/block.php @@ -0,0 +1,47 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'name' => Field::string(true), + 'content' => Field::text(true), + 'placeholder' => Field::string(true), + 'tpl' => Field::tinyint(true, true, 0) + ); + } + + public function getKeys() { + return array( + + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/captcha.php b/zira/install/captcha.php new file mode 100644 index 0000000..6fd0779 --- /dev/null +++ b/zira/install/captcha.php @@ -0,0 +1,37 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'form_id' => Field::string(true), + 'date_created' => Field::datetime(true) + ); + } + + public function getKeys() { + return array( + 'recent' => array('form_id', 'date_created') + ); + } + + public function getUnique() { + return array(); + } +} \ No newline at end of file diff --git a/zira/install/category.php b/zira/install/category.php new file mode 100644 index 0000000..d1794ce --- /dev/null +++ b/zira/install/category.php @@ -0,0 +1,60 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'name' => Field::string(true), + 'title' => Field::string(true), + 'description' => Field::string(), + 'layout' => Field::string(true), + 'meta_title' => Field::string(), + 'meta_keywords' => Field::string(), + 'meta_description' => Field::string(), + 'parent_id' => Field::int(true, true, 0), + 'access_check' => Field::tinyint(true, true, 0), + 'slider_enabled' => Field::tinyint(false, true), + 'gallery_enabled' => Field::tinyint(false, true), + 'comments_enabled' => Field::tinyint(false, true), + 'rating_enabled' => Field::tinyint(false, true), + 'display_author' => Field::tinyint(false, true), + 'display_date' => Field::tinyint(false, true), + 'records_list' => Field::tinyint(false, true), + 'tpl' => Field::string() + ); + } + + public function getKeys() { + return array( + 'parent_id' => array('parent_id') + ); + } + + public function getUnique() { + return array( + 'name' => array('name') + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/comment.php b/zira/install/comment.php new file mode 100644 index 0000000..5910ce4 --- /dev/null +++ b/zira/install/comment.php @@ -0,0 +1,56 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'record_id' => Field::int(true, true), + 'author_id' => Field::int(true, true), + 'parent_id' => Field::int(true, true, 0), + 'sort_path' => Field::string(true), + 'path_offset' => Field::int(true, true), + 'content' => Field::text(), + 'sender_name' => Field::string(), + 'recipient_name' => Field::string(), + 'likes' => Field::int(true, true, 0), + 'dislikes' => Field::int(true, true, 0), + 'creation_date' => Field::datetime(true), + 'published' => Field::tinyint(true, true, 0) + ); + } + + public function getKeys() { + return array( + 'record' => array('record_id', 'published', 'sort_path'), + 'counter' => array('record_id', 'parent_id', 'path_offset') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/commentlike.php b/zira/install/commentlike.php new file mode 100644 index 0000000..f5095ec --- /dev/null +++ b/zira/install/commentlike.php @@ -0,0 +1,48 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'comment_id' => Field::int(true, true), + 'user_id' => Field::int(true, true), + 'anonymous_id' => Field::string(true), + 'rate' => Field::tinyint(true), + 'creation_date' => Field::datetime(true) + ); + } + + public function getKeys() { + return array( + 'like' => array('comment_id', 'user_id', 'anonymous_id') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/conversation.php b/zira/install/conversation.php new file mode 100644 index 0000000..57f3593 --- /dev/null +++ b/zira/install/conversation.php @@ -0,0 +1,50 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'conversation_id' => Field::int(true, true), + 'user_id' => Field::int(true, true), + 'subject' => Field::string(true), + 'highlight' => Field::tinyint(true, true, 1), + 'creation_date' => Field::datetime(true), + 'modified_date' => Field::datetime(true) + ); + } + + public function getKeys() { + return array( + 'user' => array('user_id', 'modified_date'), + 'conversation' => array('conversation_id') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/draft.php b/zira/install/draft.php new file mode 100644 index 0000000..73ef263 --- /dev/null +++ b/zira/install/draft.php @@ -0,0 +1,49 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'record_id' => Field::int(true, true), + 'author_id' => Field::int(true, true), + 'content' => Field::longtext(), + 'published' => Field::tinyint(true, true, 0), + 'creation_date' => Field::datetime(true), + 'modified_date' => Field::datetime(true) + ); + } + + public function getKeys() { + return array( + 'published' => array('published') + ); + } + + public function getUnique() { + return array( + 'record' => array('record_id', 'author_id') + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/group.php b/zira/install/group.php new file mode 100644 index 0000000..7a1a3f6 --- /dev/null +++ b/zira/install/group.php @@ -0,0 +1,60 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'name' => Field::string(true), + 'active' => Field::tinyint(true, true, 0) + ); + } + + public function getKeys() { + return array( + 'active' => array('active') + ); + } + + public function getUnique() { + return array( + 'name' => array('name') + ); + } + + public function getDefaults() { + return array( + array( + 'id' => \Zira\User::GROUP_SUPERADMIN, + 'name' => 'Super-Administrators', + 'active' => Model::STATUS_ACTIVE + ), + array( + 'id' => \Zira\User::GROUP_ADMIN, + 'name' => 'Administrators', + 'active' => Model::STATUS_ACTIVE + ), + array( + 'id' => \Zira\User::GROUP_USER, + 'name' => 'Users', + 'active' => Model::STATUS_ACTIVE + ) + ); + } +} \ No newline at end of file diff --git a/zira/install/image.php b/zira/install/image.php new file mode 100644 index 0000000..7c3fe24 --- /dev/null +++ b/zira/install/image.php @@ -0,0 +1,47 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'record_id' => Field::int(true, true), + 'description' => Field::string(), + 'thumb' => Field::string(true), + 'image' => Field::string(true) + ); + } + + public function getKeys() { + return array( + 'record_id' => array('record_id') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/like.php b/zira/install/like.php new file mode 100644 index 0000000..13f7afd --- /dev/null +++ b/zira/install/like.php @@ -0,0 +1,47 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'record_id' => Field::int(true, true), + 'user_id' => Field::int(true, true), + 'anonymous_id' => Field::string(true), + 'creation_date' => Field::datetime(true) + ); + } + + public function getKeys() { + return array( + 'like' => array('record_id', 'user_id', 'anonymous_id') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/menu.php b/zira/install/menu.php new file mode 100644 index 0000000..9e75e15 --- /dev/null +++ b/zira/install/menu.php @@ -0,0 +1,52 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'menu_id' => Field::int(true, true), + 'parent_id' => Field::int(true, true, 0), + 'url' => Field::string(true), + 'title' => Field::string(true), + 'class' => Field::string(), + 'language' => Field::string(), + 'sort_order' => Field::int(true, false, 0), + 'external' => Field::tinyint(true, true, 0), + 'active' => Field::tinyint(true, true, 1) + ); + } + + public function getKeys() { + return array( + 'menu' => array('menu_id', 'parent_id', 'language', 'sort_order') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/message.php b/zira/install/message.php new file mode 100644 index 0000000..3df4969 --- /dev/null +++ b/zira/install/message.php @@ -0,0 +1,47 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'conversation_id' => Field::int(true, true), + 'user_id' => Field::int(true, true), + 'content' => Field::text(true), + 'creation_date' => Field::datetime(true) + ); + } + + public function getKeys() { + return array( + 'conversation' => array('conversation_id') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/option.php b/zira/install/option.php new file mode 100644 index 0000000..3205ce4 --- /dev/null +++ b/zira/install/option.php @@ -0,0 +1,34 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'module' => Field::string(true), + 'name' => Field::string(true), + 'value' => Field::string(true) + ); + } + + public function getUnique() { + return array( + 'name' => array('name') + ); + } +} \ No newline at end of file diff --git a/zira/install/permission.php b/zira/install/permission.php new file mode 100644 index 0000000..45c12f0 --- /dev/null +++ b/zira/install/permission.php @@ -0,0 +1,142 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'group_id' => Field::int(true, true), + 'module' => Field::string(true), + 'name' => Field::string(true), + 'allow' => Field::tinyint(true, true, 0) + ); + } + + public function getKeys() { + return array( + + ); + } + + public function getUnique() { + return array( + 'name_by_group' => array('group_id', 'name') + ); + } + + protected function getDefaultSuperAdminPermissions() { + return array( + \Zira\Permission::TO_ACCESS_DASHBOARD => 1, + \Zira\Permission::TO_EXECUTE_TASKS => 1, + \Zira\Permission::TO_CHANGE_OPTIONS => 1, + \Zira\Permission::TO_CHANGE_LAYOUT => 1, + \Zira\Permission::TO_CREATE_USERS => 1, + \Zira\Permission::TO_EDIT_USERS => 1, + \Zira\Permission::TO_DELETE_USERS => 1, + \Zira\Permission::TO_UPLOAD_FILES => 1, + \Zira\Permission::TO_DELETE_FILES => 1, + \Zira\Permission::TO_VIEW_FILES => 1, + \Zira\Permission::TO_UPLOAD_IMAGES => 1, + \Zira\Permission::TO_DELETE_IMAGES => 1, + \Zira\Permission::TO_VIEW_IMAGES => 1, + \Zira\Permission::TO_CREATE_RECORDS => 1, + \Zira\Permission::TO_EDIT_RECORDS => 1, + \Zira\Permission::TO_DELETE_RECORDS => 1, + \Zira\Permission::TO_VIEW_RECORDS => 1, + \Zira\Permission::TO_VIEW_RECORD => 1, + \Zira\Permission::TO_MODERATE_COMMENTS => 1 + ); + } + + protected function getDefaultAdminPermissions() { + return array( + \Zira\Permission::TO_ACCESS_DASHBOARD => 1, + \Zira\Permission::TO_EXECUTE_TASKS => 0, + \Zira\Permission::TO_CHANGE_OPTIONS => 0, + \Zira\Permission::TO_CHANGE_LAYOUT => 0, + \Zira\Permission::TO_CREATE_USERS => 0, + \Zira\Permission::TO_EDIT_USERS => 0, + \Zira\Permission::TO_DELETE_USERS => 0, + \Zira\Permission::TO_UPLOAD_FILES => 0, + \Zira\Permission::TO_DELETE_FILES => 0, + \Zira\Permission::TO_VIEW_FILES => 1, + \Zira\Permission::TO_UPLOAD_IMAGES => 1, + \Zira\Permission::TO_DELETE_IMAGES => 1, + \Zira\Permission::TO_VIEW_IMAGES => 1, + \Zira\Permission::TO_CREATE_RECORDS => 1, + \Zira\Permission::TO_EDIT_RECORDS => 1, + \Zira\Permission::TO_DELETE_RECORDS => 1, + \Zira\Permission::TO_VIEW_RECORDS => 1, + \Zira\Permission::TO_VIEW_RECORD => 1, + \Zira\Permission::TO_MODERATE_COMMENTS => 1 + ); + } + + protected function getDefaultUserPermissions() { + return array( + \Zira\Permission::TO_ACCESS_DASHBOARD => 0, + \Zira\Permission::TO_EXECUTE_TASKS => 0, + \Zira\Permission::TO_CHANGE_OPTIONS => 0, + \Zira\Permission::TO_CHANGE_LAYOUT => 0, + \Zira\Permission::TO_CREATE_USERS => 0, + \Zira\Permission::TO_EDIT_USERS => 0, + \Zira\Permission::TO_DELETE_USERS => 0, + \Zira\Permission::TO_UPLOAD_FILES => 0, + \Zira\Permission::TO_DELETE_FILES => 0, + \Zira\Permission::TO_VIEW_FILES => 0, + \Zira\Permission::TO_UPLOAD_IMAGES => 0, + \Zira\Permission::TO_DELETE_IMAGES => 0, + \Zira\Permission::TO_VIEW_IMAGES => 0, + \Zira\Permission::TO_CREATE_RECORDS => 0, + \Zira\Permission::TO_EDIT_RECORDS => 0, + \Zira\Permission::TO_DELETE_RECORDS => 0, + \Zira\Permission::TO_VIEW_RECORDS => 1, + \Zira\Permission::TO_VIEW_RECORD => 1, + \Zira\Permission::TO_MODERATE_COMMENTS => 0 + ); + } + + public function getDefaults() { + $permissionsArray = \Zira\Permission::getPermissionsArray(); + $groupsArray = \Zira\User::getDefaultGroupsArray(); + $inserts = array(); + foreach($groupsArray as $group_id) { + switch($group_id) { + case \Zira\User::GROUP_SUPERADMIN: + $permissions = self::getDefaultSuperAdminPermissions(); + break; + case \Zira\User::GROUP_ADMIN: + $permissions = self::getDefaultAdminPermissions(); + break; + default: + $permissions = self::getDefaultUserPermissions(); + break; + } + foreach($permissionsArray as $name) { + $inserts[]=array( + 'id' => null, + 'group_id' => $group_id, + 'module' => 'zira', + 'name' => $name, + 'allow' => array_key_exists($name, $permissions) ? $permissions[$name] : 0 + ); + } + } + return $inserts; + } +} \ No newline at end of file diff --git a/zira/install/record.php b/zira/install/record.php new file mode 100644 index 0000000..a9940fb --- /dev/null +++ b/zira/install/record.php @@ -0,0 +1,63 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'category_id' => Field::int(true, true), + 'author_id' => Field::int(true, true), + 'name' => Field::string(true), + 'title' => Field::string(true), + 'description' => Field::text(), + 'content' => Field::longtext(), + 'thumb' => Field::string(), + 'image' => Field::string(), + 'meta_title' => Field::string(), + 'meta_keywords' => Field::string(), + 'meta_description' => Field::text(), + 'language' => Field::string(true), + 'access_check' => Field::tinyint(true, true, 0), + 'creation_date' => Field::datetime(true), + 'modified_date' => Field::datetime(true), + 'published' => Field::tinyint(true, true, 0), + 'front_page' => Field::tinyint(true, true, 0), + 'rating' => Field::int(true, false, 0), + 'comments' => Field::int(true, true, 0), + 'tpl' => Field::string() + ); + } + + public function getKeys() { + return array( + 'record' => array('category_id', 'language', 'name','published','front_page') + ); + } + + public function getUnique() { + return array( + 'url' => array('category_id', 'language', 'name') + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/search.php b/zira/install/search.php new file mode 100644 index 0000000..3f49388 --- /dev/null +++ b/zira/install/search.php @@ -0,0 +1,47 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'keyword' => Field::string(true), + 'record_id' => Field::int(true, true), + 'language' => Field::string(true), + ); + } + + public function getKeys() { + return array( + 'keyword' => array('language', 'keyword'), + 'record_id' => array('record_id') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/slide.php b/zira/install/slide.php new file mode 100644 index 0000000..4db8948 --- /dev/null +++ b/zira/install/slide.php @@ -0,0 +1,47 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'record_id' => Field::int(true, true), + 'description' => Field::string(), + 'thumb' => Field::string(true), + 'image' => Field::string(true) + ); + } + + public function getKeys() { + return array( + 'record_id' => array('record_id') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + + ); + } +} \ No newline at end of file diff --git a/zira/install/translate.php b/zira/install/translate.php new file mode 100644 index 0000000..8b1a950 --- /dev/null +++ b/zira/install/translate.php @@ -0,0 +1,35 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'module' => Field::string(true), + 'name' => Field::string(true), + 'value' => Field::string(true), + 'language' => Field::string(true) + ); + } + + public function getUnique() { + return array( + 'name' => array('name','language') + ); + } +} \ No newline at end of file diff --git a/zira/install/user.php b/zira/install/user.php new file mode 100644 index 0000000..35df4a9 --- /dev/null +++ b/zira/install/user.php @@ -0,0 +1,63 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'email' => Field::string(true), + 'username' => Field::string(true), + 'password' => Field::string(true), + 'group_id' => Field::tinyint(true, true, 0), + 'image' => Field::string(false), + 'firstname' => Field::string(false), + 'secondname' => Field::string(false), + 'dob' => Field::date(false), + 'phone' => Field::string(false), + 'country' => Field::string(false), + 'city' => Field::string(false), + 'address' => Field::string(false), + 'date_created' => Field::datetime(true), + 'date_logged' => Field::datetime(true), + 'verified' => Field::tinyint(true, true, 0), + 'active' => Field::tinyint(true, true, 0), + 'messages' => Field::int(true, true, 0), + 'comments' => Field::int(true, true, 0), + 'posts' => Field::int(true, true, 0), + 'subscribed' => Field::tinyint(true, true, 1), + 'vcode' => Field::string(false), + 'code' => Field::string(true), + 'token' => Field::string(false) + ); + } + + public function getKeys() { + return array( + 'group_id' => array('group_id'), + 'enabled' => array('verified', 'active') + ); + } + + public function getUnique() { + return array( + 'email' => array('email'), + 'username' => array('username'), + 'code' => array('code') + ); + } +} \ No newline at end of file diff --git a/zira/install/widget.php b/zira/install/widget.php new file mode 100644 index 0000000..a34af48 --- /dev/null +++ b/zira/install/widget.php @@ -0,0 +1,124 @@ +_table); + } + + public function getFields() { + return array( + 'id' => Field::primary(), + 'name' => Field::string(true), + 'module' => Field::string(true), + 'placeholder' => Field::string(true), + 'params' => Field::string(), + 'language' => Field::string(), + 'category_id' => Field::int(false, true), + 'sort_order' => Field::int(true, false, 0), + 'active' => Field::tinyint(true, true, 0), + 'filter' => Field::string() + ); + } + + public function getKeys() { + return array( + 'search' => array('language','category_id','active'), + 'sort_order' => array('sort_order') + ); + } + + public function getUnique() { + return array( + + ); + } + + public function getDefaults() { + return array( + array( + 'id' => null, + 'name' => '\Zira\Widgets\Languages', + 'module' => 'zira', + 'placeholder' => 'header', + 'params' => null, + 'language' => null, + 'category_id' => null, + 'sort_order' => 1, + 'active' => 0, + 'filter' => null + ), + array( + 'id' => null, + 'name' => '\Zira\Widgets\Usermenu', + 'module' => 'zira', + 'placeholder' => 'header', + 'params' => null, + 'language' => null, + 'category_id' => null, + 'sort_order' => 2, + 'active' => 1, + 'filter' => null + ), + array( + 'id' => null, + 'name' => '\Zira\Widgets\Logo', + 'module' => 'zira', + 'placeholder' => 'header', + 'params' => null, + 'language' => null, + 'category_id' => null, + 'sort_order' => 3, + 'active' => 1, + 'filter' => null + ), + array( + 'id' => null, + 'name' => '\Zira\Widgets\Topmenu', + 'module' => 'zira', + 'placeholder' => 'header', + 'params' => null, + 'language' => null, + 'category_id' => null, + 'sort_order' => 4, + 'active' => 1, + 'filter' => null + ), + array( + 'id' => null, + 'name' => '\Zira\Widgets\Childmenu', + 'module' => 'zira', + 'placeholder' => 'sidebar_right', + 'params' => null, + 'language' => null, + 'category_id' => null, + 'sort_order' => 5, + 'active' => 1, + 'filter' => null + ), + array( + 'id' => null, + 'name' => '\Zira\Widgets\Footermenu', + 'module' => 'zira', + 'placeholder' => 'footer', + 'params' => null, + 'language' => null, + 'category_id' => null, + 'sort_order' => 6, + 'active' => 1, + 'filter' => null + ) + ); + } +} \ No newline at end of file diff --git a/zira/locale.php b/zira/locale.php new file mode 100644 index 0000000..5bfe542 --- /dev/null +++ b/zira/locale.php @@ -0,0 +1,255 @@ +1 && + empty($_SERVER['HTTP_REFERER']) && + !Request::isRedirected() && + !Router::getRequest() && + !Router::getLanguage() + ) { + if (self::isRemembered()) { + $locale = self::getRemembered(); + } else { + $locale = self::detect(); + } + if ($locale!=Config::get('language')) { + Helper::setAddingLanguageToUrl(false); + Response::redirect($locale); + } + } + } + + public static function detect() { + if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) return false; + $locale = explode(';', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + $locale = explode(',', $locale[0]); + $locale = explode('-', $locale[0]); + $locale = strtolower($locale[0]); + if (!in_array($locale, Config::get('languages'))) return false; + return $locale; + } + + public static function remember() { + if (Request::isAjax() || Router::getModule()=='dash') return; + if (count(Config::get('languages'))>1) { + Cookie::set(self::COOKIE_NAME, self::getLanguage(), self::COOKIE_TIME); + } + } + + public static function getRemembered() { + $language = Cookie::get(self::COOKIE_NAME); + if (!$language) return false; + if (!in_array($language, Config::get('languages'))) { + Cookie::remove(self::COOKIE_NAME); + return false; + } + return $language; + } + + public static function isRemembered() { + return (bool)self::getRemembered(); + } + + public static function load($language,$module=null) { + if (!$language) $language = self::$language; + if (!$language) return false; + if (!$module) $module = $language; + + if (self::import($language, $module) || $language == DEFAULT_LANGUAGE) { + self::$language = $language; + self::loadJsStrings($language, $module); + return true; + } + + return false; + } + + public static function getLanguageFileAbsPath($language,$prefix,$suffix='') { + if (!empty($suffix)) $suffix = '.'.$suffix; + + $file = ROOT_DIR . DIRECTORY_SEPARATOR . + LANGUAGES_DIR . DIRECTORY_SEPARATOR . + $language . DIRECTORY_SEPARATOR . + $prefix . $suffix . '.php'; + + return $file; + } + + public static function getStringsFromFile($file) { + if (!file_exists($file)) return false; + + $strings = include($file); + if (!is_array($strings)) return false; + + return $strings; + } + + public static function removeStrings() { + self::$_strings = array(); + } + + public static function addStrings(array $strings) { + self::$_strings = array_merge(self::$_strings, $strings); + } + + public static function import($language, $module) { + $lang_file = self::getLanguageFileAbsPath($language,$module); + return self::importTranslates($lang_file); + } + + protected static function importTranslates($lang_file) { + $strings = self::getStringsFromFile($lang_file); + if (!$strings) return false; + self::addStrings($strings); + self::$_loaded[] = $lang_file; + + return true; + } + + public static function loadJsStrings($language,$module) { + $lang_file = self::getLanguageFileAbsPath($language,$module,'js'); + + $strings = self::getStringsFromFile($lang_file); + if (!$strings) return false; + View::addJsStrings($strings); + + return true; + } + + public static function getDBRows($language) { + $rows = Cache::getArray(self::CACHE_KEY_PREFIX.'.'.$language); + if ($rows === false) { + $rows = Translate::getCollection() + ->where('language', '=', $language) + ->get(); + + Cache::setArray(self::CACHE_KEY_PREFIX.'.'.$language, $rows); + } + return $rows; + } + + public static function getStringsFromDb($language) { + $rows = self::getDBRows($language); + $strings = array(); + foreach($rows as $row) { + $strings[$row->name] = $row->value; + } + return $strings; + } + + public static function loadDBStrings($language=null) { + if (!$language) $language = self::$language; + if (!$language) return false; + + $strings = self::getStringsFromDb($language); + self::addStrings($strings); + } + + public static function isLoaded($language,$module=null) { + if (!$language) $language = self::$language; + if (!$language) return false; + if (!$module) $module = $language; + + $lang_file = ROOT_DIR . DIRECTORY_SEPARATOR . + LANGUAGES_DIR . DIRECTORY_SEPARATOR . + $language . DIRECTORY_SEPARATOR . + $module . '.php'; + + return in_array($lang_file, self::$_loaded); + } + + public static function t($str, $arg = null) { + if (array_key_exists($str, self::$_strings)) $str = self::$_strings[$str]; + if ($arg === null) { + if (is_array($str)) $str = end($str); + return $str; + } + if (!is_array($str) || !is_numeric($arg)) { + if (is_array($str)) $str = end($str); + return sprintf($str, $arg); + } else { + $index = self::getPluralIndex($arg, self::getLanguage()); + if (!array_key_exists($index, $str)) return sprintf(end($str), $arg); + return sprintf($str[$index], $arg); + } + } + + public static function tm($str, $module, $arg = null) { + if (array_key_exists($str, self::$_strings)) return self::t($str, $arg); + else if (!self::isLoaded(null,$module)) { + self::load(null, $module); + return self::t($str, $arg); + } else { + return self::t($str, $arg); + } + } + + public static function getLanguage() { + return self::$language; + } + + public static function getStrings() { + return self::$_strings; + } + + protected static function getPluralIndex($int, $language) { + if ($language == 'ru') { + return self::getPluralIndexLanguageRu($int); + } else { + return self::getPluralIndexLanguageDefault($int); + } + } + + protected static function getPluralIndexLanguageRu($int) { + $a = $int % 10; + $b = $int % 100; + if ($a == 0 || $a >= 5 || ($b >= 10 && $b <= 20)) return 2; + else if ($a >= 2 && $a <= 4) return 1; + else if ($a == 1) return 0; + else return -1; + } + + protected static function getPluralIndexLanguageDefault($int) { + if ($int>1) return 1; + else if ($int == 1) return 0; + else return -1; + } + + public static function getLanguagesArray() { + $active_languages = Config::get('languages'); + $languages = array(); + $d = opendir(ROOT_DIR . DIRECTORY_SEPARATOR . LANGUAGES_DIR); + while (($f=readdir($d))!==false) { + if ($f=='.' || $f=='..' || !is_dir(ROOT_DIR . DIRECTORY_SEPARATOR . LANGUAGES_DIR . DIRECTORY_SEPARATOR . $f)) continue; + if (!in_array($f, $active_languages)) continue; + $lang_file = ROOT_DIR . DIRECTORY_SEPARATOR . + LANGUAGES_DIR . DIRECTORY_SEPARATOR . + $f . DIRECTORY_SEPARATOR . + $f . '.php'; + if (!file_exists($lang_file) || !is_readable(($lang_file))) continue; + $strings = include($lang_file); + if (!is_array($strings)) continue; + $languages[$f]=array_key_exists($f,$strings) ? $strings[$f] : $f; + } + return $languages; + } +} \ No newline at end of file diff --git a/zira/log.php b/zira/log.php new file mode 100644 index 0000000..e1ce828 --- /dev/null +++ b/zira/log.php @@ -0,0 +1,78 @@ +getCode().': '.$e->getMessage().' in '.$e->getFile().':'.$e->getLine()); + } + } + + public static function write($str) { + if (!LOG_ERRORS || !self::$_file) return false; + + $log_file = REAL_PATH . DIRECTORY_SEPARATOR . + LOG_DIR . DIRECTORY_SEPARATOR . + self::$_file; + + $f=@fopen($log_file,'ab'); + if (!$f) return false; + fwrite($f, '['.date('Y-m-d H:i:s').'] URI='.Request::uri()."\r\n".$str."\r\n\r\n"); + fclose($f); + + return true; + } + + public static function getErrorType($type) + { + switch($type) + { + case E_ERROR: + return 'E_ERROR'; + case E_WARNING: + return 'E_WARNING'; + case E_PARSE: + return 'E_PARSE'; + case E_NOTICE: + return 'E_NOTICE'; + case E_CORE_ERROR: + return 'E_CORE_ERROR'; + case E_CORE_WARNING: + return 'E_CORE_WARNING'; + case E_COMPILE_ERROR: + return 'E_COMPILE_ERROR'; + case E_COMPILE_WARNING: + return 'E_COMPILE_WARNING'; + case E_USER_ERROR: + return 'E_USER_ERROR'; + case E_USER_WARNING: + return 'E_USER_WARNING'; + case E_USER_NOTICE: + return 'E_USER_NOTICE'; + case E_STRICT: + return 'E_STRICT'; + case E_RECOVERABLE_ERROR: + return 'E_RECOVERABLE_ERROR'; + case E_DEPRECATED: + return 'E_DEPRECATED'; + case E_USER_DEPRECATED: + return 'E_USER_DEPRECATED'; + } + return ''; + } +} \ No newline at end of file diff --git a/zira/mail.php b/zira/mail.php new file mode 100644 index 0000000..9189a65 --- /dev/null +++ b/zira/mail.php @@ -0,0 +1,65 @@ +isSMTP(); + self::$_mailer->Host = Config::get('smtp_host'); + self::$_mailer->SMTPAuth = true; + self::$_mailer->Username = Config::get('smtp_username'); + self::$_mailer->Password = Config::get('smtp_password'); + self::$_mailer->SMTPSecure = Config::get('smtp_secure'); + self::$_mailer->Port = Config::get('smtp_port'); + + self::sendMail($email, $subject, $body, $filename, $replyTo); + } + + protected static function sendMail($email, $subject, $body, $filename = null, $replyTo = null) { + self::$_mailer->CharSet = CHARSET; + + self::$_mailer->From = Config::get('email_from'); + self::$_mailer->FromName = Config::get('email_from_name'); + + if (!empty($replyTo)) { + self::$_mailer->addReplyTo($replyTo); + } + + self::$_mailer->addAddress($email); + + if (!empty($filename) && file_exists($filename)) { + self::$_mailer->addAttachment($filename); + } + + self::$_mailer->isHTML(self::$_is_html); + + self::$_mailer->Subject = $subject; + self::$_mailer->Body = $body; + + if(!self::$_mailer->send()) { + throw new \Exception(self::$_mailer->ErrorInfo); + } + } +} \ No newline at end of file diff --git a/zira/menu.php b/zira/menu.php new file mode 100644 index 0000000..de73879 --- /dev/null +++ b/zira/menu.php @@ -0,0 +1,275 @@ +open_query() + ->where('menu_id', '=', self::MENU_PRIMARY) + ->and_where('language', 'is', null) + ->order_by('sort_order', 'asc') + ->close_query() + ->union() + ->open_query() + ->where('menu_id', '=', self::MENU_PRIMARY) + ->and_where('language', '=', Locale::getLanguage()) + ->order_by('sort_order', 'asc') + ->close_query() + ->union() + ->open_query() + ->where('menu_id', '=', self::MENU_FOOTER) + ->and_where('language', 'is', null) + ->order_by('sort_order', 'asc') + ->close_query() + ->union() + ->open_query() + ->where('menu_id', '=', self::MENU_FOOTER) + ->and_where('language', '=', Locale::getLanguage()) + ->order_by('sort_order', 'asc') + ->close_query() + ->get(); + + usort($items, array(Models\Menu::getClass(), 'sortAsc')); + + Cache::setArray($cache_key, $items); + } + + foreach($items as $item) { + if ($item->menu_id == self::MENU_PRIMARY) { + if ($item->active == Models\Menu::STATUS_ACTIVE) { + if ($item->parent_id > 0) { + if (!array_key_exists($item->parent_id, self::$_primary_dropdowns)) { + self::$_primary_dropdowns[$item->parent_id] = array(); + } + self::$_primary_dropdowns[$item->parent_id][] = $item; + } else { + self::$_primary_items [] = $item; + } + } + + if (self::isURLActive($item->url) && ( + !self::$_primary_active_url || + mb_strlen($item->url, CHARSET)>mb_strlen(self::$_primary_active_url, CHARSET) + )) { + if ($item->active == Models\Menu::STATUS_ACTIVE) { + self::$_primary_active_url = $item->url; + } + self::$_secondary_parent_id = $item->id; + } + } else if ($item->menu_id == self::MENU_FOOTER && $item->active == Models\Menu::STATUS_ACTIVE) { + if ($item->parent_id > 0) { + if (!array_key_exists($item->parent_id, self::$_footer_dropdowns)) { + self::$_footer_dropdowns[$item->parent_id] = array(); + } + self::$_footer_dropdowns[$item->parent_id][] = $item; + } else { + self::$_footer_items [] = $item; + } + + if (self::isURLActive($item->url) && ( + !self::$_footer_active_url || + mb_strlen($item->url, CHARSET)>mb_strlen(self::$_footer_active_url, CHARSET) + )) { + self::$_footer_active_url = $item->url; + } + } + } + + self::$_initialized = true; + } + + public static function getPrimaryMenuItems() { + if (!self::$_initialized) self::init(); + return self::$_primary_items; + } + + public static function getPrimaryMenuItemDropdown($id) { + if (array_key_exists($id, self::$_primary_dropdowns)) { + return self::$_primary_dropdowns[$id]; + } else { + return array(); + } + } + + public static function getFooterMenuItems() { + if (!self::$_initialized) self::init(); + return self::$_footer_items; + } + + public static function getFooterMenuItemDropdown($id) { + if (array_key_exists($id, self::$_footer_dropdowns)) { + return self::$_footer_dropdowns[$id]; + } else { + return array(); + } + } + + public static function initSecondaryMenuItems($parent_id, $force = false) { + if (self::$_secondary_initialized && !$force) return; + self::$_secondary_initialized = true; + $items = Models\Menu::getCollection() + ->open_query() + ->where('menu_id', '=', self::MENU_SECONDARY) + ->and_where('parent_id','=',$parent_id) + ->and_where('language', 'is', null) + ->order_by('sort_order', 'asc') + ->close_query() + ->union() + ->open_query() + ->where('menu_id', '=', self::MENU_SECONDARY) + ->and_where('parent_id','=',$parent_id) + ->and_where('language', '=', Locale::getLanguage()) + ->order_by('sort_order', 'asc') + ->close_query() + ->get(); + + if (count($items)==0) return; + + usort($items, array(Models\Menu::getClass(), 'sortAsc')); + + $parents = array(); + foreach($items as $item) { + if ($item->active != Models\Menu::STATUS_ACTIVE) continue; + $parents []= $item->id; + self::$_secondary_items []= $item; + + if (self::isURLActive($item->url) && ( + !self::$_secondary_active_url || + mb_strlen($item->url, CHARSET)>mb_strlen(self::$_secondary_active_url, CHARSET) + )) { + self::$_secondary_active_url = $item->url; + } + } + + if (count($parents)==0) return; + + $items = Models\Menu::getCollection() + ->open_query() + ->where('menu_id', '=', self::MENU_SECONDARY) + ->and_where('parent_id','in',$parents) + ->and_where('language', 'is', null) + ->order_by('sort_order', 'asc') + ->close_query() + ->union() + ->open_query() + ->where('menu_id', '=', self::MENU_SECONDARY) + ->and_where('parent_id','in',$parents) + ->and_where('language', '=', Locale::getLanguage()) + ->order_by('sort_order', 'asc') + ->close_query() + ->get(); + + usort($items, array(Models\Menu::getClass(), 'sortAsc')); + + foreach($items as $item) { + if ($item->active != Models\Menu::STATUS_ACTIVE) continue; + if (!array_key_exists($item->parent_id, self::$_secondary_dropdowns)) { + self::$_secondary_dropdowns[$item->parent_id] = array(); + } + self::$_secondary_dropdowns[$item->parent_id][]=$item; + + if (self::isURLActive($item->url) && ( + !self::$_secondary_active_url || + mb_strlen($item->url, CHARSET)>mb_strlen(self::$_secondary_active_url, CHARSET) + )) { + self::$_secondary_active_url = $item->url; + } + } + } + + public static function getSecondaryMenuItems() { + return self::$_secondary_items; + } + + public static function getSecondaryMenuItemDropdown($id) { + if (array_key_exists($id, self::$_secondary_dropdowns)) { + return self::$_secondary_dropdowns[$id]; + } else { + return array(); + } + } + + public static function isSysURL($url) { + if (empty($url) || $url == '/') return true; + if ($url=='javascript:void(0)' || substr($url, 0, 1) == '#') return false; + if (strpos($url, 'http')===0 || substr($url, 0, 1) == '/') return false; + return true; + } + + public static function parseURL($url, $encode = true) { + if (!self::isSysURL($url)) { + return $url; + } else { + if ($encode) $url = Page::encodeURL($url); + return Helper::url($url); + } + } + + public static function isURLActive($url) { + if (!self::isSysURL($url)) return false; + if (Router::getModule()==DEFAULT_MODULE && + Router::getController()==DEFAULT_CONTROLLER && + Router::getAction()==DEFAULT_ACTION + ) { + if ($url == '/') return true; + else return false; + } + $record_url = Page::getRecordUrl(); + if ($record_url && $record_url == Page::encodeURL($url)) return true; + $categories = Category::chain(); + foreach($categories as $category) { + if ($category->name == $url) return true; + } + return false; + } + + public static function getPrimaryMenuActiveURL() { + if (!self::$_initialized) self::init(); + return self::$_primary_active_url; + } + + public static function getFooterMenuActiveURL() { + if (!self::$_initialized) self::init(); + return self::$_footer_active_url; + } + + public static function getSecondaryMenuActiveURL() { + return self::$_secondary_active_url; + } + + public static function getSecondaryParentId() { + if (!self::$_initialized) self::init(); + return self::$_secondary_parent_id; + } +} \ No newline at end of file diff --git a/zira/models/blacklist.php b/zira/models/blacklist.php new file mode 100644 index 0000000..80e1d8c --- /dev/null +++ b/zira/models/blacklist.php @@ -0,0 +1,36 @@ + 'user_id', + User::getClass() => 'blocked_user_id' + ); + } +} \ No newline at end of file diff --git a/zira/models/block.php b/zira/models/block.php new file mode 100644 index 0000000..9d3100e --- /dev/null +++ b/zira/models/block.php @@ -0,0 +1,37 @@ +form_id = $form_id; + $captcha->date_created = date('Y-m-d H:i:s'); + $captcha->save(); + } + + public static function isActive($form_id) { + $total = self::getCollection() + ->count() + ->where('form_id','=',$form_id) + ->and_where('date_created','>=',date('Y-m-d H:i:s',time()-CAPTCHA_SLEEP_TIME)) + ->get('co'); + + return ($total >= CAPTCHA_SLEEP_MAX_REQUESTS); + } + + public static function cleanUp() { + self::getCollection() + ->delete() + ->where('date_created','<',date('Y-m-d',time()-3600)) + ->execute() + ; + } +} \ No newline at end of file diff --git a/zira/models/category.php b/zira/models/category.php new file mode 100644 index 0000000..bf6e15c --- /dev/null +++ b/zira/models/category.php @@ -0,0 +1,67 @@ +order_by('name','asc')->get(); + + $categories = array(); + foreach($rows as $row) { + $prefix = ''; + if (!empty($_prefix) && strpos($row->name,'/')!==false) { + $prefix = str_repeat($_prefix, strlen(preg_replace('/[^\/]/','',$row->name))); + } + $categories[$row->id] = $prefix.Locale::t($row->title); + } + + return $categories; + } + + public static function getTopCategories($order_by = 'id', $sort = 'asc') { + return self::getCollection() + ->where('parent_id', '=', \Zira\Category::ROOT_CATEGORY_ID) + ->order_by($order_by, $sort) + ->get(); + } + + public static function getChildCategories($category) { + return self::getCollection() + ->where('name', 'like', $category->name . '/%') + ->get(); + } +} \ No newline at end of file diff --git a/zira/models/comment.php b/zira/models/comment.php new file mode 100644 index 0000000..1713e96 --- /dev/null +++ b/zira/models/comment.php @@ -0,0 +1,167 @@ + 'record_id', + User::getClass() => 'author_id' + ); + } + + public static function countComments($record_id, $published= true) { + $query = self::getCollection() + ->count() + ->where('record_id','=',$record_id); + if ($published) { + $query->and_where('published', '=', self::STATUS_PUBLISHED); + } + return $query->get('co'); + } + + public static function getComments($record_id, $limit = null, $offset = 0, $published= true) { + if ($limit===null) $limit = Config::get('comments_limit', 10); + + $query = self::getCollection() + ->select(self::getFields()) + ->left_join(User::getClass(), array('author_username'=>'username','author_firstname'=>'firstname','author_secondname'=>'secondname','author_image'=>'image')) + ->where('record_id','=',$record_id); + if ($published) { + $query->and_where('published', '=', self::STATUS_PUBLISHED); + } + $query->order_by('sort_path','asc'); + $query->limit($limit, $offset); + return $query->get(); + } + + public static function getPathOffset($record_id, $parent = null) { + $parent_id = 0; + if ($parent!==null) { + $parent_id = $parent->id; + $parts = explode(self::PATH_DELIMITER, $parent->sort_path); + if (count($parts)>=50) return $parent->sort_path; + } + + $offset= self::getCollection() + ->max('path_offset') + ->where('record_id','=',$record_id) + ->and_where('parent_id','=',$parent_id) + ->get('mx'); + + return intval($offset); + } + + public static function getSortPath($path_offset, $parent = null) { + if ($parent===null) { + $path = self::generatePath($path_offset, true); + } else { + $path = $parent->sort_path . self::PATH_DELIMITER . self::generatePath($path_offset, false); + } + + return $path; + } + + public static function generatePath($offset, $desc = false) { + if ($desc) $chars = range('z','a'); + else $chars = range('a','z'); + $count = count($chars); + $max = pow($count, 4); + if ($offset >= $max) $offset = $max - 1; + $offset1 = intval($offset / pow($count,3)); + $offset2 = intval(($offset % pow($count,3)) / pow($count,2)) % $count; + $offset3 = intval(($offset % pow($count,2)) / $count) % $count; + $offset4 = $offset % $count; + $path = ''; + if ($offset1<$count) $path .= $chars[$offset1]; + if ($offset2<$count) $path .= $chars[$offset2]; + if ($offset3<$count) $path .= $chars[$offset3]; + if ($offset4<$count) $path .= $chars[$offset4]; + return $path; + } + + public static function getDefaultNotifyMessage() { + $message = Locale::t('Hello %s !', Locale::t('moderator'))."\r\n\r\n"; + $message .= Locale::t('New comment was posted on: %s', '$page')."\r\n"; + $message .= Locale::t('Page URL address: %s','$url')."\r\n\r\n"; + $message .= Locale::t('Comment text').':'."\r\n"; + $message .= '$comment'."\r\n\r\n"; + $message .= Locale::t('You recieved this message, because your Email address is specified as a notification Email on %s','$site'); + return $message; + } + + public static function notify($record, $comment) { + $email = Config::get('comment_notify_email'); + if (empty($email)) return; + + if ($record->category_id != Zira\Category::ROOT_CATEGORY_ID) { + $category = new Zira\Models\Category($record->category_id); + if (!$category->loaded()) return; + $url = Zira\Page::generateRecordUrl($category->name, $record->name); + } else { + $url = Zira\Page::generateRecordUrl(null, $record->name); + } + + $message = Config::get('comment_notification_message'); + if (!$message || strlen(trim($message))==0) { + $message = self::getDefaultNotifyMessage(); + } else { + $message = Locale::t($message); + } + $message = str_replace('$page', $record->title, $message); + $message = str_replace('$url', Helper::url($url, true, true), $message); + $message = str_replace('$comment', $comment->content, $message); + $message = str_replace('$site', Helper::url('/',true, true), $message); + + Zira\Mail::send($email, Locale::t('New comment was posted'), Helper::html($message)); + } +} \ No newline at end of file diff --git a/zira/models/commentlike.php b/zira/models/commentlike.php new file mode 100644 index 0000000..5c8645e --- /dev/null +++ b/zira/models/commentlike.php @@ -0,0 +1,32 @@ + 'user_id' + ); + } + + public static function createConversation($sender_id, $recipient_id, $subject) { + //$max_id = self::getCollection()->max('conversation_id')->get('mx'); + $max_id = Message::getCollection()->max('conversation_id')->get('mx'); + $conversation_id = ++$max_id; + + $conversation = new self; + $conversation->conversation_id = $conversation_id; + $conversation->user_id = $sender_id; + $conversation->subject = $subject; + $conversation->creation_date = date('Y-m-d H:i:s'); + $conversation->modified_date = date('Y-m-d H:i:s'); + $conversation->highlight = 0; + $conversation->save(); + + $conversation = new self; + $conversation->conversation_id = $conversation_id; + $conversation->user_id = $recipient_id; + $conversation->subject = $subject; + $conversation->creation_date = date('Y-m-d H:i:s'); + $conversation->modified_date = date('Y-m-d H:i:s'); + $conversation->highlight = 1; + $conversation->save(); + + return $conversation_id; + } + + public static function createGroupConversation($sender_id, array $recipient_ids, $subject) { + //$max_id = self::getCollection()->max('conversation_id')->get('mx'); + $max_id = Message::getCollection()->max('conversation_id')->get('mx'); + $conversation_id = ++$max_id; + + $conversation = new self; + $conversation->conversation_id = $conversation_id; + $conversation->user_id = $sender_id; + $conversation->subject = $subject; + $conversation->creation_date = date('Y-m-d H:i:s'); + $conversation->modified_date = date('Y-m-d H:i:s'); + $conversation->highlight = 0; + $conversation->save(); + + foreach ($recipient_ids as $recipient_id) { + $conversation = new self; + $conversation->conversation_id = $conversation_id; + $conversation->user_id = $recipient_id; + $conversation->subject = $subject; + $conversation->creation_date = date('Y-m-d H:i:s'); + $conversation->modified_date = date('Y-m-d H:i:s'); + $conversation->highlight = 1; + $conversation->save(); + } + + return $conversation_id; + } +} \ No newline at end of file diff --git a/zira/models/draft.php b/zira/models/draft.php new file mode 100644 index 0000000..78caf36 --- /dev/null +++ b/zira/models/draft.php @@ -0,0 +1,46 @@ + 'record_id', + User::getClass() => 'author_id' + ); + } + + public static function cleanUp() { + self::getCollection() + ->delete() + ->where('published','=',self::STATUS_PUBLISHED) + ->and_where('modified_date','<',date('Y-m-d H:i:s',time()-2592000)) // 30 days + ->execute(); + } +} \ No newline at end of file diff --git a/zira/models/group.php b/zira/models/group.php new file mode 100644 index 0000000..be07780 --- /dev/null +++ b/zira/models/group.php @@ -0,0 +1,77 @@ +order_by(self::getPk(), 'ASC') + ->get(); + + Cache::setArray(self::CACHE_KEY, $rows); + } + return $rows; + } + + public static function getActiveList() { + $rows = Cache::getArray(self::CACHE_ACTIVE_KEY); + if ($rows === false) { + $rows = self::getCollection() + ->where('active', '=', self::STATUS_ACTIVE) + ->order_by(self::getPk(), 'ASC') + ->get(); + + Cache::setArray(self::CACHE_ACTIVE_KEY, $rows); + } + return $rows; + } + + public static function getArray($activeOnly=false) { + $groupsArr = array(); + if (!$activeOnly) { + $groups = self::getList(); + } else { + $groups = self::getActiveList(); + } + foreach($groups as $group) { + $groupsArr[$group->id] = Locale::t($group->name); + } + return $groupsArr; + } +} \ No newline at end of file diff --git a/zira/models/image.php b/zira/models/image.php new file mode 100644 index 0000000..5a09c9a --- /dev/null +++ b/zira/models/image.php @@ -0,0 +1,34 @@ + 'record_id' + ); + } +} \ No newline at end of file diff --git a/zira/models/like.php b/zira/models/like.php new file mode 100644 index 0000000..632b22c --- /dev/null +++ b/zira/models/like.php @@ -0,0 +1,32 @@ +sort_order == $b->sort_order) return 0; + else return ($a->sort_order < $b->sort_order) ? -1 : 1; + } + + public static function sortDesc($a, $b) { + if ($a->sort_order == $b->sort_order) return 0; + else return ($a->sort_order > $b->sort_order) ? -1 : 1; + } +} \ No newline at end of file diff --git a/zira/models/message.php b/zira/models/message.php new file mode 100644 index 0000000..d0df69a --- /dev/null +++ b/zira/models/message.php @@ -0,0 +1,64 @@ + 'conversation_id', + User::getClass() => 'user_id' + ); + } + + public static function getDefaultNotifyMessage() { + $message = Locale::t('Hello %s !', '$user')."\r\n\r\n"; + $message .= Locale::t('You have new message from %s.', '$sender')."\r\n"; + $message .= Locale::t('Log in %s to read it.','$url')."\r\n\r\n"; + $message .= Locale::t('You recieved this message, because you are subscribed to Email notifications on %s','$site'); + return $message; + } + + public static function notify($user, $sender) { + if (!$user->subscribed || !$user->email || !$user->verified || !$user->active) return; + + $message = Zira\Config::get('new_message_notification'); + if (!$message || strlen(trim($message))==0) { + $message = self::getDefaultNotifyMessage(); + } else { + $message = Locale::t($message); + } + $message = str_replace('$user', Zira\User::getProfileName($user), $message); + $message = str_replace('$sender', Zira\User::getProfileName($sender), $message); + $message = str_replace('$url', Zira\Helper::url('user/login',true, true), $message); + $message = str_replace('$site', Zira\Helper::url('/',true, true), $message); + + Zira\Mail::send($user->email, Locale::t('You have new message'), Zira\Helper::html($message)); + } +} \ No newline at end of file diff --git a/zira/models/option.php b/zira/models/option.php new file mode 100644 index 0000000..bcb8a3a --- /dev/null +++ b/zira/models/option.php @@ -0,0 +1,70 @@ +select('id') + ->where('name','=',$name) + ->get('id'); + if (empty($id)) { + $obj = new self(); + } else { + $obj = new self($id); + } + + $obj->module = 'zira'; + $obj->name = $name; + $obj->value = $value; + $obj->save(); + } + + public static function raiseVersion() { + self::write('config_version', Config::get('config_version')+1); + Cache::clear(true); + } +} \ No newline at end of file diff --git a/zira/models/permission.php b/zira/models/permission.php new file mode 100644 index 0000000..1a5cada --- /dev/null +++ b/zira/models/permission.php @@ -0,0 +1,46 @@ + 'group_id' + ); + } + + public static function getGroupPermissions($group_id) { + return self::getCollection() + ->select('name', 'allow') + ->join(Group::getClass(), array('group_name'=>'name')) + ->where('group_id','=',$group_id) + ->and_where('active','=',Group::STATUS_ACTIVE, Group::getAlias()) + ->get() + ; + } +} \ No newline at end of file diff --git a/zira/models/record.php b/zira/models/record.php new file mode 100644 index 0000000..96b931a --- /dev/null +++ b/zira/models/record.php @@ -0,0 +1,88 @@ + 'category_id', + User::getClass() => 'author_id' + ); + } + + public static function sortByRatingAsc($a, $b) { + if ($a->rating == $b->rating) return 0; + else return ($a->rating < $b->rating) ? -1 : 1; + } + + public static function sortByRatingDesc($a, $b) { + if ($a->rating == $b->rating) return 0; + else return ($a->rating > $b->rating) ? -1 : 1; + } + + public static function sortByCommentsAsc($a, $b) { + if ($a->comments == $b->comments) return 0; + else return ($a->comments < $b->comments) ? -1 : 1; + } + + public static function sortByCommentsDesc($a, $b) { + if ($a->comments == $b->comments) return 0; + else return ($a->comments > $b->comments) ? -1 : 1; + } +} \ No newline at end of file diff --git a/zira/models/search.php b/zira/models/search.php new file mode 100644 index 0000000..39c9728 --- /dev/null +++ b/zira/models/search.php @@ -0,0 +1,180 @@ + 'record_id' + ); + } + + public static function clearRecordIndex($record) { + self::getCollection() + ->delete() + ->where('record_id', '=', $record->id) + ->execute(); + } + + public static function indexRecord($record) { + self::clearRecordIndex($record); + + if ($record->published != Record::STATUS_PUBLISHED) return; + + $keywords_str = ''; + if ($record->meta_keywords) { + $keywords = explode(',', $record->meta_keywords); + foreach ($keywords as $keyword) { + $keywords_str .= ' ' . $keyword; + } + } + + $text = $record->title . ' ' . $record->meta_title . ' ' . $keywords_str; + $text = trim($text); + if (empty($text)) return; + $text = mb_strtolower($text, CHARSET); + $text = preg_replace('/[\x20]+/',' ', $text); + $keywords = explode(' ', $text); + + $added = array(); + foreach($keywords as $keyword) { + if (in_array($keyword, $added)) continue; + if (mb_strlen($keyword, CHARSET)keyword = $keyword; + $index->record_id = $record->id; + $index->language = $record->language; + $index->save(); + $added []= $keyword; + } + } + + public static function getRecords($text, $limit = 10, $offset = 0) { + $text = trim($text); + if (empty($text)) return array(); + $text = mb_strtolower($text, CHARSET); + $keywords = explode(' ', $text); + + $query = self::getCollection(); + + $added = array(); + foreach($keywords as $index=>$keyword) { + if (mb_strlen($keyword, CHARSET)0) $query->union(); + $query->open_query(); + $query->select('record_id'); + $query->where('language','=',Locale::getLanguage()); + $query->and_where('keyword','like',$keyword.'%'); + $query->limit($limit+$limit*$offset); + $query->close_query(); + $added []= $keyword; + if (count($added)>=5) break; + } + + if (empty($added)) return array(); + + $query->merge(); + $query->limit($limit, $offset); + $rows = $query->get(); + + $results = array(); + foreach($rows as $row) { + $results[]=$row->record_id; + } + + if (empty($results)) return array(); + + return Record::getCollection() + ->select('id', 'name','author_id','title','description','thumb','creation_date','rating','comments') + ->left_join(Category::getClass(), array('category_name'=>'name', 'category_title'=>'title')) + ->where('id','in',$results) + ->get(); + } + + public static function getRecordsSorted($text, $limit = 5) { + $text = trim($text); + if (empty($text)) return array(); + $text = mb_strtolower($text, CHARSET); + $keywords = explode(' ', $text); + + $query = self::getCollection(); + + $added = array(); + foreach($keywords as $index=>$keyword) { + if (mb_strlen($keyword, CHARSET)0) $query->union(); + $query->open_query(); + $query->where('language','=',Locale::getLanguage()); + $query->and_where('keyword','like',$keyword.'%'); + $query->limit($limit); + $query->close_query(); + $added []= $keyword; + if (count($added)>=5) break; + } + + if (empty($added)) return array(); + $rows = $query->get(); + + $results = array(); + foreach($rows as $row) { + if (!array_key_exists($row->record_id, $results)) { + $results[$row->record_id] = 0; + } + $results[$row->record_id]++; + } + + if (empty($results)) return array(); + + arsort($results); + + $rows = Record::getCollection() + ->select('id', 'name','author_id','title','description','thumb','creation_date','rating','comments') + ->left_join(Category::getClass(), array('category_name'=>'name', 'category_title'=>'title')) + ->where('id','in',array_keys($results)) + ->get(); + + if (empty($rows)) return array(); + + $_results = array(); + foreach($rows as $row) { + $_results[$row->id] = $row; + } + + $return = array(); + foreach($results as $id=>$co) { + if (!array_key_exists($id, $_results)) continue; + $return []= $_results[$id]; + } + + if (count($return)>$limit) return array_slice($return, 0, $limit); + else return $return; + } +} \ No newline at end of file diff --git a/zira/models/slide.php b/zira/models/slide.php new file mode 100644 index 0000000..192be15 --- /dev/null +++ b/zira/models/slide.php @@ -0,0 +1,34 @@ + 'record_id' + ); + } +} \ No newline at end of file diff --git a/zira/models/translate.php b/zira/models/translate.php new file mode 100644 index 0000000..5442d2b --- /dev/null +++ b/zira/models/translate.php @@ -0,0 +1,34 @@ + 'group_id' + ); + } + + protected static function getJoinedCollection() { + return self::getCollection() + ->join(Group::getClass(), array('group_name'=>'name')) + ; + } + + protected static function getActiveCollection() + { + $collection = self::getJoinedCollection(); + return $collection + ->where('verified', '=', self::STATUS_VERIFIED) + ->and_where('active', '=', self::STATUS_ACTIVE) + ->and_where('active', '=', Group::STATUS_ACTIVE, Group::getAlias()); + } + + public static function findUser($username_or_email_or_id) { + $collection = self::getJoinedCollection(); + $collection->select(self::getFields()); + + if (is_int($username_or_email_or_id)) { + $collection->where(self::getPk(),'=',$username_or_email_or_id); + } else if (strpos($username_or_email_or_id,'@')!==false) { + $collection->where('email','=',$username_or_email_or_id); + } else { + $collection->where('username','=',$username_or_email_or_id); + } + + return $collection->get(0); + } + + public static function findActiveUser($username_or_email_or_id) { + $collection = self::getActiveCollection(); + $collection->select(self::getFields()); + + if (is_int($username_or_email_or_id)) { + $collection->and_where(self::getPk(),'=',$username_or_email_or_id); + } else if (strpos($username_or_email_or_id,'@')!==false) { + $collection->and_where('email','=',$username_or_email_or_id); + } else { + $collection->and_where('username','=',$username_or_email_or_id); + } + + return $collection->get(0); + } + + public static function findAuthUser($username_or_email) { + $collection = self::getJoinedCollection(); + $collection->select(self::getFields()) + ->where('active','=',self::STATUS_ACTIVE) + ->and_where('active','=',Group::STATUS_ACTIVE, Group::getAlias()) + ; + + if (strpos($username_or_email,'@')!==false) { + $collection->and_where('email','=',$username_or_email); + } else { + $collection->and_where('username','=',$username_or_email); + } + + return $collection->get(0); + } + + public static function getActiveUsersCount() { + $collection = self::getActiveCollection(); + return $collection->count()->get('co'); + } + + public static function getActiveUsers($limit=10, $offset=0, $order='DESC') { + $collection = self::getActiveCollection(); + return $collection->select(self::getFields()) + ->order_by(self::getPk(), $order) + ->limit($limit,$offset) + ->get() + ; + } + + public static function getAllUsersCount() { + $collection = self::getJoinedCollection(); + return $collection->count()->get('co'); + } + + public static function getAllUsers($limit=10, $offset=0, $order='DESC') { + $collection = self::getJoinedCollection(); + return $collection->select(self::getFields()) + ->order_by(self::getPk(), $order) + ->limit($limit,$offset) + ->get() + ; + } + + public static function getGroupAllUsersCount($group_id) { + $collection = self::getJoinedCollection(); + return $collection->count() + ->where('group_id','=',$group_id) + ->get('co'); + } + + public static function getGroupAllUsers($group_id, $limit=10, $offset=0, $order='DESC') { + $collection = self::getJoinedCollection(); + return $collection->select(self::getFields()) + ->where('group_id','=',$group_id) + ->order_by(self::getPk(), $order) + ->limit($limit,$offset) + ->get() + ; + } + + public static function getSearchUsersCount($username_or_email_or_id, $group_id=null) { + $collection = self::getJoinedCollection(); + $collection->count(); + + $collection->open_where(); + if (is_numeric($username_or_email_or_id)) { + $collection->where(self::getPk(),'=',intval($username_or_email_or_id)); + } else if (strpos($username_or_email_or_id,'@')!==false) { + $collection->where('email','=',$username_or_email_or_id); + } else { + $collection->where('username','like','%'.$username_or_email_or_id.'%'); + $collection->or_where('firstname','like','%'.$username_or_email_or_id.'%'); + $collection->or_where('secondname','like','%'.$username_or_email_or_id.'%'); + } + $collection->close_where(); + + if (!empty($group_id)) { + $collection->and_where('group_id','=',$group_id); + } + + return $collection->get('co'); + } + + public static function searchUsers($username_or_email_or_id, $limit=10, $offset=0, $order='DESC', $group_id=null) { + $collection = self::getJoinedCollection(); + $collection->select(self::getFields()); + + $collection->open_where(); + if (is_numeric($username_or_email_or_id)) { + $collection->where(self::getPk(),'=',intval($username_or_email_or_id)); + } else if (strpos($username_or_email_or_id,'@')!==false) { + $collection->where('email','=',$username_or_email_or_id); + } else { + $collection->where('username','like','%'.$username_or_email_or_id.'%'); + $collection->or_where('firstname','like','%'.$username_or_email_or_id.'%'); + $collection->or_where('secondname','like','%'.$username_or_email_or_id.'%'); + } + $collection->close_where(); + + if (!empty($group_id)) { + $collection->and_where('group_id','=',$group_id); + } + + return $collection->order_by(self::getPk(), $order) + ->limit($limit,$offset) + ->get(); + } +} \ No newline at end of file diff --git a/zira/models/widget.php b/zira/models/widget.php new file mode 100644 index 0000000..2a09118 --- /dev/null +++ b/zira/models/widget.php @@ -0,0 +1,61 @@ + Locale::t('HEAD tag'), + View::VAR_BODY_TOP => Locale::t('BODY tag top'), + View::VAR_HEADER => Locale::t('Header'), + View::VAR_SIDEBAR_LEFT => Locale::t('Left sidebar'), + View::VAR_SIDEBAR_RIGHT => Locale::t('Right sidebar'), + View::VAR_CONTENT_TOP => Locale::t('Before content'), + View::VAR_CONTENT => Locale::t('Content'), + View::VAR_CONTENT_BOTTOM => Locale::t('After content'), + View::VAR_FOOTER => Locale::t('Footer'), + View::VAR_BODY_BOTTOM => Locale::t('BODY tag bottom') + ); + } + + public static function getFiltersArray() { + return array( + self::STATUS_FILTER_CATEGORY => Locale::t('Display on category page only'), + self::STATUS_FILTER_RECORD => Locale::t('Display on record page only') + ); + } +} \ No newline at end of file diff --git a/zira/orm.php b/zira/orm.php new file mode 100644 index 0000000..22c57d4 --- /dev/null +++ b/zira/orm.php @@ -0,0 +1,12 @@ +$title)); + } + + public static function setTitle($title) { + //$title = Helper::html($title); //converted in tag generation + View::setLayoutData(array(View::VAR_TITLE=>$title)); + } + + public static function setKeywords($keywords) { + //$keywords = Helper::html($keywords); //converted in addMeta + View::addMeta(array('name'=>'keywords','content'=>$keywords)); + View::setKeywordsAdded(true); + } + + public static function setDescription($description) { + //$description = Helper::html($description); //converted in addMeta + $description = str_replace("\r\n", ' ', $description); + View::addMeta(array('name'=>'description','content'=>$description)); + View::setDescriptionAdded(true); + } + + public static function addOpenGraphTags($title, $description, $url = '', $image = null) { + $description = str_replace("\r\n", ' ', $description); + if ($image === null) $image = Config::get('site_logo'); + $tags = array( + 'og:site_name' => Config::get('site_title') ? Locale::t(Config::get('site_title')) : Locale::t(Config::get('site_name')), + 'og:type' => 'website', + 'og:title' => $title, + 'og:description' => $description, + 'og:url' => Helper::url($url, true, true), + 'og:image' => Helper::baseUrl($image, true, true) + ); + foreach($tags as $property=>$content) { + View::addMeta(array('property'=>$property,'content'=>$content)); + } + } + + public static function addBreadcrumb($link, $title) { + self::$_breadcrumbs [] = array('link'=>$link, 'title'=>$title); + } + + public static function breadcrumbs() { + if (!View::renderBreadcrumbsEnabled()) return ''; + $added = array(); + $html = Helper::tag_open('ol',array('class'=>self::BREADCRUMBS_CLASS)); + foreach(self::$_breadcrumbs as $breadcrumb) { + if (!empty($breadcrumb['link'])) { + if (in_array($breadcrumb['link'], $added)) continue; + $added []= $breadcrumb['link']; + } + if (empty($breadcrumb['link']) || $breadcrumb['link'] == Router::getRequest()) { + $html .= Helper::tag('li', $breadcrumb['title'], array('class'=>'active')); + } else { + $html .= Helper::tag_open('li'); + $html .= Helper::tag('a', $breadcrumb['title'], array('href'=>Helper::url($breadcrumb['link']))); + $html .= Helper::tag_close('li'); + } + } + $html .= Helper::tag_close('ol'); + return $html; + } + + public static function allowPreview() { + return Dash::isFrame() && Permission::check(Permission::TO_ACCESS_DASHBOARD); + } + + public static function setSlider(array $images) { + View::addSlider('slider', array( + 'auto' => true, + 'speed' => 500, + 'pause' => 8000, + 'captions' => true, + 'slideMargin' => 0, + 'adaptiveHeight' => false + )); + View::addPlaceholderView(View::VAR_CONTENT_TOP, array('images'=>$images), 'zira/slider'); + } + + public static function setGallery(array $images) { + View::addLightbox(); + View::addPlaceholderView(View::VAR_CONTENT, array('images'=>$images), 'zira/gallery'); + } + + public static function setComments($record, $preview = false) { + $commenting_allowed = Config::get('comments_allowed',true); + if (!Config::get('comment_anonymous',true) && + !User::isAuthorized() + ) { + $commenting_allowed = false; + } + if ($commenting_allowed) { + $form = new Forms\Comment(); + $form->setValue('record_id', $record->id); + } else { + $form = null; + } + $limit = Config::get('comments_limit', 10); + $comments = Models\Comment::getComments($record->id, $limit, 0, !$preview); + View::addPlaceholderView(View::VAR_CONTENT, array( + 'record_id'=>$record->id, + 'form'=>$form, + 'comments'=>$comments, + 'limit'=>$limit, + 'page'=>0, + 'total'=>Models\Comment::countComments($record->id, !$preview) + ), 'zira/comments'); + View::preloadThemeLoader(); + View::addParser(); + } + + public static function encodeURL($url) { + $url = urlencode($url); + $url = str_replace('%2F','/',$url); + return $url; + } + + public static function generateCategoryUrl($category_name) { + return self::encodeURL($category_name); + } + + public static function generateRecordUrl($category_name, $record_name) { + if (empty($category_name)) return self::encodeURL($record_name); + else return self::encodeURL($category_name) . '/' . self::encodeURL($record_name); + } + + public static function getRecordId() { + return self::$_record_id; + } + + public static function getRecordUrl() { + return self::$_record_url; + } + + public static function setRecordId($record_id) { + self::$_record_id = (int)$record_id; + } + + public static function setRecordUrl($url) { + self::$_record_url = $url; + } + + public static function createRecordThumb($src_path, $category_id, $record_id, $gallery=false, $slider=false) { + if ($category_id==Category::ROOT_CATEGORY_ID) { + $savedir = THUMBS_DIR; + } else { + $savedir = THUMBS_DIR . DIRECTORY_SEPARATOR . 'cat'. $category_id; + } + if ($gallery) $savedir .= DIRECTORY_SEPARATOR . 'gal'.$record_id; + else if ($slider) $savedir .= DIRECTORY_SEPARATOR . 'sli'.$record_id; + $save_path = File::getAbsolutePath($savedir); + $ext = 'thumb'; + $p = strrpos($src_path, '.'); + if ($p!==false) $ext = substr($src_path, $p+1); + do { + if (!$gallery && !$slider) { + $name = 'rec' . $record_id . '.' . uniqid() . '.' . $ext; + } else { + $name = 'img' . uniqid() . '.' . $ext; + } + } while(file_exists($save_path . DIRECTORY_SEPARATOR . $name)); + if (file_exists($src_path) && Image::createThumb($src_path, $save_path . DIRECTORY_SEPARATOR . $name, Config::get('thumbs_width'), Config::get('thumbs_height'))) { + return UPLOADS_DIR . '/' . str_replace(DIRECTORY_SEPARATOR, '/', $savedir) . '/' . $name; + } else { + return false; + } + } + + public static function getRecords($category, $front_page = false, $limit = null, $last_id = null, $includeChilds = true, array $childs = null) { + if ($limit === null) $limit = Config::get('records_limit', 10); + + $category_ids = array($category->id); + if ($includeChilds) { + if ($childs === null) $childs = Category::getChilds($category); + foreach ($childs as $child) { + $category_ids [] = $child->id; + } + } + + if ($includeChilds && count($category_ids)>1) { + $records = self::getCategoriesRecordsList($category_ids, $front_page, $limit, $last_id); + } else { + $records = self::getCategoryRecordsList($category_ids[0], $front_page, $limit, $last_id); + } + + return $records; + } + + public static function getCategoryRecordsList($category_id, $front_page = false, $limit = null, $last_id = null) { + if ($limit === null) $limit = Config::get('records_limit', 10); + + $query = Record::getCollection() + ->select('id', 'name','author_id','title','description','thumb','creation_date','rating','comments') + ->join(Models\Category::getClass(), array('category_name'=>'name', 'category_title'=>'title')) + ->join(Models\User::getClass(), array('author_username'=>'username', 'author_firstname'=>'firstname', 'author_secondname'=>'secondname')) + ; + + $query->where('category_id', '=', $category_id); + $query->and_where('language', '=', Locale::getLanguage()); + $query->and_where('published', '=', Record::STATUS_PUBLISHED); + if ($front_page) { + $query->and_where('front_page','=',Record::STATUS_FRONT_PAGE); + } + if ($last_id!==null) { + $query->and_where('id', '<', $last_id); + } + $query->order_by('id', 'desc'); + $query->limit($limit); + + return $query->get(); + } + + public static function getCategoriesRecordsList(array $category_ids, $front_page = false, $limit = null, $last_id = null) { + if ($limit === null) $limit = Config::get('records_limit', 10); + + $query = Record::getCollection(); + foreach($category_ids as $index=>$category_id) { + if ($index>0) { + $query->union(); + } + $query->open_query(); + $query->select('id'); + $query->where('category_id', '=', $category_id); + $query->and_where('language', '=', Locale::getLanguage()); + $query->and_where('published', '=', Record::STATUS_PUBLISHED); + if ($front_page) { + $query->and_where('front_page','=',Record::STATUS_FRONT_PAGE); + } + if ($last_id!==null) { + $query->and_where('id', '<', $last_id); + } + $query->order_by('id', 'desc'); + $query->limit($limit); + $query->close_query(); + } + $query->merge(); + $query->order_by('id', 'desc'); + $query->limit($limit); + + $rows = $query->get(); + + if (!$rows) return array(); + + $query = Record::getCollection() + ->select('id', 'name','author_id','title','description','thumb','creation_date','rating','comments') + ->join(Models\Category::getClass(), array('category_name'=>'name', 'category_title'=>'title')) + ->join(Models\User::getClass(), array('author_username'=>'username', 'author_firstname'=>'firstname', 'author_secondname'=>'secondname')) + ; + + $record_ids = array(); + foreach($rows as $index=>$row) { + $record_ids []= $row->id; + } + $query->where('id','in',$record_ids); + + $query->order_by('id', 'desc'); + + return $query->get(); + } + + public static function render(array $data = null) { + if ($data === null) $data = array(); + if (View::isAjax()) { + if (!isset($data[self::VIEW_PLACEHOLDER_CONTENT]) || !($data[self::VIEW_PLACEHOLDER_CONTENT] instanceof Form\Factory)) { + echo json_encode($data); + } else { + echo json_encode(array( + 'message'=>$data[self::VIEW_PLACEHOLDER_CONTENT]->getMessage(), + 'error'=>$data[self::VIEW_PLACEHOLDER_CONTENT]->getError() + )); + } + return; + } + View::render($data, self::$_view, self::$_layout); + } +} \ No newline at end of file diff --git a/zira/pagination.php b/zira/pagination.php new file mode 100644 index 0000000..f8ee35d --- /dev/null +++ b/zira/pagination.php @@ -0,0 +1,228 @@ +_param = $param; + } + + public function setTotal($total) { + $this->_total = intval($total); + } + + public function setLimit($limit) { + $this->_limit = intval($limit); + } + + public function setPage($page) { + $this->_page = intval($page); + if ($this->_page<1) $this->_page = 1; + } + + public function setOffset($offset) { + $this->_offset = intval($offset); + if ($this->_offset<0) $this->_offset = 0; + } + + public function setPages($pages) { + $this->_pages = intval($pages); + } + + public function setUrl($url) { + $this->_url = $url; + } + + public function setUrlParams(array $url_params) { + $this->_url_params = $url_params; + } + + public function setClass($class) { + $this->_class = $class; + } + + public function setId($id) { + $this->_id = $id; + } + + public function getParam() { + return $this->_param; + } + + public function getTotal() { + return $this->_total; + } + + public function getLimit() { + return $this->_limit; + } + + public function getPage() { + if ($this->_page === null) { + $this->setPage(Request::get($this->getParam())); + } + return $this->_page; + } + + public function getOffset() { + if ($this->_offset === null) { + $limit = $this->getLimit(); + if ($limit === null) { + throw new \Exception('Limit is not set'); + } + $page = $this->getPage(); + $this->_offset = ($page-1)*$limit; + } + return $this->_offset; + } + + public function getPages() { + return $this->_pages; + } + + public function getUrl() { + return $this->_url; + } + + public function getUrlParams() { + return $this->_url_params; + } + + public function getClass() { + if ($this->_class === null) return ''; + return $this->_class; + } + + public function getId() { + if ($this->_id === null) return ''; + return $this->_id; + } + + protected function url($page) { + $url = $this->getUrl(); + $params = $this->getUrlParams(); + $url_params = ''; + if (!empty($params)) { + foreach($params as $k=>$v) { + if (empty($url_params)) $url_params .= '?'; + else $url_params .= '&'; + $url_params .= $k.'='.$v; + } + } + if ($url === null) { + if (empty($url_params)) { + $param = $this->getParam(); + foreach(Request::get() as $k=>$v) { + if ($k==$param) continue; + if (empty($url_params)) $url_params .= '?'; + else $url_params .= '&'; + $url_params .= $k.'='.$v; + } + } + $sign = '?'; + if (!empty($url_params)) $sign = '&'; + $url = Helper::url(Router::getRequest()).$url_params.$sign.$this->getParam().'='.$page; + } else { + $sign = '?'; + if (strpos($url, '?')!==false || !empty($url_params)) $sign = '&'; + $url = Helper::url($url).$url_params.$sign.$this->getParam().'='.$page; + } + return $url; + } + + public function __toString() { + $limit = $this->getLimit(); + $page = $this->getPage(); + $total = $this->getTotal(); + $pages = $this->getPages(); + + if ($total === null || $total<=0 || $limit === null || $limit<=0 || $total<=$limit) return ''; + + $total = ceil($total / $limit); + $pages_half = floor($pages/2); + $start = 1; + $end = $total>$pages ? $pages : $total; + if ($total>$pages && $page>$pages_half && $total-$page>$pages_half) { + $start = $page - $pages_half + 1; + $end = $start + $pages - 1; + } else if ($total>$pages && $page>$pages_half && $total-$page<=$pages_half) { + $end = $total; + $start = $end - $pages + 1; + } + + $class = $this->getClass(); + $id = $this->getId(); + if (!empty($class)) $class = ' '.$class; + + $html = Helper::tag_open('nav'); + if (!empty($id)) { + $html .= Helper::tag_open('ul',array('class'=>self::PAGINATION_CLASS.$class,'id'=>$id)); + } else { + $html .= Helper::tag_open('ul',array('class'=>self::PAGINATION_CLASS.$class)); + } + if ($page>1 && $page<=$total) { + $html .= Helper::tag_open('li'); + $html .= Helper::tag_open('a', array('href'=>$this->url($page-1))); + $html .= Helper::tag_open('span'); + $html .= '«'; + $html .= Helper::tag_close('span'); + $html .= Helper::tag_close('a'); + $html .= Helper::tag_close('li'); + } else { + $html .= Helper::tag_open('li',array('class'=>'disabled')); + $html .= Helper::tag_open('span'); + $html .= '«'; + $html .= Helper::tag_close('span'); + $html .= Helper::tag_close('li'); + } + for ($i=$start; $i<=$end; $i++) { + if ($i==$page) { + $html .= Helper::tag_open('li',array('class'=>'active')); + $html .= Helper::tag('span', $i); + } else { + $html .= Helper::tag_open('li'); + $html .= Helper::tag('a', $i, array('href'=>$this->url($i))); + } + $html .= Helper::tag_close('li'); + } + if ($page<$total) { + $html .= Helper::tag_open('li'); + $html .= Helper::tag_open('a', array('href'=>$this->url($page+1))); + $html .= Helper::tag_open('span'); + $html .= '»'; + $html .= Helper::tag_close('span'); + $html .= Helper::tag_close('a'); + $html .= Helper::tag_close('li'); + } else { + $html .= Helper::tag_open('li',array('class'=>'disabled')); + $html .= Helper::tag_open('span'); + $html .= '»'; + $html .= Helper::tag_close('span'); + $html .= Helper::tag_close('li'); + } + $html .= Helper::tag_close('ul'); + $html .= Helper::tag_close('nav'); + return $html; + } +} \ No newline at end of file diff --git a/zira/permission.php b/zira/permission.php new file mode 100644 index 0000000..b5d2571 --- /dev/null +++ b/zira/permission.php @@ -0,0 +1,75 @@ +name] = $row->allow; + } + self::$_loaded[$group_id] = $permissions; + } + + public static function check($permission, $user = null) { + if ($user===null && User::isAuthorized()) $user = User::getCurrent(); + if (!$user) return false; + self::loadOnceGroupPermissions($user->group_id); + if (!isset(self::$_loaded[$user->group_id])) return false; + if (!isset(self::$_loaded[$user->group_id][$permission])) return false; + return !empty(self::$_loaded[$user->group_id][$permission]); + } +} \ No newline at end of file diff --git a/zira/phpmailer/phpmailer.php b/zira/phpmailer/phpmailer.php new file mode 100644 index 0000000..9674f22 --- /dev/null +++ b/zira/phpmailer/phpmailer.php @@ -0,0 +1,3664 @@ + + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2012 - 2014 Marcus Bointon + * @copyright 2010 - 2012 Jim Jagielski + * @copyright 2004 - 2009 Andy Prevost + * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** + * PHPMailer - PHP email creation and transport class. + * @package PHPMailer + * @author Marcus Bointon (Synchro/coolbru) + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + */ + +namespace Zira\Phpmailer; + +class Phpmailer +{ + /** + * The PHPMailer Version number. + * @type string + */ + public $Version = '5.2.12'; + + /** + * Email priority. + * Options: null (default), 1 = High, 3 = Normal, 5 = low. + * When null, the header is not set at all. + * @type integer + */ + public $Priority = null; + + /** + * The character set of the message. + * @type string + */ + public $CharSet = 'iso-8859-1'; + + /** + * The MIME Content-type of the message. + * @type string + */ + public $ContentType = 'text/plain'; + + /** + * The message encoding. + * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable". + * @type string + */ + public $Encoding = '8bit'; + + /** + * Holds the most recent mailer error message. + * @type string + */ + public $ErrorInfo = ''; + + /** + * The From email address for the message. + * @type string + */ + public $From = 'root@localhost'; + + /** + * The From name of the message. + * @type string + */ + public $FromName = 'Root User'; + + /** + * The Sender email (Return-Path) of the message. + * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. + * @type string + */ + public $Sender = ''; + + /** + * The Return-Path of the message. + * If empty, it will be set to either From or Sender. + * @type string + * @deprecated Email senders should never set a return-path header; + * it's the receiver's job (RFC5321 section 4.4), so this no longer does anything. + * @link https://tools.ietf.org/html/rfc5321#section-4.4 RFC5321 reference + */ + public $ReturnPath = ''; + + /** + * The Subject of the message. + * @type string + */ + public $Subject = ''; + + /** + * An HTML or plain text message body. + * If HTML then call isHTML(true). + * @type string + */ + public $Body = ''; + + /** + * The plain-text message body. + * This body can be read by mail clients that do not have HTML email + * capability such as mutt & Eudora. + * Clients that can read HTML will view the normal Body. + * @type string + */ + public $AltBody = ''; + + /** + * The complete compiled MIME message body. + * @access protected + * @type string + */ + protected $MIMEBody = ''; + + /** + * The complete compiled MIME message headers. + * @type string + * @access protected + */ + protected $MIMEHeader = ''; + + /** + * Extra headers that createHeader() doesn't fold in. + * @type string + * @access protected + */ + protected $mailHeader = ''; + + /** + * Word-wrap the message body to this number of chars. + * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance. + * @type integer + */ + public $WordWrap = 0; + + /** + * Which method to use to send mail. + * Options: "mail", "sendmail", or "smtp". + * @type string + */ + public $Mailer = 'mail'; + + /** + * The path to the sendmail program. + * @type string + */ + public $Sendmail = '/usr/sbin/sendmail'; + + /** + * Whether mail() uses a fully sendmail-compatible MTA. + * One which supports sendmail's "-oi -f" options. + * @type boolean + */ + public $UseSendmailOptions = true; + + /** + * Path to PHPMailer plugins. + * Useful if the SMTP class is not in the PHP include path. + * @type string + * @deprecated Should not be needed now there is an autoloader. + */ + public $PluginDir = ''; + + /** + * The email address that a reading confirmation should be sent to. + * @type string + */ + public $ConfirmReadingTo = ''; + + /** + * The hostname to use in Message-Id and Received headers + * and as default HELO string. + * If empty, the value returned + * by SERVER_NAME is used or 'localhost.localdomain'. + * @type string + */ + public $Hostname = ''; + + /** + * An ID to be used in the Message-Id header. + * If empty, a unique id will be generated. + * @type string + */ + public $MessageID = ''; + + /** + * The message Date to be used in the Date header. + * If empty, the current date will be added. + * @type string + */ + public $MessageDate = ''; + + /** + * SMTP hosts. + * Either a single hostname or multiple semicolon-delimited hostnames. + * You can also specify a different port + * for each host by using this format: [hostname:port] + * (e.g. "smtp1.example.com:25;smtp2.example.com"). + * You can also specify encryption type, for example: + * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465"). + * Hosts will be tried in order. + * @type string + */ + public $Host = 'localhost'; + + /** + * The default SMTP server port. + * @type integer + * @TODO Why is this needed when the SMTP class takes care of it? + */ + public $Port = 25; + + /** + * The SMTP HELO of the message. + * Default is $Hostname. + * @type string + * @see PHPMailer::$Hostname + */ + public $Helo = ''; + + /** + * What kind of encryption to use on the SMTP connection. + * Options: '', 'ssl' or 'tls' + * @type string + */ + public $SMTPSecure = ''; + + /** + * Whether to enable TLS encryption automatically if a server supports it, + * even if `SMTPSecure` is not set to 'tls'. + * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid. + * @type boolean + */ + public $SMTPAutoTLS = true; + + /** + * Whether to use SMTP authentication. + * Uses the Username and Password properties. + * @type boolean + * @see PHPMailer::$Username + * @see PHPMailer::$Password + */ + public $SMTPAuth = false; + + /** + * Options array passed to stream_context_create when connecting via SMTP. + * @type array + */ + public $SMTPOptions = array(); + + /** + * SMTP username. + * @type string + */ + public $Username = ''; + + /** + * SMTP password. + * @type string + */ + public $Password = ''; + + /** + * SMTP auth type. + * Options are LOGIN (default), PLAIN, NTLM, CRAM-MD5 + * @type string + */ + public $AuthType = ''; + + /** + * SMTP realm. + * Used for NTLM auth + * @type string + */ + public $Realm = ''; + + /** + * SMTP workstation. + * Used for NTLM auth + * @type string + */ + public $Workstation = ''; + + /** + * The SMTP server timeout in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * @type integer + */ + public $Timeout = 300; + + /** + * SMTP class debug output mode. + * Debug output level. + * Options: + * * `0` No output + * * `1` Commands + * * `2` Data and commands + * * `3` As 2 plus connection status + * * `4` Low-level data output + * @type integer + * @see SMTP::$do_debug + */ + public $SMTPDebug = 0; + + /** + * How to handle debug output. + * Options: + * * `echo` Output plain-text as-is, appropriate for CLI + * * `html` Output escaped, line breaks converted to `
    `, appropriate for browser output + * * `error_log` Output to error log as configured in php.ini + * + * Alternatively, you can provide a callable expecting two params: a message string and the debug level: + * + * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; + * + * @type string|callable + * @see SMTP::$Debugoutput + */ + public $Debugoutput = 'echo'; + + /** + * Whether to keep SMTP connection open after each message. + * If this is set to true then to close the connection + * requires an explicit call to smtpClose(). + * @type boolean + */ + public $SMTPKeepAlive = false; + + /** + * Whether to split multiple to addresses into multiple messages + * or send them all in one message. + * @type boolean + */ + public $SingleTo = false; + + /** + * Storage for addresses when SingleTo is enabled. + * @type array + * @TODO This should really not be public + */ + public $SingleToArray = array(); + + /** + * Whether to generate VERP addresses on send. + * Only applicable when sending via SMTP. + * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path + * @link http://www.postfix.org/VERP_README.html Postfix VERP info + * @type boolean + */ + public $do_verp = false; + + /** + * Whether to allow sending messages with an empty body. + * @type boolean + */ + public $AllowEmpty = false; + + /** + * The default line ending. + * @note The default remains "\n". We force CRLF where we know + * it must be used via self::CRLF. + * @type string + */ + public $LE = "\n"; + + /** + * DKIM selector. + * @type string + */ + public $DKIM_selector = ''; + + /** + * DKIM Identity. + * Usually the email address used as the source of the email + * @type string + */ + public $DKIM_identity = ''; + + /** + * DKIM passphrase. + * Used if your key is encrypted. + * @type string + */ + public $DKIM_passphrase = ''; + + /** + * DKIM signing domain name. + * @example 'example.com' + * @type string + */ + public $DKIM_domain = ''; + + /** + * DKIM private key file path. + * @type string + */ + public $DKIM_private = ''; + + /** + * Callback Action function name. + * + * The function that handles the result of the send email action. + * It is called out by send() for each email sent. + * + * Value can be any php callable: http://www.php.net/is_callable + * + * Parameters: + * boolean $result result of the send action + * string $to email address of the recipient + * string $cc cc email addresses + * string $bcc bcc email addresses + * string $subject the subject + * string $body the email body + * string $from email address of sender + * @type string + */ + public $action_function = ''; + + /** + * What to put in the X-Mailer header. + * Options: An empty string for PHPMailer default, whitespace for none, or a string to use + * @type string + */ + public $XMailer = ''; + + /** + * Only For XOAUTH - Google + * Options: An empty string for PHPMailer default, Enter the email used to get access token + * @type string + */ +// public $UserEmail = ''; +// public $RefreshToken = ''; +// public $ClientId = ''; +// public $ClientSecret = ''; + + + /** + * An instance of the SMTP sender class. + * @type SMTP + * @access protected + */ + protected $smtp = null; + + /** + * The array of 'to' addresses. + * @type array + * @access protected + */ + protected $to = array(); + + /** + * The array of 'cc' addresses. + * @type array + * @access protected + */ + protected $cc = array(); + + /** + * The array of 'bcc' addresses. + * @type array + * @access protected + */ + protected $bcc = array(); + + /** + * The array of reply-to names and addresses. + * @type array + * @access protected + */ + protected $ReplyTo = array(); + + /** + * An array of all kinds of addresses. + * Includes all of $to, $cc, $bcc + * @type array + * @access protected + */ + protected $all_recipients = array(); + + /** + * The array of attachments. + * @type array + * @access protected + */ + protected $attachment = array(); + + /** + * The array of custom headers. + * @type array + * @access protected + */ + protected $CustomHeader = array(); + + /** + * The most recent Message-ID (including angular brackets). + * @type string + * @access protected + */ + protected $lastMessageID = ''; + + /** + * The message's MIME type. + * @type string + * @access protected + */ + protected $message_type = ''; + + /** + * The array of MIME boundary strings. + * @type array + * @access protected + */ + protected $boundary = array(); + + /** + * The array of available languages. + * @type array + * @access protected + */ + protected $language = array(); + + /** + * The number of errors encountered. + * @type integer + * @access protected + */ + protected $error_count = 0; + + /** + * The S/MIME certificate file path. + * @type string + * @access protected + */ + protected $sign_cert_file = ''; + + /** + * The S/MIME key file path. + * @type string + * @access protected + */ + protected $sign_key_file = ''; + + /** + * The optional S/MIME extra certificates ("CA Chain") file path. + * @type string + * @access protected + */ + protected $sign_extracerts_file = ''; + + /** + * The S/MIME password for the key. + * Used only if the key is encrypted. + * @type string + * @access protected + */ + protected $sign_key_pass = ''; + + /** + * Whether to throw exceptions for errors. + * @type boolean + * @access protected + */ + protected $exceptions = false; + + /** + * Unique ID used for message ID and boundaries. + * @type string + * @access protected + */ + protected $uniqueid = ''; + + /** + * Error severity: message only, continue processing. + */ + const STOP_MESSAGE = 0; + + /** + * Error severity: message, likely ok to continue processing. + */ + const STOP_CONTINUE = 1; + + /** + * Error severity: message, plus full stop, critical error reached. + */ + const STOP_CRITICAL = 2; + + /** + * SMTP RFC standard line ending. + */ + const CRLF = "\r\n"; + + /** + * The maximum line length allowed by RFC 2822 section 2.1.1 + * @type integer + */ + const MAX_LINE_LENGTH = 998; + + /** + * Constructor. + * @param boolean $exceptions Should we throw external exceptions? + */ + public function __construct($exceptions = false) + { + $this->exceptions = (boolean)$exceptions; + } + + /** + * Destructor. + */ + public function __destruct() + { + //Close any open SMTP connection nicely + if ($this->Mailer == 'smtp') { + $this->smtpClose(); + } + } + + /** + * Call mail() in a safe_mode-aware fashion. + * Also, unless sendmail_path points to sendmail (or something that + * claims to be sendmail), don't pass params (not a perfect fix, + * but it will do) + * @param string $to To + * @param string $subject Subject + * @param string $body Message Body + * @param string $header Additional Header(s) + * @param string $params Params + * @access private + * @return boolean + */ + private function mailPassthru($to, $subject, $body, $header, $params) + { + //Check overloading of mail function to avoid double-encoding + if (ini_get('mbstring.func_overload') & 1) { + $subject = $this->secureHeader($subject); + } else { + $subject = $this->encodeHeader($this->secureHeader($subject)); + } + if (ini_get('safe_mode') || !($this->UseSendmailOptions)) { + $result = @mail($to, $subject, $body, $header); + } else { + $result = @mail($to, $subject, $body, $header, $params); + } + return $result; + } + + /** + * Output debugging info via user-defined method. + * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug). + * @see PHPMailer::$Debugoutput + * @see PHPMailer::$SMTPDebug + * @param string $str + */ + protected function edebug($str) + { + if ($this->SMTPDebug <= 0) { + return; + } + //Avoid clash with built-in function names + if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) { + call_user_func($this->Debugoutput, $str, $this->SMTPDebug); + return; + } + switch ($this->Debugoutput) { + case 'error_log': + //Don't output, just log + error_log($str); + break; + case 'html': + //Cleans up output a bit for a better looking, HTML-safe output + echo htmlentities( + preg_replace('/[\r\n]+/', '', $str), + ENT_QUOTES, + 'UTF-8' + ) + . "
    \n"; + break; + case 'echo': + default: + //Normalize line breaks + $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str); + echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( + "\n", + "\n \t ", + trim($str) + ) . "\n"; + } + } + + /** + * Sets message type to HTML or plain. + * @param boolean $isHtml True for HTML mode. + * @return void + */ + public function isHTML($isHtml = true) + { + if ($isHtml) { + $this->ContentType = 'text/html'; + } else { + $this->ContentType = 'text/plain'; + } + } + + /** + * Send messages using SMTP. + * @return void + */ + public function isSMTP() + { + $this->Mailer = 'smtp'; + } + + /** + * Send messages using PHP's mail() function. + * @return void + */ + public function isMail() + { + $this->Mailer = 'mail'; + } + + /** + * Send messages using $Sendmail. + * @return void + */ + public function isSendmail() + { + $ini_sendmail_path = ini_get('sendmail_path'); + + if (!stristr($ini_sendmail_path, 'sendmail')) { + $this->Sendmail = '/usr/sbin/sendmail'; + } else { + $this->Sendmail = $ini_sendmail_path; + } + $this->Mailer = 'sendmail'; + } + + /** + * Send messages using qmail. + * @return void + */ + public function isQmail() + { + $ini_sendmail_path = ini_get('sendmail_path'); + + if (!stristr($ini_sendmail_path, 'qmail')) { + $this->Sendmail = '/var/qmail/bin/qmail-inject'; + } else { + $this->Sendmail = $ini_sendmail_path; + } + $this->Mailer = 'qmail'; + } + + /** + * Add a "To" address. + * @param string $address + * @param string $name + * @return boolean true on success, false if address already used + */ + public function addAddress($address, $name = '') + { + return $this->addAnAddress('to', $address, $name); + } + + /** + * Add a "CC" address. + * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. + * @param string $address + * @param string $name + * @return boolean true on success, false if address already used + */ + public function addCC($address, $name = '') + { + return $this->addAnAddress('cc', $address, $name); + } + + /** + * Add a "BCC" address. + * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. + * @param string $address + * @param string $name + * @return boolean true on success, false if address already used + */ + public function addBCC($address, $name = '') + { + return $this->addAnAddress('bcc', $address, $name); + } + + /** + * Add a "Reply-to" address. + * @param string $address + * @param string $name + * @return boolean + */ + public function addReplyTo($address, $name = '') + { + return $this->addAnAddress('Reply-To', $address, $name); + } + + /** + * Add an address to one of the recipient arrays. + * Addresses that have been added already return false, but do not throw exceptions + * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo' + * @param string $address The email address to send to + * @param string $name + * @throws phpmailerException + * @return boolean true on success, false if address already used or invalid in some way + * @access protected + */ + protected function addAnAddress($kind, $address, $name = '') + { + if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) { + $this->setError($this->lang('Invalid recipient array') . ': ' . $kind); + $this->edebug($this->lang('Invalid recipient array') . ': ' . $kind); + if ($this->exceptions) { + throw new phpmailerException('Invalid recipient array: ' . $kind); + } + return false; + } + $address = trim($address); + $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim + if (!$this->validateAddress($address)) { + $this->setError($this->lang('invalid_address') . ': ' . $address); + $this->edebug($this->lang('invalid_address') . ': ' . $address); + if ($this->exceptions) { + throw new phpmailerException($this->lang('invalid_address') . ': ' . $address); + } + return false; + } + if ($kind != 'Reply-To') { + if (!isset($this->all_recipients[strtolower($address)])) { + array_push($this->$kind, array($address, $name)); + $this->all_recipients[strtolower($address)] = true; + return true; + } + } else { + if (!array_key_exists(strtolower($address), $this->ReplyTo)) { + $this->ReplyTo[strtolower($address)] = array($address, $name); + return true; + } + } + return false; + } + + /** + * Parse and validate a string containing one or more RFC822-style comma-separated email addresses + * of the form "display name
    " into an array of name/address pairs. + * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available. + * Note that quotes in the name part are removed. + * @param string $addrstr The address list string + * @param bool $useimap Whether to use the IMAP extension to parse the list + * @return array + * @link http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation + */ + public function parseAddresses($addrstr, $useimap = true) + { + $addresses = array(); + if ($useimap and function_exists('imap_rfc822_parse_adrlist')) { + //Use this built-in parser if it's available + $list = imap_rfc822_parse_adrlist($addrstr, ''); + foreach ($list as $address) { + if ($address->host != '.SYNTAX-ERROR.') { + if ($this->validateAddress($address->mailbox . '@' . $address->host)) { + $addresses[] = array( + 'name' => (property_exists($address, 'personal') ? $address->personal : ''), + 'address' => $address->mailbox . '@' . $address->host + ); + } + } + } + } else { + //Use this simpler parser + $list = explode(',', $addrstr); + foreach ($list as $address) { + $address = trim($address); + //Is there a separate name part? + if (strpos($address, '<') === false) { + //No separate name, just use the whole thing + if ($this->validateAddress($address)) { + $addresses[] = array( + 'name' => '', + 'address' => $address + ); + } + } else { + list($name, $email) = explode('<', $address); + $email = trim(str_replace('>', '', $email)); + if ($this->validateAddress($email)) { + $addresses[] = array( + 'name' => trim(str_replace(array('"', "'"), '', $name)), + 'address' => $email + ); + } + } + } + } + return $addresses; + } + + /** + * Set the From and FromName properties. + * @param string $address + * @param string $name + * @param boolean $auto Whether to also set the Sender address, defaults to true + * @throws phpmailerException + * @return boolean + */ + public function setFrom($address, $name = '', $auto = true) + { + $address = trim($address); + $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim + if (!$this->validateAddress($address)) { + $this->setError($this->lang('invalid_address') . ': ' . $address); + $this->edebug($this->lang('invalid_address') . ': ' . $address); + if ($this->exceptions) { + throw new phpmailerException($this->lang('invalid_address') . ': ' . $address); + } + return false; + } + $this->From = $address; + $this->FromName = $name; + if ($auto) { + if (empty($this->Sender)) { + $this->Sender = $address; + } + } + return true; + } + + /** + * Return the Message-ID header of the last email. + * Technically this is the value from the last time the headers were created, + * but it's also the message ID of the last sent message except in + * pathological cases. + * @return string + */ + public function getLastMessageID() + { + return $this->lastMessageID; + } + + /** + * Check that a string looks like an email address. + * @param string $address The email address to check + * @param string $patternselect A selector for the validation pattern to use : + * * `auto` Pick strictest one automatically; + * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; + * * `pcre` Use old PCRE implementation; + * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; same as pcre8 but does not allow 'dotless' domains; + * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. + * * `noregex` Don't use a regex: super fast, really dumb. + * @return boolean + * @static + * @access public + */ + public static function validateAddress($address, $patternselect = 'auto') + { + if (!$patternselect or $patternselect == 'auto') { + //Check this constant first so it works when extension_loaded() is disabled by safe mode + //Constant was added in PHP 5.2.4 + if (defined('PCRE_VERSION')) { + //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2 + if (version_compare(PCRE_VERSION, '8.0.3') >= 0) { + $patternselect = 'pcre8'; + } else { + $patternselect = 'pcre'; + } + } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) { + //Fall back to older PCRE + $patternselect = 'pcre'; + } else { + //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension + if (version_compare(PHP_VERSION, '5.2.0') >= 0) { + $patternselect = 'php'; + } else { + $patternselect = 'noregex'; + } + } + } + switch ($patternselect) { + case 'pcre8': + /** + * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains. + * @link http://squiloople.com/2009/12/20/email-address-validation/ + * @copyright 2009-2010 Michael Rushton + * Feel free to use and redistribute this code. But please keep this copyright notice. + */ + return (boolean)preg_match( + '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' . + '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' . + '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' . + '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' . + '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' . + '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' . + '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' . + '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' . + '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', + $address + ); + case 'pcre': + //An older regex that doesn't need a recent PCRE + return (boolean)preg_match( + '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' . + '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' . + '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' . + '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' . + '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' . + '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' . + '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' . + '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' . + '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' . + '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD', + $address + ); + case 'html5': + /** + * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements. + * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email) + */ + return (boolean)preg_match( + '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' . + '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD', + $address + ); + case 'noregex': + //No PCRE! Do something _very_ approximate! + //Check the address is 3 chars or longer and contains an @ that's not the first or last char + return (strlen($address) >= 3 + and strpos($address, '@') >= 1 + and strpos($address, '@') != strlen($address) - 1); + case 'php': + default: + return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL); + } + } + + /** + * Create a message and send it. + * Uses the sending method specified by $Mailer. + * @throws phpmailerException + * @return boolean false on error - See the ErrorInfo property for details of the error. + */ + public function send() + { + try { + if (!$this->preSend()) { + return false; + } + return $this->postSend(); + } catch (phpmailerException $exc) { + $this->mailHeader = ''; + $this->setError($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + return false; + } + } + + /** + * Prepare a message for sending. + * @throws phpmailerException + * @return boolean + */ + public function preSend() + { + try { + $this->mailHeader = ''; + if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { + throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL); + } + + // Set whether the message is multipart/alternative + if (!empty($this->AltBody)) { + $this->ContentType = 'multipart/alternative'; + } + + $this->error_count = 0; // Reset errors + $this->setMessageType(); + // Refuse to send an empty message unless we are specifically allowing it + if (!$this->AllowEmpty and empty($this->Body)) { + throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL); + } + + // Create body before headers in case body makes changes to headers (e.g. altering transfer encoding) + $this->MIMEHeader = ''; + $this->MIMEBody = $this->createBody(); + // createBody may have added some headers, so retain them + $tempheaders = $this->MIMEHeader; + $this->MIMEHeader = $this->createHeader(); + $this->MIMEHeader .= $tempheaders; + + // To capture the complete message when using mail(), create + // an extra header list which createHeader() doesn't fold in + if ($this->Mailer == 'mail') { + if (count($this->to) > 0) { + $this->mailHeader .= $this->addrAppend('To', $this->to); + } else { + $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;'); + } + $this->mailHeader .= $this->headerLine( + 'Subject', + $this->encodeHeader($this->secureHeader(trim($this->Subject))) + ); + } + + // Sign with DKIM if enabled + if (!empty($this->DKIM_domain) + && !empty($this->DKIM_private) + && !empty($this->DKIM_selector) + && file_exists($this->DKIM_private)) { + $header_dkim = $this->DKIM_Add( + $this->MIMEHeader . $this->mailHeader, + $this->encodeHeader($this->secureHeader($this->Subject)), + $this->MIMEBody + ); + $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . self::CRLF . + str_replace("\r\n", "\n", $header_dkim) . self::CRLF; + } + return true; + } catch (phpmailerException $exc) { + $this->setError($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + return false; + } + } + + /** + * Actually send a message. + * Send the email via the selected mechanism + * @throws phpmailerException + * @return boolean + */ + public function postSend() + { + try { + // Choose the mailer and send through it + switch ($this->Mailer) { + case 'sendmail': + case 'qmail': + return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody); + case 'smtp': + return $this->smtpSend($this->MIMEHeader, $this->MIMEBody); + case 'mail': + return $this->mailSend($this->MIMEHeader, $this->MIMEBody); + default: + $sendMethod = $this->Mailer.'Send'; + if (method_exists($this, $sendMethod)) { + return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody); + } + + return $this->mailSend($this->MIMEHeader, $this->MIMEBody); + } + } catch (phpmailerException $exc) { + $this->setError($exc->getMessage()); + $this->edebug($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + } + return false; + } + + /** + * Send mail using the $Sendmail program. + * @param string $header The message headers + * @param string $body The message body + * @see PHPMailer::$Sendmail + * @throws phpmailerException + * @access protected + * @return boolean + */ + protected function sendmailSend($header, $body) + { + if ($this->Sender != '') { + if ($this->Mailer == 'qmail') { + $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + } else { + $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + } + } else { + if ($this->Mailer == 'qmail') { + $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail)); + } else { + $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail)); + } + } + if ($this->SingleTo) { + foreach ($this->SingleToArray as $toAddr) { + if (!@$mail = popen($sendmail, 'w')) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + fputs($mail, 'To: ' . $toAddr . "\n"); + fputs($mail, $header); + fputs($mail, $body); + $result = pclose($mail); + $this->doCallback( + ($result == 0), + array($toAddr), + $this->cc, + $this->bcc, + $this->Subject, + $body, + $this->From + ); + if ($result != 0) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + } + } else { + if (!@$mail = popen($sendmail, 'w')) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + fputs($mail, $header); + fputs($mail, $body); + $result = pclose($mail); + $this->doCallback(($result == 0), $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); + if ($result != 0) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + } + return true; + } + + /** + * Send mail using the PHP mail() function. + * @param string $header The message headers + * @param string $body The message body + * @link http://www.php.net/manual/en/book.mail.php + * @throws phpmailerException + * @access protected + * @return boolean + */ + protected function mailSend($header, $body) + { + $toArr = array(); + foreach ($this->to as $toaddr) { + $toArr[] = $this->addrFormat($toaddr); + } + $to = implode(', ', $toArr); + + if (empty($this->Sender)) { + $params = ' '; + } else { + $params = sprintf('-f%s', $this->Sender); + } + if ($this->Sender != '' and !ini_get('safe_mode')) { + $old_from = ini_get('sendmail_from'); + ini_set('sendmail_from', $this->Sender); + } + $result = false; + if ($this->SingleTo && count($toArr) > 1) { + foreach ($toArr as $toAddr) { + $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); + $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From); + } + } else { + $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params); + $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); + } + if (isset($old_from)) { + ini_set('sendmail_from', $old_from); + } + if (!$result) { + throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL); + } + return true; + } + + /** + * Get an instance to use for SMTP operations. + * Override this function to load your own SMTP implementation + * @return SMTP + */ + public function getSMTPInstance() + { + if (!is_object($this->smtp)) { + $this->smtp = new Smtp; + } + return $this->smtp; + } + + /** + * Send mail via SMTP. + * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. + * Uses the PHPMailerSMTP class by default. + * @see PHPMailer::getSMTPInstance() to use a different class. + * @param string $header The message headers + * @param string $body The message body + * @throws phpmailerException + * @uses SMTP + * @access protected + * @return boolean + */ + protected function smtpSend($header, $body) + { + $bad_rcpt = array(); + if (!$this->smtpConnect($this->SMTPOptions)) { + throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL); + } + if ('' == $this->Sender) { + $smtp_from = $this->From; + } else { + $smtp_from = $this->Sender; + } + if (!$this->smtp->mail($smtp_from)) { + $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError())); + throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL); + } + + // Attempt to send to all recipients + foreach (array($this->to, $this->cc, $this->bcc) as $togroup) { + foreach ($togroup as $to) { + if (!$this->smtp->recipient($to[0])) { + $error = $this->smtp->getError(); + $bad_rcpt[] = array('to' => $to[0], 'error' => $error['detail']); + $isSent = false; + } else { + $isSent = true; + } + $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From); + } + } + + // Only send the DATA command if we have viable recipients + if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) { + throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL); + } + if ($this->SMTPKeepAlive) { + $this->smtp->reset(); + } else { + $this->smtp->quit(); + $this->smtp->close(); + } + //Create error message for any bad addresses + if (count($bad_rcpt) > 0) { + $errstr = ''; + foreach ($bad_rcpt as $bad) { + $errstr .= $bad['to'] . ': ' . $bad['error']; + } + throw new phpmailerException( + $this->lang('recipients_failed') . $errstr, + self::STOP_CONTINUE + ); + } + return true; + } + + /** + * Initiate a connection to an SMTP server. + * Returns false if the operation failed. + * @param array $options An array of options compatible with stream_context_create() + * @uses SMTP + * @access public + * @throws phpmailerException + * @return boolean + */ + public function smtpConnect($options = array()) + { + if (is_null($this->smtp)) { + $this->smtp = $this->getSMTPInstance(); + } + + // Already connected? + if ($this->smtp->connected()) { + return true; + } + + $this->smtp->setTimeout($this->Timeout); + $this->smtp->setDebugLevel($this->SMTPDebug); + $this->smtp->setDebugOutput($this->Debugoutput); + $this->smtp->setVerp($this->do_verp); + $hosts = explode(';', $this->Host); + $lastexception = null; + + foreach ($hosts as $hostentry) { + $hostinfo = array(); + if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) { + // Not a valid host entry + continue; + } + // $hostinfo[2]: optional ssl or tls prefix + // $hostinfo[3]: the hostname + // $hostinfo[4]: optional port number + // The host string prefix can temporarily override the current setting for SMTPSecure + // If it's not specified, the default value is used + $prefix = ''; + $secure = $this->SMTPSecure; + $tls = ($this->SMTPSecure == 'tls'); + if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) { + $prefix = 'ssl://'; + $tls = false; // Can't have SSL and TLS at the same time + $secure = 'ssl'; + } elseif ($hostinfo[2] == 'tls') { + $tls = true; + // tls doesn't use a prefix + $secure = 'tls'; + } + //Do we need the OpenSSL extension? + $sslext = defined('OPENSSL_ALGO_SHA1'); + if ('tls' === $secure or 'ssl' === $secure) { + //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled + if (!$sslext) { + throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL); + } + } + $host = $hostinfo[3]; + $port = $this->Port; + $tport = (integer)$hostinfo[4]; + if ($tport > 0 and $tport < 65536) { + $port = $tport; + } + if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) { + try { + if ($this->Helo) { + $hello = $this->Helo; + } else { + $hello = $this->serverHostname(); + } + $this->smtp->hello($hello); + //Automatically enable TLS encryption if: + // * it's not disabled + // * we have openssl extension + // * we are not already using SSL + // * the server offers STARTTLS + if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) { + $tls = true; + } + if ($tls) { + if (!$this->smtp->startTLS()) { + throw new phpmailerException($this->lang('connect_host')); + } + // We must resend HELO after tls negotiation + $this->smtp->hello($hello); + } + if ($this->SMTPAuth) { + if (!$this->smtp->authenticate( + $this->Username, + $this->Password, + $this->AuthType, + $this->Realm, + $this->Workstation + ) + ) { + throw new phpmailerException($this->lang('authenticate')); + } + } + return true; + } catch (phpmailerException $exc) { + $lastexception = $exc; + $this->edebug($exc->getMessage()); + // We must have connected, but then failed TLS or Auth, so close connection nicely + $this->smtp->quit(); + } + } + } + // If we get here, all connection attempts have failed, so close connection hard + $this->smtp->close(); + // As we've caught all exceptions, just report whatever the last one was + if ($this->exceptions and !is_null($lastexception)) { + throw $lastexception; + } + return false; + } + + /** + * Close the active SMTP session if one exists. + * @return void + */ + public function smtpClose() + { + if ($this->smtp !== null) { + if ($this->smtp->connected()) { + $this->smtp->quit(); + $this->smtp->close(); + } + } + } + + /** + * Get the array of strings for the current language. + * @return array + */ + public function getTranslations() + { + return $this->language; + } + + /** + * Create recipient headers. + * @access public + * @param string $type + * @param array $addr An array of recipient, + * where each recipient is a 2-element indexed array with element 0 containing an address + * and element 1 containing a name, like: + * array(array('joe@example.com', 'Joe User'), array('zoe@example.com', 'Zoe User')) + * @return string + */ + public function addrAppend($type, $addr) + { + $addresses = array(); + foreach ($addr as $address) { + $addresses[] = $this->addrFormat($address); + } + return $type . ': ' . implode(', ', $addresses) . $this->LE; + } + + /** + * Format an address for use in a message header. + * @access public + * @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name + * like array('joe@example.com', 'Joe User') + * @return string + */ + public function addrFormat($addr) + { + if (empty($addr[1])) { // No name provided + return $this->secureHeader($addr[0]); + } else { + return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader( + $addr[0] + ) . '>'; + } + } + + /** + * Word-wrap message. + * For use with mailers that do not automatically perform wrapping + * and for quoted-printable encoded messages. + * Original written by philippe. + * @param string $message The message to wrap + * @param integer $length The line length to wrap to + * @param boolean $qp_mode Whether to run in Quoted-Printable mode + * @access public + * @return string + */ + public function wrapText($message, $length, $qp_mode = false) + { + if ($qp_mode) { + $soft_break = sprintf(' =%s', $this->LE); + } else { + $soft_break = $this->LE; + } + // If utf-8 encoding is used, we will need to make sure we don't + // split multibyte characters when we wrap + $is_utf8 = (strtolower($this->CharSet) == 'utf-8'); + $lelen = strlen($this->LE); + $crlflen = strlen(self::CRLF); + + $message = $this->fixEOL($message); + //Remove a trailing line break + if (substr($message, -$lelen) == $this->LE) { + $message = substr($message, 0, -$lelen); + } + + //Split message into lines + $lines = explode($this->LE, $message); + //Message will be rebuilt in here + $message = ''; + foreach ($lines as $line) { + $words = explode(' ', $line); + $buf = ''; + $firstword = true; + foreach ($words as $word) { + if ($qp_mode and (strlen($word) > $length)) { + $space_left = $length - strlen($buf) - $crlflen; + if (!$firstword) { + if ($space_left > 20) { + $len = $space_left; + if ($is_utf8) { + $len = $this->utf8CharBoundary($word, $len); + } elseif (substr($word, $len - 1, 1) == '=') { + $len--; + } elseif (substr($word, $len - 2, 1) == '=') { + $len -= 2; + } + $part = substr($word, 0, $len); + $word = substr($word, $len); + $buf .= ' ' . $part; + $message .= $buf . sprintf('=%s', self::CRLF); + } else { + $message .= $buf . $soft_break; + } + $buf = ''; + } + while (strlen($word) > 0) { + if ($length <= 0) { + break; + } + $len = $length; + if ($is_utf8) { + $len = $this->utf8CharBoundary($word, $len); + } elseif (substr($word, $len - 1, 1) == '=') { + $len--; + } elseif (substr($word, $len - 2, 1) == '=') { + $len -= 2; + } + $part = substr($word, 0, $len); + $word = substr($word, $len); + + if (strlen($word) > 0) { + $message .= $part . sprintf('=%s', self::CRLF); + } else { + $buf = $part; + } + } + } else { + $buf_o = $buf; + if (!$firstword) { + $buf .= ' '; + } + $buf .= $word; + + if (strlen($buf) > $length and $buf_o != '') { + $message .= $buf_o . $soft_break; + $buf = $word; + } + } + $firstword = false; + } + $message .= $buf . self::CRLF; + } + + return $message; + } + + /** + * Find the last character boundary prior to $maxLength in a utf-8 + * quoted-printable encoded string. + * Original written by Colin Brown. + * @access public + * @param string $encodedText utf-8 QP text + * @param integer $maxLength Find the last character boundary prior to this length + * @return integer + */ + public function utf8CharBoundary($encodedText, $maxLength) + { + $foundSplitPos = false; + $lookBack = 3; + while (!$foundSplitPos) { + $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); + $encodedCharPos = strpos($lastChunk, '='); + if (false !== $encodedCharPos) { + // Found start of encoded character byte within $lookBack block. + // Check the encoded byte value (the 2 chars after the '=') + $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2); + $dec = hexdec($hex); + if ($dec < 128) { + // Single byte character. + // If the encoded char was found at pos 0, it will fit + // otherwise reduce maxLength to start of the encoded char + if ($encodedCharPos > 0) { + $maxLength = $maxLength - ($lookBack - $encodedCharPos); + } + $foundSplitPos = true; + } elseif ($dec >= 192) { + // First byte of a multi byte character + // Reduce maxLength to split at start of character + $maxLength = $maxLength - ($lookBack - $encodedCharPos); + $foundSplitPos = true; + } elseif ($dec < 192) { + // Middle byte of a multi byte character, look further back + $lookBack += 3; + } + } else { + // No encoded character found + $foundSplitPos = true; + } + } + return $maxLength; + } + + /** + * Apply word wrapping to the message body. + * Wraps the message body to the number of chars set in the WordWrap property. + * You should only do this to plain-text bodies as wrapping HTML tags may break them. + * This is called automatically by createBody(), so you don't need to call it yourself. + * @access public + * @return void + */ + public function setWordWrap() + { + if ($this->WordWrap < 1) { + return; + } + + switch ($this->message_type) { + case 'alt': + case 'alt_inline': + case 'alt_attach': + case 'alt_inline_attach': + $this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap); + break; + default: + $this->Body = $this->wrapText($this->Body, $this->WordWrap); + break; + } + } + + /** + * Assemble message headers. + * @access public + * @return string The assembled headers + */ + public function createHeader() + { + $result = ''; + + if ($this->MessageDate == '') { + $this->MessageDate = self::rfcDate(); + } + $result .= $this->headerLine('Date', $this->MessageDate); + + + // To be created automatically by mail() + if ($this->SingleTo) { + if ($this->Mailer != 'mail') { + foreach ($this->to as $toaddr) { + $this->SingleToArray[] = $this->addrFormat($toaddr); + } + } + } else { + if (count($this->to) > 0) { + if ($this->Mailer != 'mail') { + $result .= $this->addrAppend('To', $this->to); + } + } elseif (count($this->cc) == 0) { + $result .= $this->headerLine('To', 'undisclosed-recipients:;'); + } + } + + $result .= $this->addrAppend('From', array(array(trim($this->From), $this->FromName))); + + // sendmail and mail() extract Cc from the header before sending + if (count($this->cc) > 0) { + $result .= $this->addrAppend('Cc', $this->cc); + } + + // sendmail and mail() extract Bcc from the header before sending + if (( + $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail' + ) + and count($this->bcc) > 0 + ) { + $result .= $this->addrAppend('Bcc', $this->bcc); + } + + if (count($this->ReplyTo) > 0) { + $result .= $this->addrAppend('Reply-To', $this->ReplyTo); + } + + // mail() sets the subject itself + if ($this->Mailer != 'mail') { + $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject))); + } + + if ($this->MessageID != '') { + $this->lastMessageID = $this->MessageID; + } else { + $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->ServerHostname()); + } + $result .= $this->headerLine('Message-ID', $this->lastMessageID); + if (!is_null($this->Priority)) { + $result .= $this->headerLine('X-Priority', $this->Priority); + } + if ($this->XMailer == '') { + $result .= $this->headerLine( + 'X-Mailer', + 'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer/)' + ); + } else { + $myXmailer = trim($this->XMailer); + if ($myXmailer) { + $result .= $this->headerLine('X-Mailer', $myXmailer); + } + } + + if ($this->ConfirmReadingTo != '') { + $result .= $this->headerLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>'); + } + + // Add custom headers + foreach ($this->CustomHeader as $header) { + $result .= $this->headerLine( + trim($header[0]), + $this->encodeHeader(trim($header[1])) + ); + } + if (!$this->sign_key_file) { + $result .= $this->headerLine('MIME-Version', '1.0'); + $result .= $this->getMailMIME(); + } + + return $result; + } + + /** + * Get the message MIME type headers. + * @access public + * @return string + */ + public function getMailMIME() + { + $result = ''; + $ismultipart = true; + switch ($this->message_type) { + case 'inline': + $result .= $this->headerLine('Content-Type', 'multipart/related;'); + $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + case 'attach': + case 'inline_attach': + case 'alt_attach': + case 'alt_inline_attach': + $result .= $this->headerLine('Content-Type', 'multipart/mixed;'); + $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + case 'alt': + case 'alt_inline': + $result .= $this->headerLine('Content-Type', 'multipart/alternative;'); + $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + default: + // Catches case 'plain': and case '': + $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet); + $ismultipart = false; + break; + } + // RFC1341 part 5 says 7bit is assumed if not specified + if ($this->Encoding != '7bit') { + // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE + if ($ismultipart) { + if ($this->Encoding == '8bit') { + $result .= $this->headerLine('Content-Transfer-Encoding', '8bit'); + } + // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible + } else { + $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding); + } + } + + if ($this->Mailer != 'mail') { + $result .= $this->LE; + } + + return $result; + } + + /** + * Returns the whole MIME message. + * Includes complete headers and body. + * Only valid post preSend(). + * @see PHPMailer::preSend() + * @access public + * @return string + */ + public function getSentMIMEMessage() + { + return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody; + } + + /** + * Assemble the message body. + * Returns an empty string on failure. + * @access public + * @throws phpmailerException + * @return string The assembled message body + */ + public function createBody() + { + $body = ''; + //Create unique IDs and preset boundaries + $this->uniqueid = md5(uniqid(time())); + $this->boundary[1] = 'b1_' . $this->uniqueid; + $this->boundary[2] = 'b2_' . $this->uniqueid; + $this->boundary[3] = 'b3_' . $this->uniqueid; + + if ($this->sign_key_file) { + $body .= $this->getMailMIME() . $this->LE; + } + + $this->setWordWrap(); + + $bodyEncoding = $this->Encoding; + $bodyCharSet = $this->CharSet; + //Can we do a 7-bit downgrade? + if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) { + $bodyEncoding = '7bit'; + $bodyCharSet = 'us-ascii'; + } + //If lines are too long, and we're not already using an encoding that will shorten them, + //change to quoted-printable transfer encoding + if ('base64' != $this->Encoding and self::hasLineLongerThanMax($this->Body)) { + $this->Encoding = 'quoted-printable'; + $bodyEncoding = 'quoted-printable'; + } + + $altBodyEncoding = $this->Encoding; + $altBodyCharSet = $this->CharSet; + //Can we do a 7-bit downgrade? + if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) { + $altBodyEncoding = '7bit'; + $altBodyCharSet = 'us-ascii'; + } + //If lines are too long, change to quoted-printable transfer encoding + if (self::hasLineLongerThanMax($this->AltBody)) { + $altBodyEncoding = 'quoted-printable'; + } + //Use this as a preamble in all multipart message types + $mimepre = "This is a multi-part message in MIME format." . $this->LE . $this->LE; + switch ($this->message_type) { + case 'inline': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[1]); + break; + case 'attach': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + case 'inline_attach': + $body .= $mimepre; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/related;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[2]); + $body .= $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + case 'alt': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->endBoundary($this->boundary[1]); + break; + case 'alt_inline': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/related;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[2]); + $body .= $this->LE; + $body .= $this->endBoundary($this->boundary[1]); + break; + case 'alt_attach': + $body .= $mimepre; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->endBoundary($this->boundary[2]); + $body .= $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + case 'alt_inline_attach': + $body .= $mimepre; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->textLine('--' . $this->boundary[2]); + $body .= $this->headerLine('Content-Type', 'multipart/related;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[3]); + $body .= $this->LE; + $body .= $this->endBoundary($this->boundary[2]); + $body .= $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + default: + // catch case 'plain' and case '' + $body .= $this->encodeString($this->Body, $bodyEncoding); + break; + } + + if ($this->isError()) { + $body = ''; + } elseif ($this->sign_key_file) { + try { + if (!defined('PKCS7_TEXT')) { + throw new phpmailerException($this->lang('extension_missing') . 'openssl'); + } + // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1 + $file = tempnam(sys_get_temp_dir(), 'mail'); + if (false === file_put_contents($file, $body)) { + throw new phpmailerException($this->lang('signing') . ' Could not write temp file'); + } + $signed = tempnam(sys_get_temp_dir(), 'signed'); + //Workaround for PHP bug https://bugs.php.net/bug.php?id=69197 + if (empty($this->sign_extracerts_file)) { + $sign = @openssl_pkcs7_sign( + $file, + $signed, + 'file://' . realpath($this->sign_cert_file), + array('file://' . realpath($this->sign_key_file), $this->sign_key_pass), + null + ); + } else { + $sign = @openssl_pkcs7_sign( + $file, + $signed, + 'file://' . realpath($this->sign_cert_file), + array('file://' . realpath($this->sign_key_file), $this->sign_key_pass), + null, + PKCS7_DETACHED, + $this->sign_extracerts_file + ); + } + if ($sign) { + @unlink($file); + $body = file_get_contents($signed); + @unlink($signed); + //The message returned by openssl contains both headers and body, so need to split them up + $parts = explode("\n\n", $body, 2); + $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE; + $body = $parts[1]; + } else { + @unlink($file); + @unlink($signed); + throw new phpmailerException($this->lang('signing') . openssl_error_string()); + } + } catch (phpmailerException $exc) { + $body = ''; + if ($this->exceptions) { + throw $exc; + } + } + } + return $body; + } + + /** + * Return the start of a message boundary. + * @access protected + * @param string $boundary + * @param string $charSet + * @param string $contentType + * @param string $encoding + * @return string + */ + protected function getBoundary($boundary, $charSet, $contentType, $encoding) + { + $result = ''; + if ($charSet == '') { + $charSet = $this->CharSet; + } + if ($contentType == '') { + $contentType = $this->ContentType; + } + if ($encoding == '') { + $encoding = $this->Encoding; + } + $result .= $this->textLine('--' . $boundary); + $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet); + $result .= $this->LE; + // RFC1341 part 5 says 7bit is assumed if not specified + if ($encoding != '7bit') { + $result .= $this->headerLine('Content-Transfer-Encoding', $encoding); + } + $result .= $this->LE; + + return $result; + } + + /** + * Return the end of a message boundary. + * @access protected + * @param string $boundary + * @return string + */ + protected function endBoundary($boundary) + { + return $this->LE . '--' . $boundary . '--' . $this->LE; + } + + /** + * Set the message type. + * PHPMailer only supports some preset message types, + * not arbitrary MIME structures. + * @access protected + * @return void + */ + protected function setMessageType() + { + $type = array(); + if ($this->alternativeExists()) { + $type[] = 'alt'; + } + if ($this->inlineImageExists()) { + $type[] = 'inline'; + } + if ($this->attachmentExists()) { + $type[] = 'attach'; + } + $this->message_type = implode('_', $type); + if ($this->message_type == '') { + $this->message_type = 'plain'; + } + } + + /** + * Format a header line. + * @access public + * @param string $name + * @param string $value + * @return string + */ + public function headerLine($name, $value) + { + return $name . ': ' . $value . $this->LE; + } + + /** + * Return a formatted mail line. + * @access public + * @param string $value + * @return string + */ + public function textLine($value) + { + return $value . $this->LE; + } + + /** + * Add an attachment from a path on the filesystem. + * Returns false if the file could not be found or read. + * @param string $path Path to the attachment. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @param string $disposition Disposition to use + * @throws phpmailerException + * @return boolean + */ + public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') + { + try { + if (!@is_file($path)) { + throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE); + } + + // If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($path); + } + + $filename = basename($path); + if ($name == '') { + $name = $filename; + } + + $this->attachment[] = array( + 0 => $path, + 1 => $filename, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => false, // isStringAttachment + 6 => $disposition, + 7 => 0 + ); + + } catch (phpmailerException $exc) { + $this->setError($exc->getMessage()); + $this->edebug($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + return false; + } + return true; + } + + /** + * Return the array of attachments. + * @return array + */ + public function getAttachments() + { + return $this->attachment; + } + + /** + * Attach all file, string, and binary attachments to the message. + * Returns an empty string on failure. + * @access protected + * @param string $disposition_type + * @param string $boundary + * @return string + */ + protected function attachAll($disposition_type, $boundary) + { + // Return text of body + $mime = array(); + $cidUniq = array(); + $incl = array(); + + // Add all attachments + foreach ($this->attachment as $attachment) { + // Check if it is a valid disposition_filter + if ($attachment[6] == $disposition_type) { + // Check for string attachment + $string = ''; + $path = ''; + $bString = $attachment[5]; + if ($bString) { + $string = $attachment[0]; + } else { + $path = $attachment[0]; + } + + $inclhash = md5(serialize($attachment)); + if (in_array($inclhash, $incl)) { + continue; + } + $incl[] = $inclhash; + $name = $attachment[2]; + $encoding = $attachment[3]; + $type = $attachment[4]; + $disposition = $attachment[6]; + $cid = $attachment[7]; + if ($disposition == 'inline' && isset($cidUniq[$cid])) { + continue; + } + $cidUniq[$cid] = true; + + $mime[] = sprintf('--%s%s', $boundary, $this->LE); + //Only include a filename property if we have one + if (!empty($name)) { + $mime[] = sprintf( + 'Content-Type: %s; name="%s"%s', + $type, + $this->encodeHeader($this->secureHeader($name)), + $this->LE + ); + } else { + $mime[] = sprintf( + 'Content-Type: %s%s', + $type, + $this->LE + ); + } + // RFC1341 part 5 says 7bit is assumed if not specified + if ($encoding != '7bit') { + $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE); + } + + if ($disposition == 'inline') { + $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE); + } + + // If a filename contains any of these chars, it should be quoted, + // but not otherwise: RFC2183 & RFC2045 5.1 + // Fixes a warning in IETF's msglint MIME checker + // Allow for bypassing the Content-Disposition header totally + if (!(empty($disposition))) { + $encoded_name = $this->encodeHeader($this->secureHeader($name)); + if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) { + $mime[] = sprintf( + 'Content-Disposition: %s; filename="%s"%s', + $disposition, + $encoded_name, + $this->LE . $this->LE + ); + } else { + if (!empty($encoded_name)) { + $mime[] = sprintf( + 'Content-Disposition: %s; filename=%s%s', + $disposition, + $encoded_name, + $this->LE . $this->LE + ); + } else { + $mime[] = sprintf( + 'Content-Disposition: %s%s', + $disposition, + $this->LE . $this->LE + ); + } + } + } else { + $mime[] = $this->LE; + } + + // Encode as string attachment + if ($bString) { + $mime[] = $this->encodeString($string, $encoding); + if ($this->isError()) { + return ''; + } + $mime[] = $this->LE . $this->LE; + } else { + $mime[] = $this->encodeFile($path, $encoding); + if ($this->isError()) { + return ''; + } + $mime[] = $this->LE . $this->LE; + } + } + } + + $mime[] = sprintf('--%s--%s', $boundary, $this->LE); + + return implode('', $mime); + } + + /** + * Encode a file attachment in requested format. + * Returns an empty string on failure. + * @param string $path The full path to the file + * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * @throws phpmailerException + * @see EncodeFile(encodeFile + * @access protected + * @return string + */ + protected function encodeFile($path, $encoding = 'base64') + { + try { + if (!is_readable($path)) { + throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE); + } + $magic_quotes = get_magic_quotes_runtime(); + if ($magic_quotes) { + //Doesn't exist in PHP 5.4, but we don't need to check because + //get_magic_quotes_runtime always returns false in 5.4+ + //so it will never get here + ini_set('magic_quotes_runtime', false); + } + $file_buffer = file_get_contents($path); + $file_buffer = $this->encodeString($file_buffer, $encoding); + if ($magic_quotes) { + ini_set('magic_quotes_runtime', $magic_quotes); + } + return $file_buffer; + } catch (\Exception $exc) { + $this->setError($exc->getMessage()); + return ''; + } + } + + /** + * Encode a string in requested format. + * Returns an empty string on failure. + * @param string $str The text to encode + * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * @access public + * @return string + */ + public function encodeString($str, $encoding = 'base64') + { + $encoded = ''; + switch (strtolower($encoding)) { + case 'base64': + $encoded = chunk_split(base64_encode($str), 76, $this->LE); + break; + case '7bit': + case '8bit': + $encoded = $this->fixEOL($str); + // Make sure it ends with a line break + if (substr($encoded, -(strlen($this->LE))) != $this->LE) { + $encoded .= $this->LE; + } + break; + case 'binary': + $encoded = $str; + break; + case 'quoted-printable': + $encoded = $this->encodeQP($str); + break; + default: + $this->setError($this->lang('encoding') . $encoding); + break; + } + return $encoded; + } + + /** + * Encode a header string optimally. + * Picks shortest of Q, B, quoted-printable or none. + * @access public + * @param string $str + * @param string $position + * @return string + */ + public function encodeHeader($str, $position = 'text') + { + $matchcount = 0; + switch (strtolower($position)) { + case 'phrase': + if (!preg_match('/[\200-\377]/', $str)) { + // Can't use addslashes as we don't know the value of magic_quotes_sybase + $encoded = addcslashes($str, "\0..\37\177\\\""); + if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { + return ($encoded); + } else { + return ("\"$encoded\""); + } + } + $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); + break; + /** @noinspection PhpMissingBreakStatementInspection */ + case 'comment': + $matchcount = preg_match_all('/[()"]/', $str, $matches); + // Intentional fall-through + case 'text': + default: + $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); + break; + } + + //There are no chars that need encoding + if ($matchcount == 0) { + return ($str); + } + + $maxlen = 75 - 7 - strlen($this->CharSet); + // Try to select the encoding which should produce the shortest output + if ($matchcount > strlen($str) / 3) { + // More than a third of the content will need encoding, so B encoding will be most efficient + $encoding = 'B'; + if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) { + // Use a custom function which correctly encodes and wraps long + // multibyte strings without breaking lines within a character + $encoded = $this->base64EncodeWrapMB($str, "\n"); + } else { + $encoded = base64_encode($str); + $maxlen -= $maxlen % 4; + $encoded = trim(chunk_split($encoded, $maxlen, "\n")); + } + } else { + $encoding = 'Q'; + $encoded = $this->encodeQ($str, $position); + $encoded = $this->wrapText($encoded, $maxlen, true); + $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded)); + } + + $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded); + $encoded = trim(str_replace("\n", $this->LE, $encoded)); + + return $encoded; + } + + /** + * Check if a string contains multi-byte characters. + * @access public + * @param string $str multi-byte text to wrap encode + * @return boolean + */ + public function hasMultiBytes($str) + { + if (function_exists('mb_strlen')) { + return (strlen($str) > mb_strlen($str, $this->CharSet)); + } else { // Assume no multibytes (we can't handle without mbstring functions anyway) + return false; + } + } + + /** + * Does a string contain any 8-bit chars (in any charset)? + * @param string $text + * @return boolean + */ + public function has8bitChars($text) + { + return (boolean)preg_match('/[\x80-\xFF]/', $text); + } + + /** + * Encode and wrap long multibyte strings for mail headers + * without breaking lines within a character. + * Adapted from a function by paravoid + * @link http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283 + * @access public + * @param string $str multi-byte text to wrap encode + * @param string $linebreak string to use as linefeed/end-of-line + * @return string + */ + public function base64EncodeWrapMB($str, $linebreak = null) + { + $start = '=?' . $this->CharSet . '?B?'; + $end = '?='; + $encoded = ''; + if ($linebreak === null) { + $linebreak = $this->LE; + } + + $mb_length = mb_strlen($str, $this->CharSet); + // Each line must have length <= 75, including $start and $end + $length = 75 - strlen($start) - strlen($end); + // Average multi-byte ratio + $ratio = $mb_length / strlen($str); + // Base64 has a 4:3 ratio + $avgLength = floor($length * $ratio * .75); + + for ($i = 0; $i < $mb_length; $i += $offset) { + $lookBack = 0; + do { + $offset = $avgLength - $lookBack; + $chunk = mb_substr($str, $i, $offset, $this->CharSet); + $chunk = base64_encode($chunk); + $lookBack++; + } while (strlen($chunk) > $length); + $encoded .= $chunk . $linebreak; + } + + // Chomp the last linefeed + $encoded = substr($encoded, 0, -strlen($linebreak)); + return $encoded; + } + + /** + * Encode a string in quoted-printable format. + * According to RFC2045 section 6.7. + * @access public + * @param string $string The text to encode + * @param integer $line_max Number of chars allowed on a line before wrapping + * @return string + * @link http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 Adapted from this comment + */ + public function encodeQP($string, $line_max = 76) + { + // Use native function if it's available (>= PHP5.3) + if (function_exists('quoted_printable_encode')) { + return quoted_printable_encode($string); + } + // Fall back to a pure PHP implementation + $string = str_replace( + array('%20', '%0D%0A.', '%0D%0A', '%'), + array(' ', "\r\n=2E", "\r\n", '='), + rawurlencode($string) + ); + return preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string); + } + + /** + * Backward compatibility wrapper for an old QP encoding function that was removed. + * @see PHPMailer::encodeQP() + * @access public + * @param string $string + * @param integer $line_max + * @param boolean $space_conv + * @return string + * @deprecated Use encodeQP instead. + */ + public function encodeQPphp( + $string, + $line_max = 76, + /** @noinspection PhpUnusedParameterInspection */ $space_conv = false + ) { + return $this->encodeQP($string, $line_max); + } + + /** + * Encode a string using Q encoding. + * @link http://tools.ietf.org/html/rfc2047 + * @param string $str the text to encode + * @param string $position Where the text is going to be used, see the RFC for what that means + * @access public + * @return string + */ + public function encodeQ($str, $position = 'text') + { + // There should not be any EOL in the string + $pattern = ''; + $encoded = str_replace(array("\r", "\n"), '', $str); + switch (strtolower($position)) { + case 'phrase': + // RFC 2047 section 5.3 + $pattern = '^A-Za-z0-9!*+\/ -'; + break; + /** @noinspection PhpMissingBreakStatementInspection */ + case 'comment': + // RFC 2047 section 5.2 + $pattern = '\(\)"'; + // intentional fall-through + // for this reason we build the $pattern without including delimiters and [] + case 'text': + default: + // RFC 2047 section 5.1 + // Replace every high ascii, control, =, ? and _ characters + $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern; + break; + } + $matches = array(); + if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) { + // If the string contains an '=', make sure it's the first thing we replace + // so as to avoid double-encoding + $eqkey = array_search('=', $matches[0]); + if (false !== $eqkey) { + unset($matches[0][$eqkey]); + array_unshift($matches[0], '='); + } + foreach (array_unique($matches[0]) as $char) { + $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded); + } + } + // Replace every spaces to _ (more readable than =20) + return str_replace(' ', '_', $encoded); + } + + + /** + * Add a string or binary attachment (non-filesystem). + * This method can be used to attach ascii or binary data, + * such as a BLOB record from a database. + * @param string $string String attachment data. + * @param string $filename Name of the attachment. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @param string $disposition Disposition to use + * @return void + */ + public function addStringAttachment( + $string, + $filename, + $encoding = 'base64', + $type = '', + $disposition = 'attachment' + ) { + // If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($filename); + } + // Append to $attachment array + $this->attachment[] = array( + 0 => $string, + 1 => $filename, + 2 => basename($filename), + 3 => $encoding, + 4 => $type, + 5 => true, // isStringAttachment + 6 => $disposition, + 7 => 0 + ); + } + + /** + * Add an embedded (inline) attachment from a file. + * This can include images, sounds, and just about any other document type. + * These differ from 'regular' attachments in that they are intended to be + * displayed inline with the message, not just attached for download. + * This is used in HTML messages that embed the images + * the HTML refers to using the $cid value. + * @param string $path Path to the attachment. + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File MIME type. + * @param string $disposition Disposition to use + * @return boolean True on successfully adding an attachment + */ + public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') + { + if (!@is_file($path)) { + $this->setError($this->lang('file_access') . $path); + return false; + } + + // If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($path); + } + + $filename = basename($path); + if ($name == '') { + $name = $filename; + } + + // Append to $attachment array + $this->attachment[] = array( + 0 => $path, + 1 => $filename, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => false, // isStringAttachment + 6 => $disposition, + 7 => $cid + ); + return true; + } + + /** + * Add an embedded stringified attachment. + * This can include images, sounds, and just about any other document type. + * Be sure to set the $type to an image type for images: + * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'. + * @param string $string The attachment binary data. + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML. + * @param string $name + * @param string $encoding File encoding (see $Encoding). + * @param string $type MIME type. + * @param string $disposition Disposition to use + * @return boolean True on successfully adding an attachment + */ + public function addStringEmbeddedImage( + $string, + $cid, + $name = '', + $encoding = 'base64', + $type = '', + $disposition = 'inline' + ) { + // If a MIME type is not specified, try to work it out from the name + if ($type == '' and !empty($name)) { + $type = self::filenameToType($name); + } + + // Append to $attachment array + $this->attachment[] = array( + 0 => $string, + 1 => $name, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => true, // isStringAttachment + 6 => $disposition, + 7 => $cid + ); + return true; + } + + /** + * Check if an inline attachment is present. + * @access public + * @return boolean + */ + public function inlineImageExists() + { + foreach ($this->attachment as $attachment) { + if ($attachment[6] == 'inline') { + return true; + } + } + return false; + } + + /** + * Check if an attachment (non-inline) is present. + * @return boolean + */ + public function attachmentExists() + { + foreach ($this->attachment as $attachment) { + if ($attachment[6] == 'attachment') { + return true; + } + } + return false; + } + + /** + * Check if this message has an alternative body set. + * @return boolean + */ + public function alternativeExists() + { + return !empty($this->AltBody); + } + + /** + * Clear all To recipients. + * @return void + */ + public function clearAddresses() + { + foreach ($this->to as $to) { + unset($this->all_recipients[strtolower($to[0])]); + } + $this->to = array(); + } + + /** + * Clear all CC recipients. + * @return void + */ + public function clearCCs() + { + foreach ($this->cc as $cc) { + unset($this->all_recipients[strtolower($cc[0])]); + } + $this->cc = array(); + } + + /** + * Clear all BCC recipients. + * @return void + */ + public function clearBCCs() + { + foreach ($this->bcc as $bcc) { + unset($this->all_recipients[strtolower($bcc[0])]); + } + $this->bcc = array(); + } + + /** + * Clear all ReplyTo recipients. + * @return void + */ + public function clearReplyTos() + { + $this->ReplyTo = array(); + } + + /** + * Clear all recipient types. + * @return void + */ + public function clearAllRecipients() + { + $this->to = array(); + $this->cc = array(); + $this->bcc = array(); + $this->all_recipients = array(); + } + + /** + * Clear all filesystem, string, and binary attachments. + * @return void + */ + public function clearAttachments() + { + $this->attachment = array(); + } + + /** + * Clear all custom headers. + * @return void + */ + public function clearCustomHeaders() + { + $this->CustomHeader = array(); + } + + /** + * Add an error message to the error container. + * @access protected + * @param string $msg + * @return void + */ + protected function setError($msg) + { + $this->error_count++; + if ($this->Mailer == 'smtp' and !is_null($this->smtp)) { + $lasterror = $this->smtp->getError(); + if (!empty($lasterror['error'])) { + $msg .= $this->lang('smtp_error') . $lasterror['error']; + if (!empty($lasterror['detail'])) { + $msg .= ' Detail: '. $lasterror['detail']; + } + if (!empty($lasterror['smtp_code'])) { + $msg .= ' SMTP code: ' . $lasterror['smtp_code']; + } + if (!empty($lasterror['smtp_code_ex'])) { + $msg .= ' Additional SMTP info: ' . $lasterror['smtp_code_ex']; + } + } + } + $this->ErrorInfo = $msg; + } + + /** + * Return an RFC 822 formatted date. + * @access public + * @return string + * @static + */ + public static function rfcDate() + { + // Set the time zone to whatever the default is to avoid 500 errors + // Will default to UTC if it's not set properly in php.ini + date_default_timezone_set(@date_default_timezone_get()); + return date('D, j M Y H:i:s O'); + } + + /** + * Get the server hostname. + * Returns 'localhost.localdomain' if unknown. + * @access protected + * @return string + */ + protected function serverHostname() + { + $result = 'localhost.localdomain'; + if (!empty($this->Hostname)) { + $result = $this->Hostname; + } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) { + $result = $_SERVER['SERVER_NAME']; + } elseif (function_exists('gethostname') && gethostname() !== false) { + $result = gethostname(); + } elseif (php_uname('n') !== false) { + $result = php_uname('n'); + } + return $result; + } + + /** + * Get an error message in the current language. + * @access protected + * @param string $key + * @return string + */ + protected function lang($key) + { + if (count($this->language) < 1) { + $this->language = array( + 'authenticate' => 'SMTP Error: Could not authenticate.', + 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', + 'data_not_accepted' => 'SMTP Error: data not accepted.', + 'empty_message' => 'Message body empty', + 'encoding' => 'Unknown encoding: ', + 'execute' => 'Could not execute: ', + 'file_access' => 'Could not access file: ', + 'file_open' => 'File Error: Could not open file: ', + 'from_failed' => 'The following From address failed: ', + 'instantiate' => 'Could not instantiate mail function.', + 'invalid_address' => 'Invalid address', + 'mailer_not_supported' => ' mailer is not supported.', + 'provide_address' => 'You must provide at least one recipient email address.', + 'recipients_failed' => 'SMTP Error: The following recipients failed: ', + 'signing' => 'Signing Error: ', + 'smtp_connect_failed' => 'SMTP connect() failed.', + 'smtp_error' => 'SMTP server error: ', + 'variable_set' => 'Cannot set or reset variable: ', + 'extension_missing' => 'Extension missing: ' + ); + } + + if (array_key_exists($key, $this->language)) { + if ($key == 'smtp_connect_failed') { + //Include a link to troubleshooting docs on SMTP connection failure + //this is by far the biggest cause of support questions + //but it's usually not PHPMailer's fault. + return $this->language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting'; + } + return $this->language[$key]; + } else { + //Return the key as a fallback + return $key; + } + } + + /** + * Check if an error occurred. + * @access public + * @return boolean True if an error did occur. + */ + public function isError() + { + return ($this->error_count > 0); + } + + /** + * Ensure consistent line endings in a string. + * Changes every end of line from CRLF, CR or LF to $this->LE. + * @access public + * @param string $str String to fixEOL + * @return string + */ + public function fixEOL($str) + { + // Normalise to \n + $nstr = str_replace(array("\r\n", "\r"), "\n", $str); + // Now convert LE as needed + if ($this->LE !== "\n") { + $nstr = str_replace("\n", $this->LE, $nstr); + } + return $nstr; + } + + /** + * Add a custom header. + * $name value can be overloaded to contain + * both header name and value (name:value) + * @access public + * @param string $name Custom header name + * @param string $value Header value + * @return void + */ + public function addCustomHeader($name, $value = null) + { + if ($value === null) { + // Value passed in as name:value + $this->CustomHeader[] = explode(':', $name, 2); + } else { + $this->CustomHeader[] = array($name, $value); + } + } + + /** + * Returns all custom headers + * + * @return array + */ + public function getCustomHeaders() + { + return $this->CustomHeader; + } + + /** + * Create a message from an HTML string. + * Automatically makes modifications for inline images and backgrounds + * and creates a plain-text version by converting the HTML. + * Overwrites any existing values in $this->Body and $this->AltBody + * @access public + * @param string $message HTML message string + * @param string $basedir baseline directory for path + * @param boolean|callable $advanced Whether to use the internal HTML to text converter + * or your own custom converter @see html2text() + * @return string $message + */ + public function msgHTML($message, $basedir = '', $advanced = false) + { + preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images); + if (isset($images[2])) { + foreach ($images[2] as $imgindex => $url) { + // Convert data URIs into embedded images + if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) { + $data = substr($url, strpos($url, ',')); + if ($match[2]) { + $data = base64_decode($data); + } else { + $data = rawurldecode($data); + } + $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 + if ($this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, 'base64', $match[1])) { + $message = str_replace( + $images[0][$imgindex], + $images[1][$imgindex] . '="cid:' . $cid . '"', + $message + ); + } + } elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[A-z]+://#', $url)) { + // Do not change urls for absolute images (thanks to corvuscorax) + // Do not change urls that are already inline images + $filename = basename($url); + $directory = dirname($url); + if ($directory == '.') { + $directory = ''; + } + $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 + if (strlen($basedir) > 1 && substr($basedir, -1) != '/') { + $basedir .= '/'; + } + if (strlen($directory) > 1 && substr($directory, -1) != '/') { + $directory .= '/'; + } + if ($this->addEmbeddedImage( + $basedir . $directory . $filename, + $cid, + $filename, + 'base64', + self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION)) + ) + ) { + $message = preg_replace( + '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui', + $images[1][$imgindex] . '="cid:' . $cid . '"', + $message + ); + } + } + } + } + $this->isHTML(true); + // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better + $this->Body = $this->normalizeBreaks($message); + $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced)); + if (empty($this->AltBody)) { + $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . + self::CRLF . self::CRLF; + } + return $this->Body; + } + + /** + * Convert an HTML string into plain text. + * This is used by msgHTML(). + * Note - older versions of this function used a bundled advanced converter + * which was been removed for license reasons in #232 + * Example usage: + * + * // Use default conversion + * $plain = $mail->html2text($html); + * // Use your own custom converter + * $plain = $mail->html2text($html, function($html) { + * $converter = new MyHtml2text($html); + * return $converter->get_text(); + * }); + * + * @param string $html The HTML text to convert + * @param boolean|callable $advanced Any boolean value to use the internal converter, + * or provide your own callable for custom conversion. + * @return string + */ + public function html2text($html, $advanced = false) + { + if (is_callable($advanced)) { + return call_user_func($advanced, $html); + } + return html_entity_decode( + trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), + ENT_QUOTES, + $this->CharSet + ); + } + + /** + * Get the MIME type for a file extension. + * @param string $ext File extension + * @access public + * @return string MIME type of file. + * @static + */ + public static function _mime_types($ext = '') + { + $mimes = array( + 'xl' => 'application/excel', + 'js' => 'application/javascript', + 'hqx' => 'application/mac-binhex40', + 'cpt' => 'application/mac-compactpro', + 'bin' => 'application/macbinary', + 'doc' => 'application/msword', + 'word' => 'application/msword', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'class' => 'application/octet-stream', + 'dll' => 'application/octet-stream', + 'dms' => 'application/octet-stream', + 'exe' => 'application/octet-stream', + 'lha' => 'application/octet-stream', + 'lzh' => 'application/octet-stream', + 'psd' => 'application/octet-stream', + 'sea' => 'application/octet-stream', + 'so' => 'application/octet-stream', + 'oda' => 'application/oda', + 'pdf' => 'application/pdf', + 'ai' => 'application/postscript', + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'mif' => 'application/vnd.mif', + 'xls' => 'application/vnd.ms-excel', + 'ppt' => 'application/vnd.ms-powerpoint', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'gtar' => 'application/x-gtar', + 'php3' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'php' => 'application/x-httpd-php', + 'phtml' => 'application/x-httpd-php', + 'phps' => 'application/x-httpd-php-source', + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/x-stuffit', + 'tar' => 'application/x-tar', + 'tgz' => 'application/x-tar', + 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', + 'zip' => 'application/zip', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mp2' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mpga' => 'audio/mpeg', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'ram' => 'audio/x-pn-realaudio', + 'rm' => 'audio/x-pn-realaudio', + 'rpm' => 'audio/x-pn-realaudio-plugin', + 'ra' => 'audio/x-realaudio', + 'wav' => 'audio/x-wav', + 'bmp' => 'image/bmp', + 'gif' => 'image/gif', + 'jpeg' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'png' => 'image/png', + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'eml' => 'message/rfc822', + 'css' => 'text/css', + 'html' => 'text/html', + 'htm' => 'text/html', + 'shtml' => 'text/html', + 'log' => 'text/plain', + 'text' => 'text/plain', + 'txt' => 'text/plain', + 'rtx' => 'text/richtext', + 'rtf' => 'text/rtf', + 'vcf' => 'text/vcard', + 'vcard' => 'text/vcard', + 'xml' => 'text/xml', + 'xsl' => 'text/xml', + 'mpeg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mov' => 'video/quicktime', + 'qt' => 'video/quicktime', + 'rv' => 'video/vnd.rn-realvideo', + 'avi' => 'video/x-msvideo', + 'movie' => 'video/x-sgi-movie' + ); + if (array_key_exists(strtolower($ext), $mimes)) { + return $mimes[strtolower($ext)]; + } + return 'application/octet-stream'; + } + + /** + * Map a file name to a MIME type. + * Defaults to 'application/octet-stream', i.e.. arbitrary binary data. + * @param string $filename A file name or full path, does not need to exist as a file + * @return string + * @static + */ + public static function filenameToType($filename) + { + // In case the path is a URL, strip any query string before getting extension + $qpos = strpos($filename, '?'); + if (false !== $qpos) { + $filename = substr($filename, 0, $qpos); + } + $pathinfo = self::mb_pathinfo($filename); + return self::_mime_types($pathinfo['extension']); + } + + /** + * Multi-byte-safe pathinfo replacement. + * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe. + * Works similarly to the one in PHP >= 5.2.0 + * @link http://www.php.net/manual/en/function.pathinfo.php#107461 + * @param string $path A filename or path, does not need to exist as a file + * @param integer|string $options Either a PATHINFO_* constant, + * or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2 + * @return string|array + * @static + */ + public static function mb_pathinfo($path, $options = null) + { + $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''); + $pathinfo = array(); + if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) { + if (array_key_exists(1, $pathinfo)) { + $ret['dirname'] = $pathinfo[1]; + } + if (array_key_exists(2, $pathinfo)) { + $ret['basename'] = $pathinfo[2]; + } + if (array_key_exists(5, $pathinfo)) { + $ret['extension'] = $pathinfo[5]; + } + if (array_key_exists(3, $pathinfo)) { + $ret['filename'] = $pathinfo[3]; + } + } + switch ($options) { + case PATHINFO_DIRNAME: + case 'dirname': + return $ret['dirname']; + case PATHINFO_BASENAME: + case 'basename': + return $ret['basename']; + case PATHINFO_EXTENSION: + case 'extension': + return $ret['extension']; + case PATHINFO_FILENAME: + case 'filename': + return $ret['filename']; + default: + return $ret; + } + } + + /** + * Set or reset instance properties. + * You should avoid this function - it's more verbose, less efficient, more error-prone and + * harder to debug than setting properties directly. + * Usage Example: + * `$mail->set('SMTPSecure', 'tls');` + * is the same as: + * `$mail->SMTPSecure = 'tls';` + * @access public + * @param string $name The property name to set + * @param mixed $value The value to set the property to + * @return boolean + * @TODO Should this not be using the __set() magic function? + */ + public function set($name, $value = '') + { + if (property_exists($this, $name)) { + $this->$name = $value; + return true; + } else { + $this->setError($this->lang('variable_set') . $name); + return false; + } + } + + /** + * Strip newlines to prevent header injection. + * @access public + * @param string $str + * @return string + */ + public function secureHeader($str) + { + return trim(str_replace(array("\r", "\n"), '', $str)); + } + + /** + * Normalize line breaks in a string. + * Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format. + * Defaults to CRLF (for message bodies) and preserves consecutive breaks. + * @param string $text + * @param string $breaktype What kind of line break to use, defaults to CRLF + * @return string + * @access public + * @static + */ + public static function normalizeBreaks($text, $breaktype = "\r\n") + { + return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text); + } + + + /** + * Set the public and private key files and password for S/MIME signing. + * @access public + * @param string $cert_filename + * @param string $key_filename + * @param string $key_pass Password for private key + * @param string $extracerts_filename Optional path to chain certificate + */ + public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '') + { + $this->sign_cert_file = $cert_filename; + $this->sign_key_file = $key_filename; + $this->sign_key_pass = $key_pass; + $this->sign_extracerts_file = $extracerts_filename; + } + + /** + * Quoted-Printable-encode a DKIM header. + * @access public + * @param string $txt + * @return string + */ + public function DKIM_QP($txt) + { + $line = ''; + for ($i = 0; $i < strlen($txt); $i++) { + $ord = ord($txt[$i]); + if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) { + $line .= $txt[$i]; + } else { + $line .= '=' . sprintf('%02X', $ord); + } + } + return $line; + } + + /** + * Generate a DKIM signature. + * @access public + * @param string $signHeader + * @throws phpmailerException + * @return string + */ + public function DKIM_Sign($signHeader) + { + if (!defined('PKCS7_TEXT')) { + if ($this->exceptions) { + throw new phpmailerException($this->lang('extension_missing') . 'openssl'); + } + return ''; + } + $privKeyStr = file_get_contents($this->DKIM_private); + if ($this->DKIM_passphrase != '') { + $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); + } else { + $privKey = $privKeyStr; + } + if (openssl_sign($signHeader, $signature, $privKey)) { + return base64_encode($signature); + } + return ''; + } + + /** + * Generate a DKIM canonicalization header. + * @access public + * @param string $signHeader Header + * @return string + */ + public function DKIM_HeaderC($signHeader) + { + $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader); + $lines = explode("\r\n", $signHeader); + foreach ($lines as $key => $line) { + list($heading, $value) = explode(':', $line, 2); + $heading = strtolower($heading); + $value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces + $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value + } + $signHeader = implode("\r\n", $lines); + return $signHeader; + } + + /** + * Generate a DKIM canonicalization body. + * @access public + * @param string $body Message Body + * @return string + */ + public function DKIM_BodyC($body) + { + if ($body == '') { + return "\r\n"; + } + // stabilize line endings + $body = str_replace("\r\n", "\n", $body); + $body = str_replace("\n", "\r\n", $body); + // END stabilize line endings + while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") { + $body = substr($body, 0, strlen($body) - 2); + } + return $body; + } + + /** + * Create the DKIM header and body in a new message header. + * @access public + * @param string $headers_line Header lines + * @param string $subject Subject + * @param string $body Body + * @return string + */ + public function DKIM_Add($headers_line, $subject, $body) + { + $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms + $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body + $DKIMquery = 'dns/txt'; // Query method + $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) + $subject_header = "Subject: $subject"; + $headers = explode($this->LE, $headers_line); + $from_header = ''; + $to_header = ''; + $current = ''; + foreach ($headers as $header) { + if (strpos($header, 'From:') === 0) { + $from_header = $header; + $current = 'from_header'; + } elseif (strpos($header, 'To:') === 0) { + $to_header = $header; + $current = 'to_header'; + } else { + if (!empty($$current) && strpos($header, ' =?') === 0) { + $$current .= $header; + } else { + $current = ''; + } + } + } + $from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); + $to = str_replace('|', '=7C', $this->DKIM_QP($to_header)); + $subject = str_replace( + '|', + '=7C', + $this->DKIM_QP($subject_header) + ); // Copied header fields (dkim-quoted-printable) + $body = $this->DKIM_BodyC($body); + $DKIMlen = strlen($body); // Length of body + $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body + if ('' == $this->DKIM_identity) { + $ident = ''; + } else { + $ident = ' i=' . $this->DKIM_identity . ';'; + } + $dkimhdrs = 'DKIM-Signature: v=1; a=' . + $DKIMsignatureType . '; q=' . + $DKIMquery . '; l=' . + $DKIMlen . '; s=' . + $this->DKIM_selector . + ";\r\n" . + "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" . + "\th=From:To:Subject;\r\n" . + "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" . + "\tz=$from\r\n" . + "\t|$to\r\n" . + "\t|$subject;\r\n" . + "\tbh=" . $DKIMb64 . ";\r\n" . + "\tb="; + $toSign = $this->DKIM_HeaderC( + $from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs + ); + $signed = $this->DKIM_Sign($toSign); + return $dkimhdrs . $signed . "\r\n"; + } + + /** + * Detect if a string contains a line longer than the maximum line length allowed. + * @param string $str + * @return boolean + * @static + */ + public static function hasLineLongerThanMax($str) + { + //+2 to include CRLF line break for a 1000 total + return (boolean)preg_match('/^(.{'.(self::MAX_LINE_LENGTH + 2).',})/m', $str); + } + + /** + * Allows for public read access to 'to' property. + * @access public + * @return array + */ + public function getToAddresses() + { + return $this->to; + } + + /** + * Allows for public read access to 'cc' property. + * @access public + * @return array + */ + public function getCcAddresses() + { + return $this->cc; + } + + /** + * Allows for public read access to 'bcc' property. + * @access public + * @return array + */ + public function getBccAddresses() + { + return $this->bcc; + } + + /** + * Allows for public read access to 'ReplyTo' property. + * @access public + * @return array + */ + public function getReplyToAddresses() + { + return $this->ReplyTo; + } + + /** + * Allows for public read access to 'all_recipients' property. + * @access public + * @return array + */ + public function getAllRecipientAddresses() + { + return $this->all_recipients; + } + + /** + * Perform a callback. + * @param boolean $isSent + * @param array $to + * @param array $cc + * @param array $bcc + * @param string $subject + * @param string $body + * @param string $from + */ + protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from) + { + if (!empty($this->action_function) && is_callable($this->action_function)) { + $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from); + call_user_func_array($this->action_function, $params); + } + } +} + +/** + * PHPMailer exception handler + * @package PHPMailer + */ +class phpmailerException extends \Exception +{ + /** + * Prettify error message output + * @return string + */ + public function errorMessage() + { + $errorMsg = '' . $this->getMessage() . "
    \n"; + return $errorMsg; + } +} diff --git a/zira/phpmailer/smtp.php b/zira/phpmailer/smtp.php new file mode 100644 index 0000000..8185a66 --- /dev/null +++ b/zira/phpmailer/smtp.php @@ -0,0 +1,1110 @@ + + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2014 Marcus Bointon + * @copyright 2010 - 2012 Jim Jagielski + * @copyright 2004 - 2009 Andy Prevost + * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** + * PHPMailer RFC821 SMTP email transport class. + * Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server. + * @package PHPMailer + * @author Chris Ryan + * @author Marcus Bointon + */ + +namespace Zira\Phpmailer; + +class Smtp +{ + /** + * The PHPMailer SMTP version number. + * @type string + */ + const VERSION = '5.2.12'; + + /** + * SMTP line break constant. + * @type string + */ + const CRLF = "\r\n"; + + /** + * The SMTP port to use if one is not specified. + * @type integer + */ + const DEFAULT_SMTP_PORT = 25; + + /** + * The maximum line length allowed by RFC 2822 section 2.1.1 + * @type integer + */ + const MAX_LINE_LENGTH = 998; + + /** + * Debug level for no output + */ + const DEBUG_OFF = 0; + + /** + * Debug level to show client -> server messages + */ + const DEBUG_CLIENT = 1; + + /** + * Debug level to show client -> server and server -> client messages + */ + const DEBUG_SERVER = 2; + + /** + * Debug level to show connection status, client -> server and server -> client messages + */ + const DEBUG_CONNECTION = 3; + + /** + * Debug level to show all messages + */ + const DEBUG_LOWLEVEL = 4; + + /** + * The PHPMailer SMTP Version number. + * @type string + * @deprecated Use the `VERSION` constant instead + * @see SMTP::VERSION + */ + public $Version = '5.2.12'; + + /** + * SMTP server port number. + * @type integer + * @deprecated This is only ever used as a default value, so use the `DEFAULT_SMTP_PORT` constant instead + * @see SMTP::DEFAULT_SMTP_PORT + */ + public $SMTP_PORT = 25; + + /** + * SMTP reply line ending. + * @type string + * @deprecated Use the `CRLF` constant instead + * @see SMTP::CRLF + */ + public $CRLF = "\r\n"; + + /** + * Debug output level. + * Options: + * * self::DEBUG_OFF (`0`) No debug output, default + * * self::DEBUG_CLIENT (`1`) Client commands + * * self::DEBUG_SERVER (`2`) Client commands and server responses + * * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status + * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages + * @type integer + */ + public $do_debug = self::DEBUG_OFF; + + /** + * How to handle debug output. + * Options: + * * `echo` Output plain-text as-is, appropriate for CLI + * * `html` Output escaped, line breaks converted to `
    `, appropriate for browser output + * * `error_log` Output to error log as configured in php.ini + * + * Alternatively, you can provide a callable expecting two params: a message string and the debug level: + * + * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; + * + * @type string|callable + */ + public $Debugoutput = 'echo'; + + /** + * Whether to use VERP. + * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path + * @link http://www.postfix.org/VERP_README.html Info on VERP + * @type boolean + */ + public $do_verp = false; + + /** + * The timeout value for connection, in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure. + * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2 + * @type integer + */ + public $Timeout = 300; + + /** + * How long to wait for commands to complete, in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * @type integer + */ + public $Timelimit = 300; + + /** + * The socket for the server connection. + * @type resource + */ + protected $smtp_conn; + + /** + * Error information, if any, for the last SMTP command. + * @type array + */ + protected $error = array( + 'error' => '', + 'detail' => '', + 'smtp_code' => '', + 'smtp_code_ex' => '' + ); + + /** + * The reply the server sent to us for HELO. + * If null, no HELO string has yet been received. + * @type string|null + */ + protected $helo_rply = null; + + /** + * The set of SMTP extensions sent in reply to EHLO command. + * Indexes of the array are extension names. + * Value at index 'HELO' or 'EHLO' (according to command that was sent) + * represents the server name. In case of HELO it is the only element of the array. + * Other values can be boolean TRUE or an array containing extension options. + * If null, no HELO/EHLO string has yet been received. + * @type array|null + */ + protected $server_caps = null; + + /** + * The most recent reply received from the server. + * @type string + */ + protected $last_reply = ''; + + /** + * Output debugging info via a user-selected method. + * @see SMTP::$Debugoutput + * @see SMTP::$do_debug + * @param string $str Debug string to output + * @param integer $level The debug level of this message; see DEBUG_* constants + * @return void + */ + protected function edebug($str, $level = 0) + { + if ($level > $this->do_debug) { + return; + } + //Avoid clash with built-in function names + if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) { + call_user_func($this->Debugoutput, $str, $this->do_debug); + return; + } + switch ($this->Debugoutput) { + case 'error_log': + //Don't output, just log + error_log($str); + break; + case 'html': + //Cleans up output a bit for a better looking, HTML-safe output + echo htmlentities( + preg_replace('/[\r\n]+/', '', $str), + ENT_QUOTES, + 'UTF-8' + ) + . "
    \n"; + break; + case 'echo': + default: + //Normalize line breaks + $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str); + echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( + "\n", + "\n \t ", + trim($str) + )."\n"; + } + } + + /** + * Connect to an SMTP server. + * @param string $host SMTP server IP or host name + * @param integer $port The port number to connect to + * @param integer $timeout How long to wait for the connection to open + * @param array $options An array of options for stream_context_create() + * @access public + * @return boolean + */ + public function connect($host, $port = null, $timeout = 30, $options = array()) + { + static $streamok; + //This is enabled by default since 5.0.0 but some providers disable it + //Check this once and cache the result + if (is_null($streamok)) { + $streamok = function_exists('stream_socket_client'); + } + // Clear errors to avoid confusion + $this->setError(''); + // Make sure we are __not__ connected + if ($this->connected()) { + // Already connected, generate error + $this->setError('Already connected to a server'); + return false; + } + if (empty($port)) { + $port = self::DEFAULT_SMTP_PORT; + } + // Connect to the SMTP server + $this->edebug( + "Connection: opening to $host:$port, timeout=$timeout, options=".var_export($options, true), + self::DEBUG_CONNECTION + ); + $errno = 0; + $errstr = ''; + if ($streamok) { + $socket_context = stream_context_create($options); + //Suppress errors; connection failures are handled at a higher level + $this->smtp_conn = @stream_socket_client( + $host . ":" . $port, + $errno, + $errstr, + $timeout, + STREAM_CLIENT_CONNECT, + $socket_context + ); + } else { + //Fall back to fsockopen which should work in more places, but is missing some features + $this->edebug( + "Connection: stream_socket_client not available, falling back to fsockopen", + self::DEBUG_CONNECTION + ); + $this->smtp_conn = fsockopen( + $host, + $port, + $errno, + $errstr, + $timeout + ); + } + // Verify we connected properly + if (!is_resource($this->smtp_conn)) { + $this->setError( + 'Failed to connect to server', + $errno, + $errstr + ); + $this->edebug( + 'SMTP ERROR: ' . $this->error['error'] + . ": $errstr ($errno)", + self::DEBUG_CLIENT + ); + return false; + } + $this->edebug('Connection: opened', self::DEBUG_CONNECTION); + // SMTP server can take longer to respond, give longer timeout for first read + // Windows does not have support for this timeout function + if (substr(PHP_OS, 0, 3) != 'WIN') { + $max = ini_get('max_execution_time'); + // Don't bother if unlimited + if ($max != 0 && $timeout > $max) { + @set_time_limit($timeout); + } + stream_set_timeout($this->smtp_conn, $timeout, 0); + } + // Get any announcement + $announce = $this->get_lines(); + $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER); + return true; + } + + /** + * Initiate a TLS (encrypted) session. + * @access public + * @return boolean + */ + public function startTLS() + { + if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) { + return false; + } + // Begin encrypted connection + if (!stream_socket_enable_crypto( + $this->smtp_conn, + true, + STREAM_CRYPTO_METHOD_TLS_CLIENT + )) { + return false; + } + return true; + } + + /** + * Perform SMTP authentication. + * Must be run after hello(). + * @see hello() + * @param string $username The user name + * @param string $password The password + * @param string $authtype The auth type (PLAIN, LOGIN, CRAM-MD5) + * @return bool True if successfully authenticated.* @access public + */ + public function authenticate( + $username, + $password, + $authtype = null + ) { + if (!$this->server_caps) { + $this->setError('Authentication is not allowed before HELO/EHLO'); + return false; + } + + if (array_key_exists('EHLO', $this->server_caps)) { + // SMTP extensions are available. Let's try to find a proper authentication method + + if (!array_key_exists('AUTH', $this->server_caps)) { + $this->setError('Authentication is not allowed at this stage'); + // 'at this stage' means that auth may be allowed after the stage changes + // e.g. after STARTTLS + return false; + } + + self::edebug('Auth method requested: ' . ($authtype ? $authtype : 'UNKNOWN'), self::DEBUG_LOWLEVEL); + self::edebug( + 'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']), + self::DEBUG_LOWLEVEL + ); + + if (empty($authtype)) { + foreach (array('LOGIN', 'CRAM-MD5', 'NTLM', 'PLAIN', 'XOAUTH2') as $method) { + if (in_array($method, $this->server_caps['AUTH'])) { + $authtype = $method; + break; + } + } + if (empty($authtype)) { + $this->setError('No supported authentication methods found'); + return false; + } + self::edebug('Auth method selected: '.$authtype, self::DEBUG_LOWLEVEL); + } + + if (!in_array($authtype, $this->server_caps['AUTH'])) { + $this->setError("The requested authentication method \"$authtype\" is not supported by the server"); + return false; + } + } elseif (empty($authtype)) { + $authtype = 'LOGIN'; + } + switch ($authtype) { + case 'PLAIN': + // Start authentication + if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) { + return false; + } + // Send encoded username and password + if (!$this->sendCommand( + 'User & Password', + base64_encode("\0" . $username . "\0" . $password), + 235 + ) + ) { + return false; + } + break; + case 'LOGIN': + // Start authentication + if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) { + return false; + } + if (!$this->sendCommand("Username", base64_encode($username), 334)) { + return false; + } + if (!$this->sendCommand("Password", base64_encode($password), 235)) { + return false; + } + break; + case 'CRAM-MD5': + // Start authentication + if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) { + return false; + } + // Get the challenge + $challenge = base64_decode(substr($this->last_reply, 4)); + + // Build the response + $response = $username . ' ' . $this->hmac($challenge, $password); + + // send encoded credentials + return $this->sendCommand('Username', base64_encode($response), 235); + default: + $this->setError("Authentication method \"$authtype\" is not supported"); + return false; + } + return true; + } + + /** + * Calculate an MD5 HMAC hash. + * Works like hash_hmac('md5', $data, $key) + * in case that function is not available + * @param string $data The data to hash + * @param string $key The key to hash with + * @access protected + * @return string + */ + protected function hmac($data, $key) + { + if (function_exists('hash_hmac')) { + return hash_hmac('md5', $data, $key); + } + + // The following borrowed from + // http://php.net/manual/en/function.mhash.php#27225 + + // RFC 2104 HMAC implementation for php. + // Creates an md5 HMAC. + // Eliminates the need to install mhash to compute a HMAC + // by Lance Rushing + + $bytelen = 64; // byte length for md5 + if (strlen($key) > $bytelen) { + $key = pack('H*', md5($key)); + } + $key = str_pad($key, $bytelen, chr(0x00)); + $ipad = str_pad('', $bytelen, chr(0x36)); + $opad = str_pad('', $bytelen, chr(0x5c)); + $k_ipad = $key ^ $ipad; + $k_opad = $key ^ $opad; + + return md5($k_opad . pack('H*', md5($k_ipad . $data))); + } + + /** + * Check connection state. + * @access public + * @return boolean True if connected. + */ + public function connected() + { + if (is_resource($this->smtp_conn)) { + $sock_status = stream_get_meta_data($this->smtp_conn); + if ($sock_status['eof']) { + // The socket is valid but we are not connected + $this->edebug( + 'SMTP NOTICE: EOF caught while checking if connected', + self::DEBUG_CLIENT + ); + $this->close(); + return false; + } + return true; // everything looks good + } + return false; + } + + /** + * Close the socket and clean up the state of the class. + * Don't use this function without first trying to use QUIT. + * @see quit() + * @access public + * @return void + */ + public function close() + { + $this->setError(''); + $this->server_caps = null; + $this->helo_rply = null; + if (is_resource($this->smtp_conn)) { + // close the connection and cleanup + fclose($this->smtp_conn); + $this->smtp_conn = null; //Makes for cleaner serialization + $this->edebug('Connection: closed', self::DEBUG_CONNECTION); + } + } + + /** + * Send an SMTP DATA command. + * Issues a data command and sends the msg_data to the server, + * finializing the mail transaction. $msg_data is the message + * that is to be send with the headers. Each header needs to be + * on a single line followed by a with the message headers + * and the message body being separated by and additional . + * Implements rfc 821: DATA + * @param string $msg_data Message data to send + * @access public + * @return boolean + */ + public function data($msg_data) + { + //This will use the standard timelimit + if (!$this->sendCommand('DATA', 'DATA', 354)) { + return false; + } + + /* The server is ready to accept data! + * According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF) + * so we will break the data up into lines by \r and/or \n then if needed we will break each of those into + * smaller lines to fit within the limit. + * We will also look for lines that start with a '.' and prepend an additional '.'. + * NOTE: this does not count towards line-length limit. + */ + + // Normalize line breaks before exploding + $lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data)); + + /* To distinguish between a complete RFC822 message and a plain message body, we check if the first field + * of the first line (':' separated) does not contain a space then it _should_ be a header and we will + * process all lines before a blank line as headers. + */ + + $field = substr($lines[0], 0, strpos($lines[0], ':')); + $in_headers = false; + if (!empty($field) && strpos($field, ' ') === false) { + $in_headers = true; + } + + foreach ($lines as $line) { + $lines_out = array(); + if ($in_headers and $line == '') { + $in_headers = false; + } + //Break this line up into several smaller lines if it's too long + //Micro-optimisation: isset($str[$len]) is faster than (strlen($str) > $len), + while (isset($line[self::MAX_LINE_LENGTH])) { + //Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on + //so as to avoid breaking in the middle of a word + $pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' '); + //Deliberately matches both false and 0 + if (!$pos) { + //No nice break found, add a hard break + $pos = self::MAX_LINE_LENGTH - 1; + $lines_out[] = substr($line, 0, $pos); + $line = substr($line, $pos); + } else { + //Break at the found point + $lines_out[] = substr($line, 0, $pos); + //Move along by the amount we dealt with + $line = substr($line, $pos + 1); + } + //If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1 + if ($in_headers) { + $line = "\t" . $line; + } + } + $lines_out[] = $line; + + //Send the lines to the server + foreach ($lines_out as $line_out) { + //RFC2821 section 4.5.2 + if (!empty($line_out) and $line_out[0] == '.') { + $line_out = '.' . $line_out; + } + $this->client_send($line_out . self::CRLF); + } + } + + //Message data has been sent, complete the command + //Increase timelimit for end of DATA command + $savetimelimit = $this->Timelimit; + $this->Timelimit = $this->Timelimit * 2; + $result = $this->sendCommand('DATA END', '.', 250); + //Restore timelimit + $this->Timelimit = $savetimelimit; + return $result; + } + + /** + * Send an SMTP HELO or EHLO command. + * Used to identify the sending server to the receiving server. + * This makes sure that client and server are in a known state. + * Implements RFC 821: HELO + * and RFC 2821 EHLO. + * @param string $host The host name or IP to connect to + * @access public + * @return boolean + */ + public function hello($host = '') + { + //Try extended hello first (RFC 2821) + return (boolean)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host)); + } + + /** + * Send an SMTP HELO or EHLO command. + * Low-level implementation used by hello() + * @see hello() + * @param string $hello The HELO string + * @param string $host The hostname to say we are + * @access protected + * @return boolean + */ + protected function sendHello($hello, $host) + { + $noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250); + $this->helo_rply = $this->last_reply; + if ($noerror) { + $this->parseHelloFields($hello); + } else { + $this->server_caps = null; + } + return $noerror; + } + + /** + * Parse a reply to HELO/EHLO command to discover server extensions. + * In case of HELO, the only parameter that can be discovered is a server name. + * @access protected + * @param string $type - 'HELO' or 'EHLO' + */ + protected function parseHelloFields($type) + { + $this->server_caps = array(); + $lines = explode("\n", $this->last_reply); + + foreach ($lines as $n => $s) { + //First 4 chars contain response code followed by - or space + $s = trim(substr($s, 4)); + if (empty($s)) { + continue; + } + $fields = explode(' ', $s); + if (!empty($fields)) { + if (!$n) { + $name = $type; + $fields = $fields[0]; + } else { + $name = array_shift($fields); + switch ($name) { + case 'SIZE': + $fields = ($fields ? $fields[0] : 0); + break; + case 'AUTH': + if (!is_array($fields)) { + $fields = array(); + } + break; + default: + $fields = true; + } + } + $this->server_caps[$name] = $fields; + } + } + } + + /** + * Send an SMTP MAIL command. + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more recipient + * commands may be called followed by a data command. + * Implements rfc 821: MAIL FROM: + * @param string $from Source address of this message + * @access public + * @return boolean + */ + public function mail($from) + { + $useVerp = ($this->do_verp ? ' XVERP' : ''); + return $this->sendCommand( + 'MAIL FROM', + 'MAIL FROM:<' . $from . '>' . $useVerp, + 250 + ); + } + + /** + * Send an SMTP QUIT command. + * Closes the socket if there is no error or the $close_on_error argument is true. + * Implements from rfc 821: QUIT + * @param boolean $close_on_error Should the connection close if an error occurs? + * @access public + * @return boolean + */ + public function quit($close_on_error = true) + { + $noerror = $this->sendCommand('QUIT', 'QUIT', 221); + $err = $this->error; //Save any error + if ($noerror or $close_on_error) { + $this->close(); + $this->error = $err; //Restore any error from the quit command + } + return $noerror; + } + + /** + * Send an SMTP RCPT command. + * Sets the TO argument to $toaddr. + * Returns true if the recipient was accepted false if it was rejected. + * Implements from rfc 821: RCPT TO: + * @param string $toaddr The address the message is being sent to + * @access public + * @return boolean + */ + public function recipient($toaddr) + { + return $this->sendCommand( + 'RCPT TO', + 'RCPT TO:<' . $toaddr . '>', + array(250, 251) + ); + } + + /** + * Send an SMTP RSET command. + * Abort any transaction that is currently in progress. + * Implements rfc 821: RSET + * @access public + * @return boolean True on success. + */ + public function reset() + { + return $this->sendCommand('RSET', 'RSET', 250); + } + + /** + * Send a command to an SMTP server and check its return code. + * @param string $command The command name - not sent to the server + * @param string $commandstring The actual command to send + * @param integer|array $expect One or more expected integer success codes + * @access protected + * @return boolean True on success. + */ + protected function sendCommand($command, $commandstring, $expect) + { + if (!$this->connected()) { + $this->setError("Called $command without being connected"); + return false; + } + $this->client_send($commandstring . self::CRLF); + + $this->last_reply = $this->get_lines(); + // Fetch SMTP code and possible error code explanation + $matches = array(); + if (preg_match("/^([0-9]{3})[ -](?:([0-9]\\.[0-9]\\.[0-9]) )?/", $this->last_reply, $matches)) { + $code = $matches[1]; + $code_ex = (count($matches) > 2 ? $matches[2] : null); + // Cut off error code from each response line + $detail = preg_replace( + "/{$code}[ -]".($code_ex ? str_replace('.', '\\.', $code_ex).' ' : '')."/m", + '', + $this->last_reply + ); + } else { + // Fall back to simple parsing if regex fails + $code = substr($this->last_reply, 0, 3); + $code_ex = null; + $detail = substr($this->last_reply, 4); + } + + $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER); + + if (!in_array($code, (array)$expect)) { + $this->setError( + "$command command failed", + $detail, + $code, + $code_ex + ); + $this->edebug( + 'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply, + self::DEBUG_CLIENT + ); + return false; + } + + $this->setError(''); + return true; + } + + /** + * Send an SMTP SAML command. + * Starts a mail transaction from the email address specified in $from. + * Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more recipient + * commands may be called followed by a data command. This command + * will send the message to the users terminal if they are logged + * in and send them an email. + * Implements rfc 821: SAML FROM: + * @param string $from The address the message is from + * @access public + * @return boolean + */ + public function sendAndMail($from) + { + return $this->sendCommand('SAML', "SAML FROM:$from", 250); + } + + /** + * Send an SMTP VRFY command. + * @param string $name The name to verify + * @access public + * @return boolean + */ + public function verify($name) + { + return $this->sendCommand('VRFY', "VRFY $name", array(250, 251)); + } + + /** + * Send an SMTP NOOP command. + * Used to keep keep-alives alive, doesn't actually do anything + * @access public + * @return boolean + */ + public function noop() + { + return $this->sendCommand('NOOP', 'NOOP', 250); + } + + /** + * Send an SMTP TURN command. + * This is an optional command for SMTP that this class does not support. + * This method is here to make the RFC821 Definition complete for this class + * and _may_ be implemented in future + * Implements from rfc 821: TURN + * @access public + * @return boolean + */ + public function turn() + { + $this->setError('The SMTP TURN command is not implemented'); + $this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT); + return false; + } + + /** + * Send raw data to the server. + * @param string $data The data to send + * @access public + * @return integer|boolean The number of bytes sent to the server or false on error + */ + public function client_send($data) + { + $this->edebug("CLIENT -> SERVER: $data", self::DEBUG_CLIENT); + return fwrite($this->smtp_conn, $data); + } + + /** + * Get the latest error. + * @access public + * @return array + */ + public function getError() + { + return $this->error; + } + + /** + * Get SMTP extensions available on the server + * @access public + * @return array|null + */ + public function getServerExtList() + { + return $this->server_caps; + } + + /** + * A multipurpose method + * The method works in three ways, dependent on argument value and current state + * 1. HELO/EHLO was not sent - returns null and set up $this->error + * 2. HELO was sent + * $name = 'HELO': returns server name + * $name = 'EHLO': returns boolean false + * $name = any string: returns null and set up $this->error + * 3. EHLO was sent + * $name = 'HELO'|'EHLO': returns server name + * $name = any string: if extension $name exists, returns boolean True + * or its options. Otherwise returns boolean False + * In other words, one can use this method to detect 3 conditions: + * - null returned: handshake was not or we don't know about ext (refer to $this->error) + * - false returned: the requested feature exactly not exists + * - positive value returned: the requested feature exists + * @param string $name Name of SMTP extension or 'HELO'|'EHLO' + * @return mixed + */ + public function getServerExt($name) + { + if (!$this->server_caps) { + $this->setError('No HELO/EHLO was sent'); + return null; + } + + // the tight logic knot ;) + if (!array_key_exists($name, $this->server_caps)) { + if ($name == 'HELO') { + return $this->server_caps['EHLO']; + } + if ($name == 'EHLO' || array_key_exists('EHLO', $this->server_caps)) { + return false; + } + $this->setError('HELO handshake was used. Client knows nothing about server extensions'); + return null; + } + + return $this->server_caps[$name]; + } + + /** + * Get the last reply from the server. + * @access public + * @return string + */ + public function getLastReply() + { + return $this->last_reply; + } + + /** + * Read the SMTP server's response. + * Either before eof or socket timeout occurs on the operation. + * With SMTP we can tell if we have more lines to read if the + * 4th character is '-' symbol. If it is a space then we don't + * need to read anything else. + * @access protected + * @return string + */ + protected function get_lines() + { + // If the connection is bad, give up straight away + if (!is_resource($this->smtp_conn)) { + return ''; + } + $data = ''; + $endtime = 0; + stream_set_timeout($this->smtp_conn, $this->Timeout); + if ($this->Timelimit > 0) { + $endtime = time() + $this->Timelimit; + } + while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) { + $str = @fgets($this->smtp_conn, 515); + $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL); + $this->edebug("SMTP -> get_lines(): \$str is \"$str\"", self::DEBUG_LOWLEVEL); + $data .= $str; + // If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen + if ((isset($str[3]) and $str[3] == ' ')) { + break; + } + // Timed-out? Log and break + $info = stream_get_meta_data($this->smtp_conn); + if ($info['timed_out']) { + $this->edebug( + 'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)', + self::DEBUG_LOWLEVEL + ); + break; + } + // Now check if reads took too long + if ($endtime and time() > $endtime) { + $this->edebug( + 'SMTP -> get_lines(): timelimit reached ('. + $this->Timelimit . ' sec)', + self::DEBUG_LOWLEVEL + ); + break; + } + } + return $data; + } + + /** + * Enable or disable VERP address generation. + * @param boolean $enabled + */ + public function setVerp($enabled = false) + { + $this->do_verp = $enabled; + } + + /** + * Get VERP address generation mode. + * @return boolean + */ + public function getVerp() + { + return $this->do_verp; + } + + /** + * Set error messages and codes. + * @param string $message The error message + * @param string $detail Further detail on the error + * @param string $smtp_code An associated SMTP error code + * @param string $smtp_code_ex Extended SMTP code + */ + protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ex = '') + { + $this->error = array( + 'error' => $message, + 'detail' => $detail, + 'smtp_code' => $smtp_code, + 'smtp_code_ex' => $smtp_code_ex + ); + } + + /** + * Set debug output method. + * @param string|callable $method The name of the mechanism to use for debugging output, or a callable to handle it. + */ + public function setDebugOutput($method = 'echo') + { + $this->Debugoutput = $method; + } + + /** + * Get debug output method. + * @return string + */ + public function getDebugOutput() + { + return $this->Debugoutput; + } + + /** + * Set debug output level. + * @param integer $level + */ + public function setDebugLevel($level = 0) + { + $this->do_debug = $level; + } + + /** + * Get debug output level. + * @return integer + */ + public function getDebugLevel() + { + return $this->do_debug; + } + + /** + * Set SMTP timeout. + * @param integer $timeout + */ + public function setTimeout($timeout = 0) + { + $this->Timeout = $timeout; + } + + /** + * Get SMTP timeout. + * @return integer + */ + public function getTimeout() + { + return $this->Timeout; + } +} diff --git a/zira/request.php b/zira/request.php new file mode 100644 index 0000000..43de635 --- /dev/null +++ b/zira/request.php @@ -0,0 +1,117 @@ +0) { + $part = array_pop($uri_parts); + if ($found || $part == $root_parts[count($root_parts)-1]) { + $_parts []= $part; + $found = true; + } + if ($found) { + array_pop($root_parts); + } + } + + $base_url = '/' . implode('/', array_reverse($_parts)); + + return $base_url; + } + + public static function isBaseRequestUri() { + $uri = '/' . trim($_SERVER['REQUEST_URI'],'/'); + return $uri == self::detectBaseUrl(); + } + + public static function isInstallRequestUri() { + $uri = '/' . trim($_SERVER['REQUEST_URI'],'/'); + return $uri == rtrim(self::detectBaseUrl() ,'/') . '/install'; + } +} diff --git a/zira/response.php b/zira/response.php new file mode 100644 index 0000000..9e1a55d --- /dev/null +++ b/zira/response.php @@ -0,0 +1,122 @@ +$value) { + if ($key == Dash::GET_FRAME_PARAM) continue; + if (!empty($params)) $params .= '&'; + $params .= $key .'='. $value; + } + if (!empty($params)) { + if (strpos($url, '?') === false) $url .= '?'; + else $url .= '&'; + $url .= $params; + } + } + header('Location: '.$url); + exit; + } + + public static function notFound() { + self::$status = self::STATUS_404; + http_response_code(self::$status); + if (View::isInitialized()) { + View::addDefaultAssets(); + View::addThemeAssets(); + if (Config::get('site_window_title') && Config::get('site_title')) { + $suffix = PAGE_TITLE_DELIMITER . Locale::t(Config::get('site_title')); + } else { + $suffix = ''; + } + View::setLayoutData(array(View::VAR_TITLE=>Locale::t('Page not found').$suffix)); + View::render(array('code'=>self::$status,'message'=>Locale::t('Page not found')), 'error', View::LAYOUT_NO_SIDEBARS); + } else { + echo Locale::t('Page not found'); + } + exit; + } + + public static function forbidden() { + self::$status = self::STATUS_403; + http_response_code(self::$status); + if (View::isInitialized()) { + View::addDefaultAssets(); + View::addThemeAssets(); + if (Config::get('site_window_title') && Config::get('site_title')) { + $suffix = PAGE_TITLE_DELIMITER . Locale::t(Config::get('site_title')); + } else { + $suffix = ''; + } + View::setLayoutData(array(View::VAR_TITLE=>Locale::t('Access denied').$suffix)); + View::render(array('code'=>self::$status,'message'=>Locale::t('Access denied')), 'error', View::LAYOUT_NO_SIDEBARS); + } else { + echo Locale::t('Access denied'); + } + exit; + } + + public static function error($message) { + self::$status = self::STATUS_500; + http_response_code(self::$status); + if (View::isInitialized()) { + if (defined('DEBUG') && DEBUG && !View::isRenderStarted()) { + View::addDefaultAssets(); + View::addThemeAssets(); + if (Config::get('site_window_title') && Config::get('site_title')) { + $suffix = PAGE_TITLE_DELIMITER . Locale::t(Config::get('site_title')); + } else { + $suffix = ''; + } + View::setLayoutData(array(View::VAR_TITLE=>Locale::t('An error occurred').$suffix)); + } + View::render(array('code'=>self::$status,'message'=>Locale::t('An error occurred'),'content'=>$message), 'error', View::LAYOUT_NO_SIDEBARS); + } else { + echo $message; + } + exit; + } + + public static function exception(\Exception $e) { + if (defined('DEBUG') && DEBUG) { + $str = Helper::tag('div', $e->getMessage().' in '.$e->getFile().':'.$e->getLine()); + $str .= Helper::tag_open('div'); + $str .= Helper::tag_open('code'); + $str .= nl2br($e->getTraceAsString()); + $str .= Helper::tag_close('code'); + $str .= Helper::tag_close('div'); + } else { + $str = Helper::tag('div', $e->getMessage()); + } + self:: error($str); + } +} \ No newline at end of file diff --git a/zira/router.php b/zira/router.php new file mode 100644 index 0000000..2e643a6 --- /dev/null +++ b/zira/router.php @@ -0,0 +1,215 @@ +1 + && preg_match('/^\/('.implode('|',Config::get('languages')).')(\/.*)$/iu',self::$request,$matches) + ) { + self::$language = $matches[1]; + self::$request = $matches[2]; + } + + self::$request = trim(self::$request,'/'); + + if ($redirect) { + if (self::$language) self::$request = self::$language.'/'.self::$request; + Response::redirect(self::$request, true); + } + + self::$param = ''; + $url_parts = array(); + if (preg_match('/^([a-z\/]+)\/(.*)/',self::$request.'/',$matches)) { + $url_parts = explode('/',$matches[1]); + $rewrite = ''; + $rewrite_match = ''; + if (array_key_exists($matches[1],self::$_map)) { + $rewrite_match = $matches[1]; + $rewrite = self::$_map[$matches[1]]; + } else { + $variants = array(); + if (count($url_parts) == 2) { + $variants[]='*/'.$url_parts[1]; + $variants[]=$url_parts[0].'/*'; + } else if (count($url_parts) == 3) { + $variants[]='*/'.$url_parts[1]; + $variants[]=$url_parts[0].'/*'; + $variants[]='*/*/'.$url_parts[2]; + $variants[]='*/'.$url_parts[1].'/*'; + $variants[]=$url_parts[0].'/*/*'; + $variants[]='*/'.$url_parts[1].'/'.$url_parts[2]; + $variants[]=$url_parts[0].'/*/'.$url_parts[2]; + $variants[]=$url_parts[0].'/'.$url_parts[1].'/*'; + } + + foreach($variants as $variant) { + if (array_key_exists($variant, self::$_map)) { + $rewrite = self::$_map[$variant]; + $rewrite_match = $variant; + break; + } + } + } + if (!empty($rewrite)) { + for ($i=0; $i<3; $i++) { + if (strpos($rewrite, '$'.($i+1))!==false) { + if (isset($url_parts[$i])) { + $rewrite = str_replace('$'.($i+1), $url_parts[$i], $rewrite); + } else { + if ($i==0) $part = DEFAULT_MODULE; + else if ($i==1) $part = DEFAULT_CONTROLLER; + else $part = DEFAULT_ACTION; + $rewrite = str_replace('$'.($i+1), $part, $rewrite); + } + } + } + $_url_parts = explode('/', $rewrite); + if (!empty($rewrite_match)) { + $_match_parts = explode('/', $rewrite_match); + if (count($_match_parts) < count($url_parts)) { + $_add_params = array_slice($url_parts, count($_match_parts)); + $_url_parts = array_merge($_url_parts, $_add_params); + } + } + $url_parts = $_url_parts; + } + self::$param = trim($matches[2],'/'); + } else { + self::$param = self::$request; + } + + if (count($url_parts)==0) { + self::$module = DEFAULT_MODULE; + self::$controller = DEFAULT_CONTROLLER; + self::$action = DEFAULT_ACTION; + } else if (count($url_parts)==1) { + self::$module = $url_parts[0]; + self::$controller = DEFAULT_CONTROLLER; + self::$action = DEFAULT_ACTION; + } else if (count($url_parts)==2) { + self::$module = $url_parts[0]; + self::$controller = $url_parts[1]; + self::$action = DEFAULT_ACTION; + } else { + self::$module = array_shift($url_parts); + self::$controller = array_shift($url_parts); + self::$action = array_shift($url_parts); + + if (count($url_parts)>0) { + $_param = implode('/',$url_parts); + if (!empty(self::$param)) $_param .= '/'; + self::$param = $_param . self::$param; + } + } + + if (!self::$language && count(Config::get('languages'))>1 && + !empty(self::$request) && + self::$request!='cron' && + self::$request!='sitemap.xml' && + self::$module!='dash' + ) { + self::$language = Config::get('language'); + Response::redirect(self::$language.'/'.self::$request, true); + } else if (self::$language && self::$language==Config::get('language') && empty(self::$request)) { + Response::redirect(self::$request, true); + } + } +} \ No newline at end of file diff --git a/zira/session.php b/zira/session.php new file mode 100644 index 0000000..144095e --- /dev/null +++ b/zira/session.php @@ -0,0 +1,43 @@ +id) return false; + if (!self::isAuthorized()) return false; + return (self::$_current->id == $user->id); + } + + public static function generatePasswordHash($password) { + return password_hash($password, PASSWORD_DEFAULT); + } + + public static function verifyPassword($password, $hash) { + return password_verify($password, $hash); + } + + public static function generateEmailConfirmationCode() { + return Zira::randomSecureString(16); + } + + public static function getHashedConfirmationCode($code) { + return self::generatePasswordHash($code); + } + + public static function verifyConfirmationCode($code, $hash) { + return self::verifyPassword($code, $hash); + } + + public static function generatePasswordRecoveryCode() { + return Zira::randomSecureString(24); + } + + public static function getHashedPasswordRecoveryCode($code) { + return self::generatePasswordHash($code); + } + + public static function verifyPasswordRecoveryCode($code, $hash) { + return self::verifyPassword($code, $hash); + } + + public static function generateRememberCode($login,$email) { + do { + $random = Zira::randomSecureString(16); + $code = md5($random.$login.$email); + $co = Models\User::getCollection() + ->count() + ->where('code','=',$code) + ->get('co'); + } while($co>0); + + return $code; + } + + public static function generateUserToken() { + return Zira::randomSecureString(32); + } + + public static function getHashedUserToken($code) { + return self::generatePasswordHash($code); + } + + public static function verifyUserToken($token, $hash) { + return password_verify($token, $hash); + } + + public static function isVerificationCodeCorrect($login_or_email, $code) { + if (empty($code)) return false; + $user = Models\User::findAuthUser($login_or_email); + if (!$user) return false; + $hash = $user->vcode; + if (empty($hash)) return false; + if ($user->verified == \Zira\Models\User::STATUS_VERIFIED) return false; + if (self::verifyConfirmationCode($code, $hash)) { + self::setCurrent($user); + return true; + } else { + return false; + } + } + + public static function isRecoveryCodeCorrect($login_or_email, $code) { + if (empty($code)) return false; + $user = Models\User::findAuthUser($login_or_email); + if (!$user) return false; + $hash = $user->vcode; + if (empty($hash)) return false; + if ($user->verified != \Zira\Models\User::STATUS_VERIFIED) return false; + if (self::verifyPasswordRecoveryCode($code, $hash)) { + self::setCurrent($user); + return true; + } else { + return false; + } + } + + public static function getDefaultConfirmMessage() { + $message = Locale::t('Hello %s !', '$user')."\r\n\r\n"; + $message .= Locale::t('Please confirm your Email address.')."\r\n"; + $message .= Locale::t('Your verification code: %s', '$code')."\r\n"; + $message .= Locale::t('Enter code on the following page %s','$url')."\r\n\r\n"; + $message .= Locale::t('You recieved this message, because your Email address was specified during registration process on %s','$site'); + return $message; + } + + public static function sendConfirmEmail($email, $login, $code) { + $message = Config::get(self::CONFIG_CONFIRMATION_MESSAGE); + if (!$message || strlen(trim($message))==0) { + $message = self::getDefaultConfirmMessage(); + } else { + $message = Locale::t($message); + } + $message = str_replace('$user', $login, $message); + $message = str_replace('$code', $code, $message); + $message = str_replace('$url', Helper::url('user/confirm', true, true), $message); + $message = str_replace('$site', Helper::url('/',true, true), $message); + + Mail::send($email, Locale::t('Email confirmation'), Helper::html($message)); + } + + public static function getDefaultRecoveryMessage() { + $message = Locale::t('Hello %s !', '$user')."\r\n\r\n"; + $message .= Locale::t('We recieved password recovery request for your account.')."\r\n"; + $message .= Locale::t('Your verification code: %s', '$code')."\r\n"; + $message .= Locale::t('Enter code on the following page %s','$url')."\r\n\r\n"; + $message .= Locale::t('You recieved this message, because your Email address or login was specified during password recovery process on %s. If it was not you, ignore this message','$site'); + return $message; + } + + public static function sendRecoverEmail($email, $login, $code) { + $message = Config::get(self::CONFIG_RECOVERY_MESSAGE); + if (!$message || strlen(trim($message))==0) { + $message = self::getDefaultRecoveryMessage(); + } else { + $message = Locale::t($message); + } + $message = str_replace('$user', $login, $message); + $message = str_replace('$code', $code, $message); + $message = str_replace('$url', Helper::url('user/password', true, true), $message); + $message = str_replace('$site', Helper::url('/',true, true), $message); + + Mail::send($email, Locale::t('Password recovery'), Helper::html($message)); + } + + public static function getDefaultPasswordMessage() { + $message = Locale::t('Hello %s !', '$user')."\r\n\r\n"; + $message .= Locale::t('Your new password: %s', '$code')."\r\n"; + $message .= Locale::t('You can now sign in on the following page %s','$url')."\r\n\r\n"; + $message .= Locale::t('You recieved this message, because your Email address or login was specified during password recovery process on %s','$site'); + return $message; + } + + public static function sendPasswordEmail($email, $login, $password) { + $message = Config::get(self::CONFIG_PASSWORD_MESSAGE); + if (!$message || strlen(trim($message))==0) { + $message = self::getDefaultPasswordMessage(); + } else { + $message = Locale::t($message); + } + $message = str_replace('$user', $login, $message); + $message = str_replace('$code', $password, $message); + $message = str_replace('$url', Helper::url('user/login', true, true), $message); + $message = str_replace('$site', Helper::url('/',true, true), $message); + + Mail::send($email, Locale::t('Your new password'), Helper::html($message)); + } + + public static function isPasswordCorrect($login, $password) { + if (empty($login) || empty($password)) return false; + $user = Models\User::findAuthUser($login); + if (!$user) return false; + if (!$user->username || !$user->password) return false; + if (self::verifyPassword($password, $user->password)) { + self::setCurrent($user); + return true; + } else { + return false; + } + } + + public static function isAllowedToLogin() { + $user = self::getCurrent(); + if (!$user) return false; + if (!Config::get(self::CONFIG_VERIFY_EMAIL, true)) return true; + return $user->verified == Models\User::STATUS_VERIFIED; + } + + public static function rememberConfirmEmail($email) { + Session::set(self::SESSION_CONFIRM_EMAIL, $email); + } + + public static function getRememberedConfirmEmail() { + return Session::get(self::SESSION_CONFIRM_EMAIL); + } + + public static function rememberAuthorizedUserId($user_id) { + Session::set(self::SESSION_AUTHORIZED_USER_ID, $user_id); + $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; + Session::set(self::SESSION_UA, $ua); + } + + public static function forgetAuthorizedUserId() { + Session::remove(self::SESSION_AUTHORIZED_USER_ID); + Session::remove(self::SESSION_UA); + self::unsetUserPasswordChecked(); + } + + public static function load() { + User::initAnonymousUser(); + $user_id = intval(Session::get(self::SESSION_AUTHORIZED_USER_ID)); + if (!$user_id) { + $user_id = self::loadRememberedUser(); + if (!$user_id) return; + } else { + $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; + if (Config::get(self::CONFIG_CHECK_UA, true) && Session::get(self::SESSION_UA) != $ua) { + self::forgetAuthorizedUserId(); + return; + } + } + $user = self::getCurrent(); + if (!$user || !($user instanceof Models\User)) { + $user = new Models\User($user_id); + if (!$user->loaded()) $user = null; + } + if (!$user || !$user->active) { + self::forgetAuthorizedUserId(); + self::forgetUser(); + if ($user) { + $user->token = ''; + $user->save(); + } + return; + } + self::setCurrent($user); + } + + public static function isAuthorized() { + $user = self::getCurrent(); + if (!$user) return false; + if (!($user instanceof Models\User)) return false; + return true; + } + + public static function isVerified() { + if (!self::isAuthorized()) return false; + return self::$_current->verified == Models\User::STATUS_VERIFIED; + } + + public static function onUserLogin($remember = false) { + Session::regenerate(); + $user = self::getCurrent(); + if (!$user) return; + if (!($user instanceof Models\User)) { + $user = new Models\User($user->id); + if (!$user) return; + } + $user->date_logged = date('Y-m-d H:i:s'); + if ($remember) { + $token = self::generateUserToken(); + $ua=isset($_SERVER['HTTP_USER_AGENT']) && Config::get(self::CONFIG_CHECK_UA, true) ? $_SERVER['HTTP_USER_AGENT'] : ''; + $user->token = self::getHashedUserToken($token.$ua); + self::rememberUser($user->code, $token); + } else { + $user->token = ''; + } + $user->save(); + self::setCurrent($user); + self::rememberAuthorizedUserId($user->id); + } + + public static function onUserLogout() { + self::clearToken(); + Dash::clearToken(); + Session::regenerate(); + } + + public static function rememberUser($code, $token) { + Cookie::set(self::COOKIE_REMEMBER_ME, $code.';'.$token, self::REMEMBER_ME_LIFETIME); + } + + public static function forgetUser() { + Cookie::remove(self::COOKIE_REMEMBER_ME); + } + + public static function loadRememberedUser() { + $cookie = Cookie::get(self::COOKIE_REMEMBER_ME); + if (empty($cookie)) return null; + $data = explode(';',$cookie); + if (count($data)!=2 || empty($data[0]) || empty($data[1])) { + self::forgetUser(); + return null; + } + $user = Models\User::getCollection() + ->select(Models\User::getFields()) + ->join(Models\Group::getClass(), array('group_name'=>'name')) + ->where('code','=',$data[0]) + ->and_where('active','=',Models\User::STATUS_ACTIVE) + ->and_where('active','=',Models\Group::STATUS_ACTIVE, Models\Group::getAlias()) + ->get(0); + if (!$user || !$user->token) { + self::forgetUser(); + return null; + } + if (Config::get(self::CONFIG_VERIFY_EMAIL, true) && $user->verified != Models\User::STATUS_VERIFIED) { + self::forgetUser(); + return null; + } + $ua=isset($_SERVER['HTTP_USER_AGENT']) && Config::get(self::CONFIG_CHECK_UA, true) ? $_SERVER['HTTP_USER_AGENT'] : ''; + if (!self::verifyUserToken($data[1].$ua, $user->token)) { + $user = new Models\User($user->id); + if ($user) { + $user->token = ''; + $user->save(); + } + self::forgetUser(); + return null; + } + $user = new Models\User($user->id); + if (!$user) { + return null; + } else { + self::setCurrent($user); + self::onUserLogin(true); + return $user->id; + } + } + + public static function setUserPasswordChecked() { + Session::set(self::SESSION_PASSWORD_CHECKED, 1); + } + + public static function unsetUserPasswordChecked() { + Session::remove(self::SESSION_PASSWORD_CHECKED); + } + + public static function isUserPasswordChecked() { + return (bool)Session::get(self::SESSION_PASSWORD_CHECKED); + } + + public static function generateUserPhotoName($user_id) { + $random = Zira::randomSecureString(16); + return md5($random.$user_id); + } + + public static function generateAnonymousId() { + $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''; + $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; + return self::getToken().md5($ip.microtime().$ua); + } + + public static function getAnonymousUserId() { + $anonymous_id = Cookie::get(self::COOKIE_ANONYMOUS_USER); + if (empty($anonymous_id)) { + $anonymous_id = self::generateAnonymousId(); + } + return $anonymous_id; + } + + public static function initAnonymousUser() { + $anonymous_id = self::getAnonymousUserId(); + Cookie::set(self::COOKIE_ANONYMOUS_USER, $anonymous_id, self::REMEMBER_ANONYMOUS_ID); + } + + protected static function generateToken() { + return Zira::randomSecureString(8); + } + + public static function getToken() { + $exist = Session::get(self::SESSION_TOKEN); + if ($exist) return $exist; + + $token = self::generateToken(); + Session::set(self::SESSION_TOKEN,$token); + + return $token; + } + + public static function checkToken($token) { + if (!$token) return false; + $exist = Session::get(self::SESSION_TOKEN); + if (!$exist) return false; + + return ($token == $exist); + } + + public static function clearToken() { + Session::remove(self::SESSION_TOKEN); + } + + public static function getUserPhotoFilename($image) { + return $image.'.'.self::PHOTO_EXT; + } + + public static function getUserThumbFilename($image) { + return $image.'.thumb.'.self::PHOTO_EXT; + } + + public static function deletePhoto($user) { + if (!$user->image) return; + $name = self::getUserPhotoFilename($user->image); + $thumb_name = self::getUserThumbFilename($user->image); + + $dir = ROOT_DIR . DIRECTORY_SEPARATOR . UPLOADS_DIR . DIRECTORY_SEPARATOR . USERS_DIR . DIRECTORY_SEPARATOR; + if (file_exists($dir.$name)) unlink($dir.$name); + if (file_exists($dir.$thumb_name)) unlink($dir.$thumb_name); + } + + public static function savePhoto($user, array $file) { + if ($user->image) self::deletePhoto($user); + $save_path = USERS_DIR; + $max_width = Config::get('user_photo_max_width'); + $max_height = Config::get('user_photo_max_height'); + $thumb_width = Config::get('user_thumb_width'); + $thumb_height = Config::get('user_thumb_height'); + do { + $image = self::generateUserPhotoName($user->id); + $name = self::getUserPhotoFilename($image); + $thumb_name = self::getUserThumbFilename($image); + } while(file_exists(File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $name) || file_exists(File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $thumb_name)); + $files = File::save($file, $save_path); + if (!$files) return false; + foreach($files as $path=>$_name) { + $size = @getimagesize($path); + if ($size[0]>$size[1]) { + if ($size[0]<$max_width) $max_width = $size[0]; + if (!Image::resize($path, File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $name, $max_width, null, self::PHOTO_EXT)) return false; + } else if ($size[0]<=$size[1]) { + if ($size[1]<$max_height) $max_height = $size[1]; + if (!Image::resize($path, File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $name, null, $max_height, self::PHOTO_EXT)) return false; + } + if (!Image::createThumb($path, File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $thumb_name, $thumb_width, $thumb_height, self::PHOTO_EXT)) return false; + unlink($path); + } + return $image; + } + + public static function saveAvatar($user, $width_percent, $height_percent, $left_percent, $top_percent) { + if (!$user->image) return false; + $thumb_width = Config::get('user_thumb_width'); + $thumb_height = Config::get('user_thumb_height'); + $name = self::getUserPhotoFilename($user->image); + $thumb_name = self::getUserThumbFilename($user->image); + $save_path = USERS_DIR; + if (!Image::crop(File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $name, File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $thumb_name, $width_percent, $height_percent, $left_percent, $top_percent, self::PHOTO_EXT)) return false; + if (!Image::resize(File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $thumb_name, File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $thumb_name, $thumb_width, $thumb_height, self::PHOTO_EXT)) return false; + do { + $image = self::generateUserPhotoName($user->id); + $new_name = self::getUserPhotoFilename($image); + $new_thumb_name = self::getUserThumbFilename($image); + } while(file_exists(File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $new_name) || file_exists(File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $new_thumb_name)); + if ( + !rename(File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $thumb_name, File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $new_thumb_name) || + !rename(File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $name, File::getAbsolutePath($save_path). DIRECTORY_SEPARATOR . $new_name) + ) return false; + return $image; + } + + public static function isProfileVerified($user=null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return false; + return $user->verified == Models\User::STATUS_VERIFIED; + } + + public static function getProfileName($user=null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + $name = trim($user->firstname.' '.$user->secondname); + if (!empty($name)) return $name; + return $user->username; + } + + public static function getProfileLocation($user=null, $default = null) { + if ($default === null) $default = Locale::t('not specified'); + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + $country = trim($user->country); + $city = trim($user->city); + $address = trim($user->address); + $loc = array(); + if (!empty($country)) $loc []= $country; + if (!empty($city)) $loc []= $city; + if (!empty($address)) $loc []= $address; + $loc = implode(', ',$loc); + if (empty($loc)) $loc = $default; + return $loc; + } + + public static function getProfileDob($user=null, $default = null) { + if ($default === null) $default = Locale::t('not specified'); + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + $dob = $user->dob; + if (!empty($dob)) return date(Config::get('date_format'), strtotime($dob)); + return $default; + } + + public static function getProfileSignupDate($user=null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + return date(Config::get('date_format'), strtotime($user->date_created)); + } + + public static function getProfileLoginDate($user=null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + return date(Config::get('date_format'), strtotime($user->date_logged)); + } + + public static function getProfileGroup($user=null, $default = null) { + if ($default === null) $default = Locale::t('unknown'); + if($user===null) $user = self::getCurrent(); + if (!$user) return $default; + $groups = Models\Group::getArray(); + if (!array_key_exists($user->group_id, $groups)) return $default; + return $groups[$user->group_id]; + } + + public static function getProfileNoPhotoUrl() { + return Helper::imgUrl(self::USER_NOPHOTO); + } + + public static function getProfilePhoto($user=null, $default = '') { + if($user===null) $user = self::getCurrent(); + if (!$user || !$user->image) return $default; + + $name = self::getUserPhotoFilename($user->image); + + return Helper::baseUrl(UPLOADS_DIR . '/' . USERS_DIR . '/' . $name); + } + + public static function getProfilePhotoThumb($user=null, $default = '') { + if($user===null) $user = self::getCurrent(); + if (!$user || !$user->image) return $default; + + $name = self::getUserThumbFilename($user->image); + + return Helper::baseUrl(UPLOADS_DIR . '/' . USERS_DIR . '/' . $name); + } + + public static function getProfileEmail($user=null, $default = '') { + if($user===null) $user = self::getCurrent(); + if (!$user) return $default; + if (!self::isSelf($user)) return $default; + return $user->email; + } + + public static function getProfilePhone($user=null, $default = '') { + if($user===null) $user = self::getCurrent(); + if (!$user || !$user->phone) return $default; + if (!self::isSelf($user)) return $default; + return $user->phone; + } + + public static function getProfileUrlPath($user=null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + return 'user/'.$user->id; + } + + public static function getProfileUrl($user=null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + return Helper::url('user/'.$user->id); + } + + public static function getProfileComments($user=null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + return (int)$user->comments; + } + + public static function getDefaultGroupsArray() { + return array( + self::GROUP_SUPERADMIN, + self::GROUP_ADMIN, + self::GROUP_USER + ); + } + + public static function generateUserProfileLink($id, $firstname, $secondname, $username, $rel = null, $icon_class = '') { + $name = $firstname && $secondname ? trim($firstname . ' ' . $secondname) : $username; + $attr = array('href'=>Helper::url('user/'.$id)); + if ($rel !== null) $attr['rel'] = $rel; + if (empty($icon_class)) return Helper::tag('a', $name, $attr); + else { + $html = Helper::tag_open('a', $attr); + $html .= Helper::tag('span', null, array('class'=>$icon_class)).' '; + $html .= Helper::html($name); + $html .= Helper::tag_close('a'); + return $html; + } + } + + public static function generateUserProfileThumb($image, $default = null, array $attributes = array()) { + $url = Helper::imgUrl('nophoto.jpg'); + if (!$image && $default!==null) $url = $default; + else if ($image) { + $name = self::getUserThumbFilename($image); + $url = Helper::baseUrl(UPLOADS_DIR . '/' . USERS_DIR . '/' . $name); + } + $attributes['src'] = $url; + $attributes['width'] = Config::get('user_thumb_width'); + $attributes['height'] = Config::get('user_thumb_height'); + return Helper::tag_short('img', $attributes); + } + + public static function generateUserProfileThumbLink($id, $firstname, $secondname, $username, $rel = null, $image, $default_image = null, array $attributes = array()) { + $name = $firstname && $secondname ? trim($firstname . ' ' . $secondname) : $username; + $attr = array('href'=>Helper::url('user/'.$id),'title'=>$name); + if ($rel !== null) $attr['rel'] = $rel; + $html = Helper::tag_open('a', $attr); + $html .= self::generateUserProfileThumb($image, $default_image, $attributes); + $html .= Helper::tag_close('a'); + return $html; + } + + public static function getProfileEditLinks() { + $user = self::getCurrent(); + if (!$user) return array(); + $links = array(); + $links []= array( + 'url' => 'user/messages', + 'icon' => 'glyphicon glyphicon-envelope', + 'title' => Locale::t('Messages') + ); + $links []= array( + 'type' => 'separator' + ); + $links []= array( + 'url' => 'user/photo', + 'icon' => 'glyphicon glyphicon-picture', + 'title' => Locale::t('Edit photo') + ); + if ($user->image) { + $links [] = array( + 'url' => 'user/avatar', + 'icon' => 'glyphicon glyphicon-scissors', + 'title' => Locale::t('Edit avatar') + ); + $links []= array( + 'url' => 'user/nophoto', + 'icon' => 'glyphicon glyphicon-ban-circle', + 'title' => Locale::t('Delete photo') + ); + } + $links []= array( + 'type' => 'separator' + ); + $links []= array( + 'url' => 'user/edit', + 'icon' => 'glyphicon glyphicon-list-alt', + 'title' => Locale::t('Edit profile') + ); + $links []= array( + 'url' => 'user/email', + 'icon' => 'glyphicon glyphicon-envelope', + 'title' => Locale::t('Edit email') + ); + if (Config::get(self::CONFIG_ALLOW_LOGIN_CHANGE, true)) { + $links [] = array( + 'url' => 'user/name', + 'icon' => 'glyphicon glyphicon-user', + 'title' => Locale::t('Edit username') + ); + } + $links []= array( + 'url' => 'user/pwd', + 'icon' => 'glyphicon glyphicon-lock', + 'title' => Locale::t('Edit password') + ); + $extra_links = Hook::run(self::PROFILE_LINKS_HOOK); + if (!empty($extra_links)) { + $links = array_merge($links, $extra_links); + } + return $links; + } + + public static function getProfileExtraInfo() { + return Hook::run(self::PROFILE_INFO_HOOK); + } + + public static function increaseMessagesCount($user = null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + $user->messages++; + $user->save(); + } + + public static function decreaseMessagesCount($user = null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + $user->messages--; + if ($user->messages<0) $user->messages=0; + $user->save(); + } + + public static function increaseCommentsCount($user = null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + $user->comments++; + $user->save(); + } + + public static function decreaseCommentsCount($user = null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + $user->comments--; + if ($user->comments<0) $user->comments=0; + $user->save(); + } + + public static function increasePostsCount($user = null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + $user->posts++; + $user->save(); + } + + public static function decreasePostsCount($user = null) { + if($user===null) $user = self::getCurrent(); + if (!$user) return ''; + $user->posts--; + if ($user->posts<0) $user->posts=0; + $user->save(); + } + + public static function isUserBlocked($user_id, $return_found_row = false) { + if (!self::isAuthorized()) return false; + + $row=Models\Blacklist::getCollection() + ->where('user_id','=',self::getCurrent()->id) + ->and_where('blocked_user_id','=',$user_id) + ->get(0); + + if (!$row) return false; + if (!$return_found_row) return true; + else return $row; + } + + public static function isCurrentBlocked($user_id, $return_found_row = false) { + if (!self::isAuthorized()) return false; + + $row=Models\Blacklist::getCollection() + ->where('user_id','=',$user_id) + ->and_where('blocked_user_id','=',self::getCurrent()->id) + ->get(0); + + if (!$row) return false; + if (!$return_found_row) return true; + else return $row; + } +} \ No newline at end of file diff --git a/zira/view.php b/zira/view.php new file mode 100644 index 0000000..62238a3 --- /dev/null +++ b/zira/view.php @@ -0,0 +1,824 @@ +$v) { + $html .= Helper::html($k) . '="' . Helper::html($v) . '" '; + } + $html .= '/>'; + + self::addHTML($html,self::VAR_META); + } + + public static function addStyle($url, $theme = false, array $attributes = null) { + if (Assets::isActive() && Assets::isMergedCSS($url)) return; + if (!$attributes) $attributes = array(); + if (!isset($attributes['rel'])) $attributes['rel'] = 'stylesheet'; + if (!isset($attributes['type'])) $attributes['type'] = 'text/css'; + if (!$theme) { + $attributes['href'] = Helper::cssUrl($url); + } else { + $attributes['href'] = Helper::cssThemeUrl($url); + } + self::addHTML(Helper::tag_short('link', $attributes),self::VAR_STYLES); + } + + public static function addThemeStyle($url, array $attributes = null) { + self::addStyle($url, true, $attributes); + } + + public static function addScript($url, $theme = false, array $attributes = null) { + if (Assets::isActive() && Assets::isMergedJS($url)) return; + if (!$attributes) $attributes = array(); + if (!$theme) { + $attributes['src'] = Helper::jsUrl($url); + } else { + $attributes['src'] = Helper::jsThemeUrl($url); + } + self::addHTML(Helper::tag('script', null, $attributes),self::VAR_SCRIPTS); + } + + public static function addThemeScript($url, array $attributes = null) { + self::addScript($url, true, $attributes); + } + + public static function addHTML($html,$var) { + if (!isset(self::$_layout_data[$var])) self::$_layout_data[$var] = $html . "\r\n"; + else self::$_layout_data[$var] .= $html . "\r\n"; + } + + public static function isRenderStarted() { + return self::$_render_started; + } + + public static function setKeywordsAdded($value) { + self::$_keywords_added = (bool)$value; + } + + public static function setDescriptionAdded($value) { + self::$_description_added = (bool)$value; + } + + public static function render(array $data, $view=null, $layout=null) { + require_once(ROOT_DIR . DIRECTORY_SEPARATOR . 'zira' . DIRECTORY_SEPARATOR . 'tpl.php'); + + if (!$view) { + $view = Router::getModule() . DIRECTORY_SEPARATOR . + Router::getController() . DIRECTORY_SEPARATOR . + Router::getAction(); + } else { + $view = str_replace('/', DIRECTORY_SEPARATOR, $view); + } + + $view_file = ROOT_DIR . DIRECTORY_SEPARATOR . + THEMES_DIR . DIRECTORY_SEPARATOR . + self::$_theme . DIRECTORY_SEPARATOR . + $view . '.php'; + + if (self::$_theme!=DEFAULT_THEME && !file_exists($view_file)) { + $view_file = ROOT_DIR . DIRECTORY_SEPARATOR . + THEMES_DIR . DIRECTORY_SEPARATOR . + DEFAULT_THEME . DIRECTORY_SEPARATOR . + $view . '.php'; + } + + if (self::$_render_layout && !self::$_render_started) { + if (!$layout) { + $layout = Config::get('layout'); + } + + $layout = str_replace('/', DIRECTORY_SEPARATOR, $layout); + + $layout_file = ROOT_DIR . DIRECTORY_SEPARATOR . + THEMES_DIR . DIRECTORY_SEPARATOR . + self::$_theme . DIRECTORY_SEPARATOR . + $layout . '.php'; + + $default_layouts = self::getDefaultLayouts(); + if (!file_exists($layout_file) && !array_key_exists($layout, $default_layouts)) { + $layout_file = ROOT_DIR . DIRECTORY_SEPARATOR . + THEMES_DIR . DIRECTORY_SEPARATOR . + self::$_theme . DIRECTORY_SEPARATOR . + self::LAYOUT_ALL_SIDEBARS . '.php'; + } + + if (self::$_theme!=DEFAULT_THEME && !file_exists($layout_file)) { + $layout_file = ROOT_DIR . DIRECTORY_SEPARATOR . + THEMES_DIR . DIRECTORY_SEPARATOR . + DEFAULT_THEME . DIRECTORY_SEPARATOR . + $layout . '.php'; + } + + self::renderLayout($data, $view_file, $layout_file); + + if (defined('DEBUG') && DEBUG && defined('START_TIME')) { + echo "\r\n".''; + echo "\r\n".''; + if (defined('START_TIME')) { + echo "\r\n".''; + } + echo "\r\n".''; + } + } else { + self::renderContent($data, $view_file); + } + } + + public static function renderView(array $data, $view) { + require_once(ROOT_DIR . DIRECTORY_SEPARATOR . 'zira' . DIRECTORY_SEPARATOR . 'tpl.php'); + + $view = str_replace('/', DIRECTORY_SEPARATOR, $view); + + $view_file = ROOT_DIR . DIRECTORY_SEPARATOR . + THEMES_DIR . DIRECTORY_SEPARATOR . + self::$_theme . DIRECTORY_SEPARATOR . + $view . '.php'; + + if (self::$_theme!=DEFAULT_THEME && !file_exists($view_file)) { + $view_file = ROOT_DIR . DIRECTORY_SEPARATOR . + THEMES_DIR . DIRECTORY_SEPARATOR . + DEFAULT_THEME . DIRECTORY_SEPARATOR . + $view . '.php'; + } + + self::renderContent($data, $view_file); + } + + public static function isViewExists($view=null) { + if (!$view) { + $view = Router::getModule() . DIRECTORY_SEPARATOR . + Router::getController() . DIRECTORY_SEPARATOR . + Router::getAction(); + } else { + $view = str_replace('/', DIRECTORY_SEPARATOR, $view); + } + + $view_file = ROOT_DIR . DIRECTORY_SEPARATOR . + THEMES_DIR . DIRECTORY_SEPARATOR . + self::$_theme . DIRECTORY_SEPARATOR . + $view . '.php'; + + return file_exists($view_file); + } + + public static function renderContent(array $data, $view_file) { + self::$_render_started = true; + extract($data); + include($view_file); + echo "\r\n"; + } + + public static function renderLayout($data, $view_file, $layout_file) { + require_once(ROOT_DIR . DIRECTORY_SEPARATOR . 'zira' . DIRECTORY_SEPARATOR . 'tpl.php'); + + self::$_content_data = $data; + self::$_content_view = $view_file; + + if (self::$_render_js_strings) { + if (!isset(self::$_layout_data[self::VAR_HEAD_BOTTOM])) self::$_layout_data[self::VAR_HEAD_BOTTOM] = ''; + self::$_layout_data[self::VAR_HEAD_BOTTOM] .= Helper::tag_open('script', array('type'=>'text/javascript')); + self::$_layout_data[self::VAR_HEAD_BOTTOM] .= 'var zira_strings = { '; + $co = 0; + foreach(self::$_js_strings as $string => $translate) { + if ($co>0) self::$_layout_data[self::VAR_HEAD_BOTTOM] .= ', '; + self::$_layout_data[self::VAR_HEAD_BOTTOM] .= "'".Helper::html($string)."': ".json_encode(Helper::html(Locale::t($translate))); + $co++; + } + self::$_layout_data[self::VAR_HEAD_BOTTOM] .= ' };'; + self::$_layout_data[self::VAR_HEAD_BOTTOM] .= Helper::tag_close('script')."\r\n"; + + $body_bottom_scripts = self::getBodyBottomScripts(); + if (!empty($body_bottom_scripts)) self::addHTML($body_bottom_scripts, self::VAR_BODY_BOTTOM); + + self::$_layout_data[self::VAR_HEAD_BOTTOM] .= Helper::tag_open('script', array('type'=>'text/javascript')); + self::$_layout_data[self::VAR_HEAD_BOTTOM] .= 'zira_base = \''.Helper::baseUrl('').'\';'; + self::$_layout_data[self::VAR_HEAD_BOTTOM] .= Helper::tag_close('script')."\r\n"; + } + + if (!isset(self::$_layout_data[self::VAR_CHARSET])) self::$_layout_data[self::VAR_CHARSET] = CHARSET; + self::$_layout_data[self::VAR_CHARSET] = Helper::tag_short('meta',array('charset'=>self::$_layout_data[self::VAR_CHARSET]))."\r\n"; + + if (!isset(self::$_layout_data[self::VAR_TITLE])) { + if (Config::get('site_title')) { + self::$_layout_data[self::VAR_TITLE] = Locale::t(Config::get('site_title')); + } else if (Config::get('site_name')) { + self::$_layout_data[self::VAR_TITLE] = Locale::t(Config::get('site_name')); + } else { + self::$_layout_data[self::VAR_TITLE] = Locale::t(DEFAULT_TITLE); + } + } + self::$_layout_data[self::VAR_TITLE] = Helper::tag('title',self::$_layout_data[self::VAR_TITLE])."\r\n"; + + if (!self::$_keywords_added) { + self::addMeta(array('name'=>'keywords','content'=>Locale::t(Config::get('site_keywords')))); + } + if (!self::$_description_added) { + self::addMeta(array('name'=>'description','content'=>Locale::t(Config::get('site_description')))); + } + + self::addCR(); + self::$_render_started = true; + + include($layout_file); + } + + public static function renderContentData() { + if (self::$_content_data === null || self::$_content_view === null) return; + self::renderContent(self::$_content_data, self::$_content_view); + } + + public static function setRenderLayout($render_layout) { + self::$_render_layout = (bool) $render_layout; + } + + public static function setLayoutData(array $layout_data) { + self::$_layout_data = array_merge(self::$_layout_data, $layout_data); + } + + public static function addLayoutContent($placeholder, $content) { + if (!isset(self::$_layout_data[$placeholder])) { + self::$_layout_data[$placeholder] = $content."\r\n"; + } else { + self::$_layout_data[$placeholder] .= $content."\r\n"; + } + } + + public static function getLayoutData($var=null) { + if ($var === null) return self::$_layout_data; + if (!isset(self::$_layout_data[$var])) return null; + return self::$_layout_data[$var]; + } + + public static function addPlaceholderView($placeholder,$data,$view) { + if (!isset(self::$_placeholder_views[$placeholder])) self::$_placeholder_views[$placeholder] = array(); + self::$_placeholder_views[$placeholder][$view] = $data; + } + + public static function includePlaceholderViews($placeholder) { + if (!isset(self::$_placeholder_views[$placeholder]) || !is_array(self::$_placeholder_views[$placeholder])) return; + + foreach(self::$_placeholder_views[$placeholder] as $view=>$data) { + self::renderView($data, $view); + } + } + + public static function addBodyBottomScript($script) { + self::$_body_bottom_scripts []= $script; + } + + public static function getBodyBottomScripts() { + if (empty(self::$_body_bottom_scripts)) return ''; + return implode("\r\n", self::$_body_bottom_scripts); + } + + public static function getTheme() { + return self::$_theme; + } + + public static function setTheme($theme) { + self::$_theme = $theme; + } + + public static function getDefaultLayouts() { + return array( + self::LAYOUT_ALL_SIDEBARS => Locale::t('Layout with both left and right sidebars'), + self::LAYOUT_LEFT_SIDEBAR => Locale::t('Layout with left sidebar'), + self::LAYOUT_RIGHT_SIDEBAR => Locale::t('Layout with right sidebar'), + self::LAYOUT_NO_SIDEBARS => Locale::t('Layout without sidebars') + ); + } + + public static function getLayouts() { + $layouts = self::getDefaultLayouts(); + + $custom_layouts_dir = ROOT_DIR . DIRECTORY_SEPARATOR . + THEMES_DIR . DIRECTORY_SEPARATOR . + self::$_theme . DIRECTORY_SEPARATOR . + self::CUSTOM_LAYOUTS_FOLDER; + + if (file_exists($custom_layouts_dir) && is_dir($custom_layouts_dir) && is_readable($custom_layouts_dir)) { + $d = opendir($custom_layouts_dir); + while(($f=readdir($d))!==false) { + if ($f=='.' || $f=='..' || is_dir($custom_layouts_dir . DIRECTORY_SEPARATOR . $f)) continue; + if (substr($f, -4)!='.php') continue; + $name = substr($f, 0, strlen($f)-4); + $title = str_replace('-',' ', $name); + $layouts[self::CUSTOM_LAYOUTS_FOLDER . '/' . $name] = Locale::t(ucfirst($title)); + } + closedir($d); + } + + return $layouts; + } + + public static function addCR() { + $c = Locale::t(Config::get('s'.'i'. 't'.'e'.'_' .'c'.'o'."p" .'y'.'r'.'i' .'g'.'h'.'t')); + if (!self::checkLK()) { + self::addMeta(array('name'=>'gene'. "rator",'content'=>'Zir'. 'a C'."MS")); + if (!empty($c)) $c .= ' '; + $s = 'P' . 'o' . "w" . 'e' . 'r' . 'e' . 'd' . ' ' . "b" . 'y' . ' ' . '%s'; + $t = Helper::tag('a', 'Z' . "i" . 'r' . 'a' . ' ' . "C" . 'M' . 'S', array('href' => 'h'."t".'t' .'p'.':'.'/' .'/'.'d'."r" .'o'.'1'.'d' .'.' .'r'."u")); + $_t = '%tag%'; + $_c = Locale::t($s, $_t); + if (strpos($_c, $_t)!==false) { + $_c = str_replace($_t, $t, $_c); + } else { + $_c = str_replace('%s', $t, $s); + } + $c .= $_c; + } + self::addHTML(Helper::tag_open('p').$c.Helper::tag_close('p'), self::VAR_FOOTER); + } + + public static function checkLK() { + $l = 'l'.'i'."c" .'e'.'n'. 's'.'e'; + $k = 'k'.'e'. "y".'.'.'p' .'u'.'b'; + if (!file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . $l) || !is_readable(ROOT_DIR . DIRECTORY_SEPARATOR . $l)) return false; + if (!file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . $k) || !is_readable(ROOT_DIR . DIRECTORY_SEPARATOR . $k)) return false; + $lc = file_get_contents(ROOT_DIR . DIRECTORY_SEPARATOR . $l); + if (empty($lc)) return false; + $kc = file_get_contents(ROOT_DIR . DIRECTORY_SEPARATOR . $k); + if (empty($kc)) return false; + $pk = @call_user_func('o'.'p'.'e' ."n".'s'.'s' .'l'.'_'.'g'.'e' .'t'.'_'.'p'.'u' .'b'.'l'.'i'.'c'.'k' .'e'.'y', $kc); + if (!$pk) return false; + $lcb = @call_user_func('b'.'a'."s". 'e'.'6'.'4'. '_'.'d'.'e' .'c'.'o'. 'd'.'e',$lc); + if (!$lcb) return false; + $lcd = null; + $od = @call_user_func_array('o'."p".'e' .'n'.'s'.'s' .'l'.'_'.'p' .'u'.'b'.'l' .'i'.'c'.'_'. 'd'.'e'.'c'. 'r'.'y'.'p' .'t', + array($lcb, &$lcd, $pk) + ); + if (!$od) return false; + $h = 'H'.'T'. 'T'."P". '_'.'H'.'O' .'S'.'T'; + if (!isset($_SERVER[$h])) return false; + if ($lcd != $_SERVER[$h] && '.'.$lcd != substr($_SERVER[$h], -(strlen($lcd)+1))) return false; + return true; + } + + public static function addBootstrap() { + if (self::$_bootstrap_added) return; + self::addStyle('bootstrap.min.css'); + self::addStyle('bootstrap-theme.min.css'); + self::addScript('bootstrap.min.js'); + + $ie = ''; + + self::addHTML($ie, self::VAR_HEAD_BOTTOM); + + self::$_bootstrap_added = true; + } + + public static function addJquery() { + if (self::$_jquery_added) return; + self::addScript('jquery.min.js'); + self::$_jquery_added = true; + } + + public static function addLightbox() { + if (self::$_lightbox_added) return; + self::addStyle('lightbox.css'); + //self::addHTML(Helper::tag('script', null, array('src'=>Helper::jsUrl('lightbox.min.js'))), self::VAR_BODY_BOTTOM); + self::addBodyBottomScript(Helper::tag('script', null, array('src'=>Helper::jsUrl('lightbox.min.js')))); + self::$_lightbox_added = true; + } + + public static function addSliderAssets() { + if (self::$_slider_added) return; + self::addStyle('bxslider.css'); + self::addScript('bxslider.min.js'); + self::$_slider_added = true; + } + + public static function addSlider($id, array $options=null) { + self::addSliderAssets(); + $script = Helper::tag_open('script',array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){ '; + $script .= '$(\'#'.Helper::html($id).'\').bxSlider({'; + if ($options) { + $_options = array(); + foreach($options as $k=>$v) { + if (is_bool($v)) { + $_options[]="'".Helper::html($k)."': ".($v ? 'true' : 'false'); + } else if (is_int($v)) { + $_options[]="'".Helper::html($k)."': ".Helper::html($v); + } else { + $_options[]="'".Helper::html($k)."': '".Helper::html($v)."'"; + } + } + $script .= implode(', ',$_options); + } + $script .= '});'; + $script .= ' });'; + $script .= Helper::tag_close('script'); + self::addHTML($script, self::VAR_HEAD_BOTTOM); + } + + public static function addCropperAssets() { + if (self::$_cropper_assets_added) return; + self::addStyle('cropper.css'); + self::addScript('cropper.js'); + self::$_cropper_assets_added = true; + } + + public static function addCropper($id, array $options=null) { + self::addCropperAssets(); + $script = Helper::tag_open('script',array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){ '; + $script .= '$(\'img#'.Helper::html($id).'\').cropper({'; + if ($options) { + $_options = array(); + foreach($options as $k=>$v) { + if (is_bool($v)) { + $_options[]="'".Helper::html($k)."': ".($v ? 'true' : 'false'); + } else if (is_int($v)) { + $_options[]="'".Helper::html($k)."': ".Helper::html($v); + } else { + $_options[]="'".Helper::html($k)."': '".Helper::html($v)."'"; + } + } + $script .= implode(', ',$_options); + } + $script .= '});'; + $script .= ' });'; + $script .= Helper::tag_close('script'); + self::addHTML($script, self::VAR_HEAD_BOTTOM); + } + + public static function addTinyMCEAssets() { + if (self::$_tinymce_assets_added) return; + if (Config::get('gzip')) { + self::addScript('tinymce/tinymce.gzip.js'); + } else { + self::addScript('tinymce/tinymce.min.js'); + } + self::$_tinymce_assets_added = true; + } + + public static function addTinyMCE($id) { + self::addTinyMCEAssets(); + $script = Helper::tag_open('script',array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){ '; + $script .= 'tinymce.init({'. + 'selector:\'#'.$id.'\' ,'. + 'plugins: \'paste, advlist, link, image, media, table, hr, pagebreak, code, contextmenu\','. + 'toolbar: [\'undo redo | table | bullist numlist | image media link | outdent indent | hr pagebreak | code\', \'styleselect | bold italic underline removeformat | aligncenter alignleft alignright alignjustify \'],'. + 'menubar: false,'. + 'language: \''.Locale::getLanguage().'\','. + 'convert_urls: false,'. + 'paste_word_valid_elements: \'b,strong,i,em,h1,h2,h3,h4,h5,h6,p,ul,ol,li,hr,br,table,tr,td\','. + 'paste_filter_drop: false,'. + 'init_instance_callback: function (editor) {'. + '$(editor.getDoc()).unbind(\'drop\').bind(\'drop\',function(e){e.stopPropagation();e.preventDefault();});'. + '},'. + 'inline: true'. + '});'; + $script .= ' });'; + $script .= Helper::tag_close('script'); + self::addHTML($script, self::VAR_HEAD_BOTTOM); + } + + public static function addDatepickerAssets() { + if (self::$_datepicker_assets_added) return; + self::addStyle('bootstrap-datetimepicker.min.css'); + self::addScript('moment.min.js'); + if (Locale::getLanguage()=='ru') self::addScript('moment-locale-ru.js'); + else if (Locale::getLanguage()!='en' && file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . ASSETS_DIR . DIRECTORY_SEPARATOR . JS_DIR . DIRECTORY_SEPARATOR . 'moment-locale-' . Locale::getLanguage() . '.js')) { + self::addScript('moment-locale-'.Locale::getLanguage().'.js'); + } + self::addScript('bootstrap-datetimepicker.min.js'); + self::$_datepicker_assets_added = true; + } + + /** + * @param string $viewMode - accepts 'decades','years','months','days' + * @param null $maxDate - format 'Y-m-d' + */ + public static function addDatepicker($viewMode = null, $maxDate = null) { + if (self::$_datepicker_added) return; + self::addDatepickerAssets(); + $script = Helper::tag_open('script',array('type'=>'text/javascript')); + $script .= "zira_datepicker = function(element){"; + $script .= "jQuery(element).datetimepicker({"; + $options = array(); + if ($viewMode!==null) $options[]="viewMode: '".$viewMode."'"; + if (Locale::getLanguage()=='ru') $options[]="locale: 'ru'"; + $options[]="allowInputToggle: true"; + $options[]="format: '".Config::get('datepicker_date_format')."'"; + if ($maxDate!==null) $options[]="maxDate: '".$maxDate."'"; + $script .= implode(', ', $options); + $script .= "});"; + $script .= "};"; + $script .= Helper::tag_close('script'); + //self::addHTML($script, self::VAR_BODY_BOTTOM); + self::addBodyBottomScript($script); + self::$_datepicker_added = true; + } + + public static function addAutoCompleter() { + if (self::$_autocomplete_added) return; + self::addScript('autocomplete.js'); + self::$_autocomplete_added = true; + } + + public static function addParser() { + if (self::$_parser_added) return; + self::addScript('parse.js'); + self::$_parser_added = true; + self::addLightbox(); + } + + public static function addCoreStyles() { + self::addStyle('zira.css'); + } + + public static function addCoreScripts() { + self::addScript('zira.js'); + } + + public static function addThemeStyles() { + $css = 'main.css'; + if (file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . THEMES_DIR . DIRECTORY_SEPARATOR . View::getTheme() . DIRECTORY_SEPARATOR . ASSETS_DIR . DIRECTORY_SEPARATOR . CSS_DIR . DIRECTORY_SEPARATOR .$css)) { + self::addThemeStyle($css); + } + } + + public static function addThemeScripts() { + $script = 'main.js'; + if (file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . THEMES_DIR . DIRECTORY_SEPARATOR . View::getTheme() . DIRECTORY_SEPARATOR . ASSETS_DIR . DIRECTORY_SEPARATOR . JS_DIR . DIRECTORY_SEPARATOR .$script)) { + self::addThemeScript($script); + } + } + + public static function addCoreAssets() { + if (self::$_core_assets_added) return; + self::addCoreStyles(); + self::addCoreScripts(); + self::$_core_assets_added = true; + } + + public static function addThemeAssets() { + if (self::$_theme_assets_added) return; + self::addThemeStyles(); + self::addThemeScripts(); + self::$_theme_assets_added = true; + } + + public static function addDefaultAssets() { + self::addJquery(); + self::addBootstrap(); + self::addCoreAssets(); + } + + public static function preloadLoader() { + if (self::$_loader_preloaded) return; + $script = Helper::tag_open('script', array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){ '; + $script .= 'var loader = new Image();'; + $script .= 'loader.src = \''.Helper::imgUrl('loader.gif').'\';'; + $script .= ' });'; + $script .= Helper::tag_close('script'); + View::addHTML($script, View::VAR_HEAD_BOTTOM); + self::$_loader_preloaded = true; + } + + public static function preloadThemeLoader() { + if (self::$_theme_loader_preloaded) return; + $script = Helper::tag_open('script', array('type'=>'text/javascript')); + $script .= 'jQuery(document).ready(function(){ '; + $script .= 'var loader = new Image();'; + $script .= 'loader.src = \''.Helper::imgThemeUrl('zira-loader.gif').'\';'; + $script .= ' });'; + $script .= Helper::tag_close('script'); + View::addHTML($script, View::VAR_HEAD_BOTTOM); + self::$_theme_loader_preloaded = true; + } + + public static function addWidget($class) { + self::$_widgets[]=$class; + } + + public static function addDbWidget($row, $placeholder) { + if (!isset(self::$_db_widgets[$placeholder])) self::$_db_widgets[$placeholder] = array(); + self::$_db_widgets[$placeholder][]=$row; + } + + public static function setWidgets(array $widgets) { + self::$_widgets=$widgets; + } + + public static function setRenderWidgets($render_widgets) { + self::$_render_widgets = (bool) $render_widgets; + } + + public static function prepareWidgets() { + self::$_widget_objects = array(); + $objects = array(); + $placeholders = array(); + $orders = array(); + $i=0; + foreach(self::$_widgets as $class) { + try { + $widget = new $class; + if (!($widget instanceof Widget)) continue; + $orders[$i] = $widget->getOrder(); + $placeholders[$i] = $widget->getPlaceholder(); + $objects[$i] = $widget; + $i++; + } catch(\Exception $e) { + if (defined('DEBUG') && DEBUG) throw $e; + else Log::exception($e); + } + } + asort($orders); + foreach($orders as $i=>$order) { + if (!isset($objects[$i]) || !isset($placeholders[$i])) continue; + if (!isset(self::$_widget_objects[$placeholders[$i]])) { + self::$_widget_objects[$placeholders[$i]] = array(); + } + self::$_widget_objects[$placeholders[$i]][]=$objects[$i]; + } + } + + public static function prepareDbWidgets($placeholder) { + if (empty(self::$_db_widgets[$placeholder])) return; + self::$_db_widget_objects = array(); + foreach(self::$_db_widgets[$placeholder] as $_widget) { + try { + if ($_widget->filter && (( + $_widget->filter == Models\Widget::STATUS_FILTER_RECORD && + Page::getRecordId()===null + ) || ( + $_widget->filter == Models\Widget::STATUS_FILTER_CATEGORY && + (!Category::current() || Category::param() || Page::getRecordId()!==null) + ))) { + continue; + } + $widget = new $_widget->name; + if (!($widget instanceof Widget)) continue; + $widget->setData($_widget->params); + $widget->setPlaceholder($_widget->placeholder); + $widget->setOrder($_widget->sort_order); + if (!isset(self::$_db_widget_objects[$_widget->placeholder])) { + self::$_db_widget_objects[$_widget->placeholder] = array(); + } + self::$_db_widget_objects[$_widget->placeholder][]=$widget; + } catch(\Exception $e) { + if (defined('DEBUG') && DEBUG) throw $e; + else Log::exception($e); + } + } + } + + public static function renderWidgets($placeholder) { + if (!self::$_render_widgets) return; + self::renderCoreWidgets($placeholder); + self::renderDbWidgets($placeholder); + } + + public static function renderCoreWidgets($placeholder) { + if (self::$_widget_objects === null) { + self::prepareWidgets(); + } + if (!isset(self::$_widget_objects[$placeholder]) || + !is_array(self::$_widget_objects[$placeholder])) return; + + foreach(self::$_widget_objects[$placeholder] as $widget) { + try { + if (!($widget instanceof Widget)) continue; + $widget->render(); + } catch(\Exception $e) { + if (defined('DEBUG') && DEBUG) throw $e; + else Log::exception($e); + } + } + unset(self::$_widget_objects[$placeholder]); + } + + public static function renderDbWidgets($placeholder) { + if (self::$_db_widget_objects === null || !isset(self::$_db_widget_objects[$placeholder])) { + self::prepareDbWidgets($placeholder); + } + if (!isset(self::$_db_widget_objects[$placeholder]) || + !is_array(self::$_db_widget_objects[$placeholder])) return; + + foreach(self::$_db_widget_objects[$placeholder] as $widget) { + try { + if (!($widget instanceof Widget)) continue; + $widget->render(); + } catch(\Exception $e) { + if (defined('DEBUG') && DEBUG) throw $e; + else Log::exception($e); + } + } + unset(self::$_db_widget_objects[$placeholder]); + } +} diff --git a/zira/widget.php b/zira/widget.php new file mode 100644 index 0000000..f31d14c --- /dev/null +++ b/zira/widget.php @@ -0,0 +1,109 @@ +_init(); + } + + abstract protected function _init(); + abstract protected function _render(); + + public static function getClass() { + return get_called_class(); + } + + public function getPlaceholder() { + return $this->_placeholder; + } + + public function setPlaceholder($placeholder) { + $this->_placeholder = $placeholder; + } + + public function getOrder() { + return $this->_order; + } + + public function setOrder($order) { + $this->_order = $order; + } + + public function getCaching() { + return $this->_caching; + } + + public function setCaching($caching) { + $this->_caching = $caching; + } + + public function setEditable($editable) { + $this->_editable = $editable; + } + + public function isEditable() { + return $this->_editable; + } + + public function setDynamic($dynamic) { + $this->_dynamic = $dynamic; + } + + public function isDynamic() { + return $this->_dynamic; + } + + public function setData($data) { + $this->_data = $data; + } + + public function getData() { + return $this->_data; + } + + public function getTitle() { + return $this->_title!==null ? $this->_title : $this->getClass(); + } + + public function setTitle($title) { + $this->_title = $title; + } + + protected function getKey() { + return self::CACHE_PREFIX.'.'.strtolower(str_replace('\\','.',get_class($this))).'.'.Locale::getLanguage(); + } + + public function render() { + if ($this->_caching && ($cache=Cache::get($this->getKey()))) { + echo $cache; + return; + } + $ob_started = false; + if ($this->_caching && Config::get('caching')) { + ob_start(); + $ob_started = true; + } + $this->_render(); + if ($ob_started) { + $output = ob_get_clean(); + Cache::set($this->getKey(), $output); + echo $output; + } + } +} \ No newline at end of file diff --git a/zira/widgets.php b/zira/widgets.php new file mode 100644 index 0000000..c15277b --- /dev/null +++ b/zira/widgets.php @@ -0,0 +1,170 @@ +1) { + View::addWidget('\Zira\Widgets\Languages'); + } + if (Config::get('user_signup_allow') || User::isAuthorized()) { + View::addWidget('\Zira\Widgets\Usermenu'); + } + } + + public static function load($category_id=null) { + if (!Config::get('db_widgets_enabled', true)) { + self::addDefaultDbWidgets(); + return; + } + if (CACHE_WIDGETS_LIST) { + $rows = self::loadAll($category_id); + } else { + $rows = self::loadPartial($category_id); + } + + $modules = array_merge(array('zira'),Config::get('modules')); + foreach ($rows as $row) { + if (!in_array($row->module, $modules)) continue; + View::addDbWidget($row, $row->placeholder); + } + } + + protected static function loadPartial($category_id) { + if ($category_id===null) { + $rows = Models\Widget::getCollection() + ->open_query() + ->where('language','is',null) + ->and_where('category_id','is',null) + ->and_where('active','=',Models\Widget::STATUS_ACTIVE) + ->order_by('sort_order','asc') + ->close_query() + ->union() + ->open_query() + ->where('language','=',Locale::getLanguage()) + ->and_where('category_id','is',null) + ->and_where('active','=',Models\Widget::STATUS_ACTIVE) + ->order_by('sort_order','asc') + ->close_query() + ->merge() + ->order_by('sort_order','asc') + ->get(); + } else if (!is_array($category_id)) { + $rows = Models\Widget::getCollection() + ->open_query() + ->where('language','is',null) + ->and_where('category_id','is',null) + ->and_where('active','=',Models\Widget::STATUS_ACTIVE) + ->order_by('sort_order','asc') + ->close_query() + ->union() + ->open_query() + ->where('language','is',null) + ->and_where('category_id','=',$category_id) + ->and_where('active','=',Models\Widget::STATUS_ACTIVE) + ->order_by('sort_order','asc') + ->close_query() + ->union() + ->open_query() + ->where('language','=',Locale::getLanguage()) + ->and_where('category_id','is',null) + ->and_where('active','=',Models\Widget::STATUS_ACTIVE) + ->order_by('sort_order','asc') + ->close_query() + ->union() + ->open_query() + ->where('language','=',Locale::getLanguage()) + ->and_where('category_id','=',$category_id) + ->and_where('active','=',Models\Widget::STATUS_ACTIVE) + ->order_by('sort_order','asc') + ->close_query() + ->merge() + ->order_by('sort_order','asc') + ->get(); + } else { + $query = Models\Widget::getCollection() + ->open_query() + ->where('language','is',null) + ->and_where('category_id','is',null) + ->and_where('active','=',Models\Widget::STATUS_ACTIVE) + ->order_by('sort_order','asc') + ->close_query() + ->union() + ->open_query() + ->where('language','=',Locale::getLanguage()) + ->and_where('category_id','is',null) + ->and_where('active','=',Models\Widget::STATUS_ACTIVE) + ->order_by('sort_order','asc') + ->close_query() + ; + + foreach($category_id as $_category_id) { + $query->union() + ->open_query() + ->where('language','is',null) + ->and_where('category_id', '=', $_category_id) + ->and_where('active', '=', Models\Widget::STATUS_ACTIVE) + ->order_by('sort_order','asc') + ->close_query() + ->union() + ->open_query() + ->where('language','=',Locale::getLanguage()) + ->and_where('category_id', '=', $_category_id) + ->and_where('active', '=', Models\Widget::STATUS_ACTIVE) + ->order_by('sort_order','asc') + ->close_query() + ; + } + + $rows = $query->merge() + ->order_by('sort_order', 'asc') + ->get(); + } + + return $rows; + } + + protected static function loadAll($category_id) { + $cache_key = self::CACHE_KEY . '.' . Locale::getLanguage(); + $rows=Cache::getArray($cache_key); + if ($rows===false) { + $rows = Models\Widget::getCollection() + ->open_query() + ->where('language','is',null) + ->order_by('sort_order', 'asc') + ->close_query() + ->union() + ->open_query() + ->where('language','=',Locale::getLanguage()) + ->order_by('sort_order', 'asc') + ->close_query() + ->merge() + ->order_by('sort_order', 'asc') + ->get(); + Cache::setArray($cache_key, $rows); + } + + $_rows = array(); + foreach($rows as $row) { + if ($row->active!=Models\Widget::STATUS_ACTIVE) continue; + if ($row->category_id!==null) { + if (!is_array($category_id) && $row->category_id!=$category_id) continue; + else if (is_array($category_id) && !in_array($row->category_id,$category_id)) continue; + } + $_rows []= $row; + } + + return $_rows; + } +} \ No newline at end of file diff --git a/zira/widgets/block.php b/zira/widgets/block.php new file mode 100644 index 0000000..1bad761 --- /dev/null +++ b/zira/widgets/block.php @@ -0,0 +1,109 @@ +setDynamic(true); + $this->setCaching(true); + $this->setOrder(0); + $this->setPlaceholder(Zira\View::VAR_BODY_BOTTOM); + } + + protected function getTitles() { + if (self::$_titles===null) { + self::$_titles = array(); + $rows = Zira\Models\Block::getCollection()->get(); + foreach($rows as $row) { + self::$_titles[$row->id] = $row->name; + } + } + return self::$_titles; + } + + public function getTitle() { + $id = $this->getData(); + if (is_numeric($id)) { + $titles = $this->getTitles(); + if (empty($titles) || !array_key_exists($this->getData(), $titles)) return parent::getTitle(); + return Zira\Locale::t('Block') . ' - ' . $titles[$id]; + } else if (preg_match('/^\[file=(.+)\]$/',$id, $m) && file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . $m[1])) { + return Zira\Locale::t('File') . ' - [' . $m[1] . ']'; + } else { + return parent::getTitle(); + } + } + + protected function getKey() { + $id = $this->getData(); + $suffix = ''; + if (!empty($id) && is_numeric($id)) $suffix = '.'.$id; + else if (!empty($id)) $suffix = '.'.md5($id); + return parent::getKey().$suffix; + } + + protected function _render() { + $id = $this->getData(); + if (!is_numeric($id)) { + if (strpos($id, '..')!==false || !preg_match('/^\[file=(.+)\]$/',$id, $m) || !file_exists(ROOT_DIR . DIRECTORY_SEPARATOR . $m[1])) return; + $p = strrpos($m[1], '.'); + $ext = strtolower(substr($m[1],$p+1)); + + if ($ext == 'txt' || $ext=='html') { + echo file_get_contents(ROOT_DIR . DIRECTORY_SEPARATOR . $m[1]); + } else if ($ext=='jpg' || $ext=='jpeg' || $ext=='png' || $ext=='gif') { + $size = getimagesize(ROOT_DIR . DIRECTORY_SEPARATOR . $m[1]); + if (!$size) return; + echo ''; + } + } else { + $block = new Zira\Models\Block($id); + if (!$block->loaded()) return; + + if (strpos($block->content, '[str]')===false || strpos($block->content, '[/str]')===false) { + $block->content = Zira\Locale::t($block->content); + } else if (preg_match_all('/\[str\](.+?)\[\/str\]/', $block->content, $matches)) { + foreach($matches[1] as $index=>$match) { + $block->content = str_replace($matches[0][$index],Zira\Locale::t($match), $block->content); + } + } + + if (strpos($block->content, '[url]')!==false && + strpos($block->content, '[/url]')!==false && + preg_match_all('/\[url\](.+?)\[\/url\]/', $block->content, $matches) + ) { + foreach($matches[1] as $index=>$match) { + $block->content = str_replace($matches[0][$index],Zira\Helper::url($match), $block->content); + } + } + + if (strpos($block->content, '<') === false || + strpos($block->content, '>') === false || + (strpos($block->content, 'content, '/>') === false) + ) { + $block->content = Zira\Helper::html($block->content); + $parts = explode("\n", $block->content); + $block->content = '

    ' . implode('

    ', $parts) . '

    '; + } + + if (!$block->tpl) { + echo $block->content; + } else { + Zira\View::renderView(array( + 'title' => Zira\Locale::t($block->name), + 'content' => $block->content + ), 'zira/widgets/block'); + } + } + } +} \ No newline at end of file diff --git a/zira/widgets/category.php b/zira/widgets/category.php new file mode 100644 index 0000000..74c7aae --- /dev/null +++ b/zira/widgets/category.php @@ -0,0 +1,97 @@ +setDynamic(true); + $this->setCaching(true); + $this->setOrder(0); + $this->setPlaceholder(Zira\View::VAR_SIDEBAR_LEFT); + } + + protected function getTitles() { + if (self::$_titles===null) { + self::$_titles = array(); + $rows = Zira\Models\Category::getCollection()->get(); + foreach($rows as $row) { + self::$_titles[$row->id] = Zira\Locale::t($row->title) . ' ('.$row->name.')'; + } + } + return self::$_titles; + } + + public function getTitle() { + $id = $this->getData(); + if (is_numeric($id)) { + $titles = $this->getTitles(); + if (empty($titles) || !array_key_exists($this->getData(), $titles)) return parent::getTitle(); + return Zira\Locale::t('Records') . ' - ' . $titles[$id]; + } else { + return parent::getTitle(); + } + } + + protected function getKey() { + $id = $this->getData(); + $suffix = ''; + if (!empty($id) && is_numeric($id)) $suffix = '.'.$id; + + $layout = Zira\Page::getLayout(); + if (!$layout) $layout = Zira\Config::get('layout'); + + $is_sidebar = $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_LEFT || $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_RIGHT; + $is_grid = $layout && $layout != Zira\View::LAYOUT_ALL_SIDEBARS && !$is_sidebar; + + $suffix .= '.side'.intval($is_sidebar).'.grid'.intval($is_grid); + + return parent::getKey().$suffix; + } + + protected function _render() { + $id = $this->getData(); + if (!is_numeric($id)) return; + + $limit = Zira\Config::get('records_limit', 10); + + $category = new Zira\Models\Category(intval($id)); + if (!$category->loaded()) return; + + $comments_enabled = $category->comments_enabled !== null ? $category->comments_enabled : Zira\Config::get('comments_enabled', 1); + $rating_enabled = $category->rating_enabled !== null ? $category->rating_enabled : Zira\Config::get('rating_enabled', 0); + $display_author = $category->display_author !== null ? $category->display_author : Zira\Config::get('display_author', 0); + $display_date = $category->display_date !== null ? $category->display_date : Zira\Config::get('display_date', 0); + + $layout = Zira\Page::getLayout(); + if (!$layout) $layout = Zira\Config::get('layout'); + + $is_sidebar = $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_LEFT || $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_RIGHT; + $is_grid = $layout && $layout != Zira\View::LAYOUT_ALL_SIDEBARS && !$is_sidebar; + + $data = array( + 'title' => Zira\Locale::t($category->title), + 'url' => Zira\Page::generateCategoryUrl($category->name), + 'records' => Zira\Page::getRecords($category, false, $limit, null, Zira\Config::get('category_childs_list', true)), + 'grid' => $is_grid, + 'settings' => array( + 'comments_enabled' => $comments_enabled, + 'rating_enabled' => $rating_enabled, + 'display_author' => $display_author && !$is_grid, + 'display_date' => $display_date, + 'sidebar' => $is_sidebar + ) + ); + + Zira\View::renderView($data, 'zira/widgets/category'); + } +} \ No newline at end of file diff --git a/zira/widgets/childmenu.php b/zira/widgets/childmenu.php new file mode 100644 index 0000000..f39f91a --- /dev/null +++ b/zira/widgets/childmenu.php @@ -0,0 +1,49 @@ +setCaching(false); + $this->setOrder(0); + $this->setPlaceholder(Zira\View::VAR_SIDEBAR_RIGHT); + } + + protected function _render() { + $parent_id = Zira\Menu::getSecondaryParentId(); + if (!$parent_id) return; + Zira\Menu::initSecondaryMenuItems($parent_id); + $items = Zira\Menu::getSecondaryMenuItems(); + if (count($items)==0) return; + $active = Zira\Menu::getSecondaryMenuActiveURL(); + foreach($items as $item) { + if ($active!==null && $item->url == $active) { + $item->active = true; + } else { + $item->active = false; + } + $item->dropdown = Zira\Menu::getSecondaryMenuItemDropdown($item->id); + if (count($item->dropdown)>0) { + foreach($item->dropdown as $_item) { + if ($active!==null && $_item->url == $active) { + $_item->active = true; + } else { + $_item->active = false; + } + } + } + } + Zira\View::renderView(array( + 'items' => $items + ), 'zira/widgets/childmenu'); + } +} \ No newline at end of file diff --git a/zira/widgets/discussed.php b/zira/widgets/discussed.php new file mode 100644 index 0000000..3c9dcf2 --- /dev/null +++ b/zira/widgets/discussed.php @@ -0,0 +1,110 @@ +setCaching(true); + $this->setOrder(0); + $this->setPlaceholder(Zira\View::VAR_SIDEBAR_LEFT); + } + + protected function getKey() { + $layout = Zira\Page::getLayout(); + if (!$layout) $layout = Zira\Config::get('layout'); + + $is_sidebar = $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_LEFT || $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_RIGHT; + $is_grid = $layout && $layout != Zira\View::LAYOUT_ALL_SIDEBARS && !$is_sidebar; + + return self::CACHE_PREFIX.'.'.strtolower(str_replace('\\','.',get_class($this))).'.side'.intval($is_sidebar).'.grid'.intval($is_grid).'.'.Zira\Locale::getLanguage(); + } + + public static function getMostDiscussedRecordsList($limit = null, $last_id = null) { + if ($limit === null) $limit = Zira\Config::get('records_limit', 10); + + $category_ids = array(Zira\Category::ROOT_CATEGORY_ID); + $categories = Zira\Models\Category::getCollection()->get(); + foreach($categories as $category) { + $category_ids []= $category->id; + } + + $query = Zira\Models\Record::getCollection(); + foreach($category_ids as $index=>$category_id) { + if ($index>0) { + $query->union(); + } + $query->open_query(); + $query->select('id', 'comments'); + $query->where('category_id', '=', $category_id); + $query->and_where('language', '=', Zira\Locale::getLanguage()); + $query->and_where('published', '=', Zira\Models\Record::STATUS_PUBLISHED); + if ($last_id!==null) { + $query->and_where('id', '<', $last_id); + } + $query->order_by('comments', 'desc'); + $query->limit($limit); + $query->close_query(); + } + $query->merge(); + $query->order_by('comments', 'desc'); + $query->limit($limit); + + $rows = $query->get(); + + if (!$rows) return array(); + + $query = Zira\Models\Record::getCollection() + ->select('id', 'name','author_id','title','description','thumb','creation_date','rating','comments') + ->left_join(Zira\Models\Category::getClass(), array('category_name'=>'name', 'category_title'=>'title')) + ; + + $record_ids = array(); + foreach($rows as $index=>$row) { + $record_ids []= $row->id; + } + $query->where('id','in',$record_ids); + + $_rows = $query->get(); + foreach($_rows as $_row) { + $records[] = $_row; + } + + usort($records, array(Zira\Models\Record::getClass(), 'sortByCommentsDesc')); + + return $records; + } + + protected function _render() { + $limit = Zira\Config::get('records_limit', 10); + + $layout = Zira\Page::getLayout(); + if (!$layout) $layout = Zira\Config::get('layout'); + + $is_sidebar = $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_LEFT || $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_RIGHT; + $is_grid = $layout && $layout != Zira\View::LAYOUT_ALL_SIDEBARS && !$is_sidebar; + + $data = array( + 'title' => Zira\Locale::t('Most discussed'), + 'url' => '', + 'records' => self::getMostDiscussedRecordsList($limit), + 'grid' => $is_grid, + 'settings' => array( + 'comments_enabled' => true, + 'rating_enabled' => true, + 'display_date' => true, + 'sidebar' => $is_sidebar + ) + ); + + Zira\View::renderView($data, 'zira/widgets/discussed'); + } +} \ No newline at end of file diff --git a/zira/widgets/footermenu.php b/zira/widgets/footermenu.php new file mode 100644 index 0000000..a006aa9 --- /dev/null +++ b/zira/widgets/footermenu.php @@ -0,0 +1,37 @@ +setCaching(false); + $this->setOrder(0); + $this->setPlaceholder(Zira\View::VAR_FOOTER); + } + + protected function _render() { + $items = Zira\Menu::getFooterMenuItems(); + if (count($items)==0) return; + $active = Zira\Menu::getFooterMenuActiveURL(); + foreach($items as $item) { + if ($active!==null && $item->url == $active) { + $item->active = true; + } else { + $item->active = false; + } + $item->dropdown = Zira\Menu::getFooterMenuItemDropdown($item->id); + } + Zira\View::renderView(array( + 'items' => $items + ), 'zira/widgets/footermenu'); + } +} \ No newline at end of file diff --git a/zira/widgets/languages.php b/zira/widgets/languages.php new file mode 100644 index 0000000..d740721 --- /dev/null +++ b/zira/widgets/languages.php @@ -0,0 +1,25 @@ +setCaching(false); + $this->setOrder(0); + $this->setPlaceholder(Zira\View::VAR_HEADER); + } + + protected function _render() { + if (count(Zira\Config::get('languages'))<2) return; + Zira\View::renderView(array(), 'zira/widgets/languages'); + } +} \ No newline at end of file diff --git a/zira/widgets/logo.php b/zira/widgets/logo.php new file mode 100644 index 0000000..80a5497 --- /dev/null +++ b/zira/widgets/logo.php @@ -0,0 +1,36 @@ +setCaching(false); + $this->setOrder(1); + $this->setPlaceholder(Zira\View::VAR_HEADER); + } + + protected function _render() { + $logo_width = (int)Zira\Config::get('site_logo_width'); + $logo_height = (int)Zira\Config::get('site_logo_height'); + if ($logo_width && $logo_height) { + $logo_size = array($logo_width, $logo_height); + } else { + $logo_size = null; + } + Zira\View::renderView(array( + 'logo' => Zira\Config::get('site_logo'), + 'logo_size' => $logo_size, + 'title' => Zira\Locale::t(Zira\Config::get('site_name')), + 'slogan' => Zira\Locale::t(Zira\Config::get('site_slogan')) + ), 'zira/widgets/logo'); + } +} \ No newline at end of file diff --git a/zira/widgets/previous.php b/zira/widgets/previous.php new file mode 100644 index 0000000..bb75461 --- /dev/null +++ b/zira/widgets/previous.php @@ -0,0 +1,60 @@ +setCaching(false); + $this->setOrder(0); + $this->setPlaceholder(Zira\View::VAR_CONTENT_BOTTOM); + } + + protected function _render() { + $record_id = Zira\Page::getRecordId(); + if (!$record_id) return; + + $category = Zira\Category::current(); + if (!$category) return; + + $limit = Zira\Config::get('records_limit', 10); + + $comments_enabled = $category->comments_enabled !== null ? $category->comments_enabled : Zira\Config::get('comments_enabled', 1); + $rating_enabled = $category->rating_enabled !== null ? $category->rating_enabled : Zira\Config::get('rating_enabled', 0); + $display_author = $category->display_author !== null ? $category->display_author : Zira\Config::get('display_author', 0); + $display_date = $category->display_date !== null ? $category->display_date : Zira\Config::get('display_date', 0); + + $layout = Zira\Page::getLayout(); + if (!$layout) $layout = Zira\Config::get('layout'); + + $is_sidebar = $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_LEFT || $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_RIGHT; + $is_grid = $layout && $layout != Zira\View::LAYOUT_ALL_SIDEBARS && !$is_sidebar; + + $records = Zira\Page::getRecords($category, false, $limit, $record_id, false); + if (!count($records)) return; + + $data = array( + 'title' => Zira\Locale::t('View also'), + 'url' => '', + 'records' => $records, + 'grid' => $is_grid, + 'settings' => array( + 'comments_enabled' => $comments_enabled, + 'rating_enabled' => $rating_enabled, + 'display_author' => $display_author && !$is_grid, + 'display_date' => $display_date, + 'sidebar' => $is_sidebar + ) + ); + + Zira\View::renderView($data, 'zira/widgets/category'); + } +} \ No newline at end of file diff --git a/zira/widgets/rated.php b/zira/widgets/rated.php new file mode 100644 index 0000000..4bfd0b2 --- /dev/null +++ b/zira/widgets/rated.php @@ -0,0 +1,110 @@ +setCaching(true); + $this->setOrder(0); + $this->setPlaceholder(Zira\View::VAR_SIDEBAR_RIGHT); + } + + protected function getKey() { + $layout = Zira\Page::getLayout(); + if (!$layout) $layout = Zira\Config::get('layout'); + + $is_sidebar = $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_LEFT || $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_RIGHT; + $is_grid = $layout && $layout != Zira\View::LAYOUT_ALL_SIDEBARS && !$is_sidebar; + + return self::CACHE_PREFIX.'.'.strtolower(str_replace('\\','.',get_class($this))).'.side'.intval($is_sidebar).'.grid'.intval($is_grid).'.'.Zira\Locale::getLanguage(); + } + + public static function getTopRatedRecordsList($limit = null, $last_id = null) { + if ($limit === null) $limit = Zira\Config::get('records_limit', 10); + + $category_ids = array(Zira\Category::ROOT_CATEGORY_ID); + $categories = Zira\Models\Category::getCollection()->get(); + foreach($categories as $category) { + $category_ids []= $category->id; + } + + $query = Zira\Models\Record::getCollection(); + foreach($category_ids as $index=>$category_id) { + if ($index>0) { + $query->union(); + } + $query->open_query(); + $query->select('id', 'rating'); + $query->where('category_id', '=', $category_id); + $query->and_where('language', '=', Zira\Locale::getLanguage()); + $query->and_where('published', '=', Zira\Models\Record::STATUS_PUBLISHED); + if ($last_id!==null) { + $query->and_where('id', '<', $last_id); + } + $query->order_by('rating', 'desc'); + $query->limit($limit); + $query->close_query(); + } + $query->merge(); + $query->order_by('rating', 'desc'); + $query->limit($limit); + + $rows = $query->get(); + + if (!$rows) return array(); + + $query = Zira\Models\Record::getCollection() + ->select('id', 'name','author_id','title','description','thumb','creation_date','rating','comments') + ->left_join(Zira\Models\Category::getClass(), array('category_name'=>'name', 'category_title'=>'title')) + ; + + $record_ids = array(); + foreach($rows as $index=>$row) { + $record_ids []= $row->id; + } + $query->where('id','in',$record_ids); + + $_rows = $query->get(); + foreach($_rows as $_row) { + $records[] = $_row; + } + + usort($records, array(Zira\Models\Record::getClass(), 'sortByRatingDesc')); + + return $records; + } + + protected function _render() { + $limit = Zira\Config::get('records_limit', 10); + + $layout = Zira\Page::getLayout(); + if (!$layout) $layout = Zira\Config::get('layout'); + + $is_sidebar = $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_LEFT || $this->getPlaceholder() == Zira\View::VAR_SIDEBAR_RIGHT; + $is_grid = $layout && $layout != Zira\View::LAYOUT_ALL_SIDEBARS && !$is_sidebar; + + $data = array( + 'title' => Zira\Locale::t('Top rated'), + 'url' => '', + 'records' => self::getTopRatedRecordsList($limit), + 'grid' => $is_grid, + 'settings' => array( + 'comments_enabled' => true, + 'rating_enabled' => true, + 'display_date' => true, + 'sidebar' => $is_sidebar + ) + ); + + Zira\View::renderView($data, 'zira/widgets/rated'); + } +} \ No newline at end of file diff --git a/zira/widgets/share.php b/zira/widgets/share.php new file mode 100644 index 0000000..6fd411d --- /dev/null +++ b/zira/widgets/share.php @@ -0,0 +1,27 @@ +setCaching(false); + $this->setOrder(0); + $this->setPlaceholder(Zira\View::VAR_CONTENT_BOTTOM); + } + + protected function _render() { + Zira\View::renderView(array( + 'url' => Zira\Helper::url(Zira\Router::getRequest(), true, true), + 'title' => strip_tags(Zira\View::getLayoutData(Zira\View::VAR_TITLE)) + ), 'zira/widgets/share'); + } +} \ No newline at end of file diff --git a/zira/widgets/topmenu.php b/zira/widgets/topmenu.php new file mode 100644 index 0000000..c8efb4e --- /dev/null +++ b/zira/widgets/topmenu.php @@ -0,0 +1,38 @@ +setCaching(false); + $this->setOrder(2); + $this->setPlaceholder(Zira\View::VAR_HEADER); + } + + protected function _render() { + $items = Zira\Menu::getPrimaryMenuItems(); + if (count($items)==0) return; + $active = Zira\Menu::getPrimaryMenuActiveURL(); + foreach($items as $item) { + if ($active!==null && $item->url == $active) { + $item->active = true; + } else { + $item->active = false; + } + $item->dropdown = Zira\Menu::getPrimaryMenuItemDropdown($item->id); + } + Zira\View::renderView(array( + 'items' => $items, + 'search' => new Zira\Forms\Search() + ), 'zira/widgets/topmenu'); + } +} \ No newline at end of file diff --git a/zira/widgets/usermenu.php b/zira/widgets/usermenu.php new file mode 100644 index 0000000..018fcd2 --- /dev/null +++ b/zira/widgets/usermenu.php @@ -0,0 +1,102 @@ +setCaching(false); + $this->setOrder(0); + $this->setPlaceholder(Zira\View::VAR_HEADER); + } + + protected function _render() { + if (Zira\User::isAuthorized()) { + $class='authorized'; + $items = array( + array( + 'url' => 'user/profile', + 'icon' => 'glyphicon glyphicon-log-in', + 'title' => Zira\User::getProfileName(), + 'dropdown' => array( + array( + 'url' => 'user/profile', + 'icon' => 'glyphicon glyphicon-user', + 'title' => Zira\Locale::t('Profile') + ), + array( + 'type' => 'separator' + ), + array( + 'url' => 'user/messages', + 'icon' => 'glyphicon glyphicon-envelope', + 'title' => Zira\Locale::t('Messages') . (Zira\User::getCurrent()->messages>0 ? '('.Zira\User::getCurrent()->messages.')' : '') + ), + array( + 'type' => 'separator' + ), + array( + 'url' => 'user/logout', + 'icon' => 'glyphicon glyphicon-log-out', + 'title' => Zira\Locale::t('Logout') + ) + ) + ) + ); + if (Zira\User::getCurrent()->messages>0) { + $items = array_merge(array( + array( + 'url' => 'user/messages', + 'icon' => 'glyphicon glyphicon-envelope', + 'title' => Zira\User::getCurrent()->messages, + ) + ), $items); + } + } else { + $redirect_url = Zira\Page::getRecordUrl(); + if ($redirect_url && $redirect_url==Zira\Config::get('home_record_name')) $redirect_url = null; + if (!$redirect_url && Zira\Category::current()) $redirect_url = Zira\Category::current()->name; + $class='not-authorized'; + if (Zira\Config::get('user_signup_allow')) { + $items = array( + array( + 'url' => 'user/login'.($redirect_url ? '?redirect='.$redirect_url : ''), + 'icon' => '', + 'title' => Zira\Locale::t('Log In') + ) + ); + $items []= array( + 'url' => 'user/signup', + 'icon' => '', + 'title' => Zira\Locale::t('Sign Up') + ); + } else { + $items = array( + array( + 'url' => 'user/login'.($redirect_url ? '?redirect='.$redirect_url : ''), + 'icon' => 'glyphicon glyphicon-log-in', + 'title' => Zira\Locale::t('Authorization') + ) + ); + } + } + + $extra_items = Zira\Hook::run(Zira\Menu::USER_MENU_HOOK_NAME); + if (!empty($extra_items)) { + $items = array_merge($extra_items, $items); + } + + Zira\View::renderView(array( + 'class' => $class, + 'items' => $items + ),'zira/user/menu'); + } +} \ No newline at end of file diff --git a/zira/zira.php b/zira/zira.php new file mode 100644 index 0000000..9e5b7ba --- /dev/null +++ b/zira/zira.php @@ -0,0 +1,254 @@ +process(); + } + + protected function registerDbWidgets() { + if (Request::isAjax()) return; + $category_id = null; + if (!Router::getRequest()) { + $category_id = Category::ROOT_CATEGORY_ID; + } else if (Category::current()) { + $chain = Category::chain(); + $category_id = array(); + foreach($chain as $row) { + $category_id[]=$row->id; + } + } + Widgets::load($category_id); + } + + public function beforeDispatch() { + $this->registerRoutes(); + + Dash::getInstance()->beforeDispatch(); + + foreach(Config::get('modules') as $module) { + if ($module == 'zira' || $module == 'dash') continue; + $class = '\\'.ucfirst($module).'\\'.ucfirst($module); + try { + if (method_exists($class, 'getInstance')) { + $obj = call_user_func($class . '::getInstance'); + } else { + $obj = new $class; + } + } catch(\Exception $e) { + continue; + } + if (method_exists($obj,'beforeDispatch')) { + call_user_func(array($obj,'beforeDispatch')); + } + } + } + + protected function registerRoutes() { + Router::addRoute('captcha','zira/index/captcha'); + Router::addRoute('cron','zira/cron/index'); + Router::addRoute('forbidden','zira/index/forbidden'); + Router::addRoute('notfound','zira/index/notfound'); + Router::addRoute('user','zira/user'); + Router::addRoute('user/*','zira/user/$2'); + Router::addRoute('poll','zira/poll/index'); + Router::addRoute('records','zira/records/index'); + Router::addRoute('comment','zira/comments/comment'); + Router::addRoute('comments','zira/comments/index'); + Router::addRoute('search','zira/search/index'); + Router::addRoute('sitemap','zira/index/map'); + Router::addRoute('rss','zira/xml/rss'); + Router::addRoute('contact','zira/contact/index'); + } + + public function bootstrapModules() { + Dash::getInstance()->bootstrap(); + + foreach(Config::get('modules') as $module) { + if ($module == 'zira' || $module == 'dash') continue; + $class = '\\'.ucfirst($module).'\\'.ucfirst($module); + try { + if (method_exists($class, 'getInstance')) { + $obj = call_user_func($class . '::getInstance'); + } else { + $obj = new $class; + } + } catch(\Exception $e) { + continue; + } + if (method_exists($obj,'bootstrap')) { + call_user_func(array($obj,'bootstrap')); + } + } + } + + public function process() { + $controller_class = '\\'.ucfirst(Router::getModule()). + '\\'.ucfirst(CONTROLLERS_DIR). + '\\'.ucfirst(Router::getController()); + + try { + if (!class_exists($controller_class)) throw new \Exception('Controller class not found'); + $controller_obj = new $controller_class; + if (!($controller_obj instanceof Controller)) throw new \Exception('Invalid controller class'); + if (!method_exists($controller_obj, Router::getAction())) throw new \Exception('Action not found'); + $param = Router::getParam(); + // only numeric params allowed + if ((count(explode('/',Router::getRequest()))!=1 || Router::getModule()!=DEFAULT_MODULE || Router::getController()!=DEFAULT_CONTROLLER || Router::getAction()!=DEFAULT_ACTION) && + !empty($param) && (!is_numeric($param) || intval($param)<=0) + ) { + throw new \Exception('Bad request'); + } + // checking if param is accepted + if (strlen($param)>0 && (Router::getModule()!=DEFAULT_MODULE || Router::getController()!=DEFAULT_CONTROLLER || Router::getAction()!=DEFAULT_ACTION)) { + $reflectionMethod = new \ReflectionMethod($controller_obj, Router::getAction()); + if ($reflectionMethod->getNumberOfParameters() == 0) { + throw new \Exception('Bad request'); + } + } + // catch and process pages + if (Router::getRequest() && Router::getModule()==DEFAULT_MODULE && Router::getController()==DEFAULT_CONTROLLER && Router::getAction()==DEFAULT_ACTION) { + throw new \Exception('Bad request'); + } else { + $param = intval($param); + } + } catch (\Exception $e) { + $controller_obj = null; + $param = null; + if (Category::current()) { + $controller_obj = new Controllers\Index(); + Router::setAction('page'); + Router::setController(DEFAULT_CONTROLLER); + Router::setModule(DEFAULT_MODULE); + $param = Category::param(); + } else if (count(explode('/',Router::getRequest()))==1) { + Router::setModule(DEFAULT_MODULE); + $param = Router::getRequest(); + if ($param == 'sitemap.xml') { + $controller_obj = new Controllers\Xml(); + Router::setController('xml'); + Router::setAction('sitemap'); + } else { + $controller_obj = new Controllers\Index(); + Router::setController(DEFAULT_CONTROLLER); + Router::setAction('page'); + } + } else { + Response::notFound(); + } + } + + if ( + Router::getModule()!='zira' && Router::getModule()!='dash' + && !in_array(Router::getModule(), Config::get('modules') + )) { + Response::notFound(); + } + + call_user_func(array($controller_obj, '_before')); + call_user_func_array(array($controller_obj, Router::getAction()), array($param)); + call_user_func(array($controller_obj, '_after')); + } + + public static function getModuleCronTasks($module) { + $dir = ROOT_DIR . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . 'cron'; + if (!file_exists($dir) || !is_dir($dir)) return array(); + $objects = array(); + $d = opendir($dir); + while(($f=readdir($d))!==false) { + if ($f=='.' || $f=='..' || is_dir($dir. DIRECTORY_SEPARATOR . $f)) continue; + if (!preg_match('/^([a-zA-Z0-9]+)\.php$/', $f, $matches)) continue; + $class = '\\'.ucfirst($module).'\\Cron\\'.ucfirst($matches[1]); + try { + if (class_exists($class)) { + $obj = new $class; + if ($obj instanceof Cron) { + $objects []= $obj; + } else { + unset($obj); + } + } + } catch(\Exception $e) { + Log::exception($e); + } + } + closedir($d); + return $objects; + } + + public function exception(\Exception $e) { + if (defined('DEBUG') && DEBUG) throw $e; + else Log::exception($e);; + } + + public function shutdown() { + Session::close(); + Db\Db::close(); + } + + public static function randomSecureString($bytes) { + return bin2hex(openssl_random_pseudo_bytes($bytes)); + } +} \ No newline at end of file