diff --git a/data/web/promote.telegram.org/css/promote.css b/data/web/promote.telegram.org/css/promote.css
index 3338086830..b3970a9b2e 100644
--- a/data/web/promote.telegram.org/css/promote.css
+++ b/data/web/promote.telegram.org/css/promote.css
@@ -49,7 +49,8 @@ body {
margin-bottom: 0 !important;
height: 0 !important;
}
-.sanim {
+.sanim,
+.oanim {
transition: all .2s ease;
}
@@ -258,7 +259,7 @@ a.input:hover {
font-size: 14px;
font-weight: 500;
line-height: 20px;
- background: #119af5;
+ background: var(--accent-color);
text-align: left;
border-radius: 6px;
color: #fff;
@@ -718,6 +719,15 @@ a:hover img.emoji {
.pr-dropdown.dropdown-toggle {
cursor: pointer;
}
+.pr-dropdown-wrap.inline-dropdown {
+ display: inline-block;
+}
+.pr-dropdown-wrap.inline-dropdown .pr-form-control {
+ padding: 6px 11px;
+}
+.pr-layer-popup .radio-item-block .pr-dropdown-wrap.inline-dropdown {
+ margin: -5px 10px;
+}
.pr-dropdown-wrap span.dropdown-menu {
left: auto;
right: -1px;
@@ -728,14 +738,25 @@ a:hover img.emoji {
overflow: hidden;
min-width: 150px;
}
+.pr-dropdown-wrap span.dropdown-menu.dropdown-menu-top {
+ margin: -2px 0 4px 0;
+ bottom: 100%;
+ top: auto;
+}
.pr-dropdown-wrap.input-dropdown span.dropdown-menu {
left: -1px;
}
+.pr-dropdown-wrap.open .pr-form-control {
+ box-shadow: inset 0 0 0 2px #35a3f6;
+}
.pr-dropdown-wrap.input-dropdown .input {
padding-right: 40px;
position: relative;
cursor: pointer;
}
+.pr-dropdown-wrap.inline-dropdown .input {
+ padding-right: 30px;
+}
.pr-dropdown-wrap.input-dropdown .input:after {
position: absolute;
top: 1px;
@@ -749,6 +770,9 @@ a:hover img.emoji {
height: 6px;
background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2213%22%20height%3D%226%22%20viewBox%3D%220%200%2013%206%22%3E%3Cpath%20fill%3D%22none%22%20stroke%3D%22%23c1c4c7%22%20stroke-linecap%3D%22round%22%20stroke-width%3D%222%22%20d%3D%22M%201.68%201%20L%205.8%204.46%20C%206.17%204.77%206.71%204.77%207.08%204.46%20L%2011.2%201%20L%2011.2%201%22%2F%3E%3C%2Fsvg%3E');
}
+.pr-dropdown-wrap.inline-dropdown .input:after {
+ margin: auto 9px;
+}
.dropdown-menu .divider {
height: 1px;
margin: 6px 0;
@@ -1587,10 +1611,11 @@ input.pr-form-control:focus {
font-size: 13px;
line-height: 18px;
margin: 0 12px;
+ position: absolute;
float: right;
- right: 0;
+ right: 15px;
cursor: pointer;
- transition: all .2s ease;
+ transition: opacity .2s ease, visibility .2s ease;
}
.pr-form-link.inactive {
opacity: 0;
@@ -1817,15 +1842,29 @@ input.pr-form-control:focus {
line-height: 18px;
margin: 0 15px 25px;
}
-form > .form-group {
+form > .form-group,
+form > .sanim > .form-group {
position: relative;
}
-.pr-form .form-group {
+.pr-form .form-group,
+.pr-form .form-group-link-wrap,
+.pr-popup-edit-form .form-group-link-wrap {
position: relative;
padding: 7px 15px;
max-width: 460px;
margin: 0 auto;
}
+.pr-popup-edit-form.pr-popup-edit-status-form {
+ margin-top: -18px;
+}
+.pr-popup-edit-status-form .form-group {
+ position: relative;
+ padding: 7px 0;
+ margin: 0;
+}
+.pr-popup-edit-status-form .form-group-link-wrap .form-group-link {
+ margin-left: 10px;
+}
.form-group-divider {
border-bottom: 1px solid #d9d9d9;
text-align: center;
@@ -1939,7 +1978,9 @@ form > .form-group {
padding-top: 4px;
padding-bottom: 10px;
}
-.pr-form .form-group.form-group-checkbox .checkbox-item {
+.pr-form .form-group.form-group-checkbox .checkbox-item,
+.form-group-link-wrap .form-group-link,
+.pr-form .form-group .radio-group {
margin-left: 13px;
}
.pr-form .form-group-slim .radio-group {
@@ -1951,10 +1992,94 @@ form > .form-group {
.pr-form .form-group-slim .radio-group .radio-item-block + .radio-item-block {
margin-top: 0;
}
+.pr-form .form-group-link-wrap,
+.pr-popup-edit-form .form-group-link-wrap {
+ max-width: 460px;
+ padding-top: 0;
+ padding-bottom: 0;
+ margin: 0 auto;
+}
+.form-group-link-wrap .form-group-link {
+ display: inline-block;
+ font-size: 13px;
+ line-height: 18px;
+ padding-bottom: 10px;
+ vertical-align: top;
+ cursor: pointer;
+}
.pr-layer-popup .pr-form .form-group {
padding-left: 0;
padding-right: 0;
}
+.form-group .radio-group {
+ margin: 8px 0 0;
+}
+.radio-group .radio-item input.radio:disabled ~ .radio-label {
+ cursor: default;
+ pointer-events: none;
+ opacity: .65;
+}
+.form-group .datetime-group {
+ display: flex;
+ margin: 0 -6px;
+}
+.form-group .datetime-group .date-input-wrap {
+ width: 50%;
+ margin: 0 6px;
+ flex-grow: 1;
+}
+.form-group .datetime-group .date-input-wrap:before {
+ position: absolute;
+ right: 0;
+ top: 0;
+ display: inline-block;
+ content: '';
+ vertical-align: top;
+ width: 36px;
+ height: 36px;
+ margin: 2px;
+ pointer-events: none;
+ border-radius: 6px;
+ background: url('data:image/svg+xml,%3Csvg%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%20stroke%3D%22%23808080%22%20stroke-linecap%3D%22round%22%3E%3Cpath%20d%3D%22m16.8%2019h-9.6c-1.22%200-2.2-.98-2.2-2.2v-8.87c0-1.21.98-2.2%202.2-2.2h9.6c1.22%200%202.2.99%202.2%202.2v8.87c0%201.22-.98%202.2-2.2%202.2zm-11.38-8.94h13.16z%22%20stroke-width%3D%221.3%22%2F%3E%3Cpath%20d%3D%22m8.24%205.44v-1.64zm7.52%200v-1.64z%22%20stroke-width%3D%221.4%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E') center no-repeat;
+}
+.form-group .datetime-group .date-input-wrap .pr-form-control[readonly] {
+ cursor: pointer;
+}
+.form-group .datetime-group .time-input-wrap {
+ width: 150px;
+ margin: 0 6px;
+ flex-grow: 1;
+}
+.form-group .datetime-group .time-input-wrap .pr-form-control {
+ padding-right: 90px;
+}
+.form-group .datetime-group .time-input-wrap .time-input-suffix {
+ position: absolute;
+ right: 0;
+ top: 0;
+ font-size: 13px;
+ padding: 11px 13px 11px 0;
+ pointer-events: none;
+ color: #999;
+}
+.datetime-group input::-webkit-input-placeholder {
+ letter-spacing: 1px;
+}
+.datetime-group input::-moz-placeholder {
+ letter-spacing: 1px;
+}
+.datetime-group input:-ms-input-placeholder {
+ letter-spacing: 1px;
+}
+.datetime-group input::placeholder {
+ letter-spacing: 1px;
+}
+.date-input-wrap input[type="date"],
+.time-input-wrap input[type="time"] {
+ position: absolute;
+ pointer-events: none;
+ visibility: hidden;
+}
.pr-budget-form {
display: flex;
@@ -2282,6 +2407,7 @@ fieldset.pr-form-control-wrap .checkbox-item-block {
.form-group .pr-placeholder-label {
font-weight: normal;
}
+.open > .dropdown-toggle ~ .pr-placeholder-label:before,
.field-focused .pr-placeholder-label:before {
box-shadow: inset 0 2px #fff;
transition-timing-function: ease, step-start;
@@ -2395,7 +2521,7 @@ fieldset.pr-form-control-wrap .checkbox-item-block {
width: 300px;
}
.pr-new-form .pr-form-column {
- width: 330px;
+ width: 100%;
}
.pr-form-header {
font-size: 16px;
@@ -2529,7 +2655,9 @@ fieldset.pr-form-control-wrap .checkbox-item-block {
display: block;
}
@media (min-width: 992px) {
- .pr-form .form-group {
+ .pr-form .form-group,
+ .pr-form .form-group-link-wrap,
+ .pr-popup-edit-form .form-group-link-wrap {
max-width: none;
padding-left: 0;
padding-right: 0;
@@ -2549,11 +2677,15 @@ fieldset.pr-form-control-wrap .checkbox-item-block {
margin-right: 13px;
}
.pr-new-form .pr-form-column {
+ width: 330px;
margin: 0;
}
.pr-new-form .pr-form-column + .pr-form-column {
width: 430px;
}
+ .pr-form-link {
+ right: 0;
+ }
.add-funds-req-form .pr-article {
padding: 0;
}
@@ -3063,13 +3195,13 @@ a.ad-declined:focus {
}
.pr-radio-buttons {
padding: 4px 0;
- margin: 0 -5px;
+ margin: 0 -6px;
border: 0;
min-width: 0;
}
.pr-radio-button {
display: block;
- margin: 0 5px;
+ margin: 0 6px;
flex: 1;
position: relative;
overflow: hidden;
@@ -3830,6 +3962,295 @@ a.pr-popup-account:hover {
color: #808080;
}
+.pr-schedule-input {
+ padding: 10px 5px 15px 0;
+ margin: 0 -14px;
+}
+.pr-schedule-input-mini {
+ padding: 12px 0 0;
+}
+.pr-schedule-input-overview {
+ display: block;
+ font-size: 12px;
+ line-height: 14px;
+ text-align: center;
+ padding: 6px 13px 0;
+ cursor: pointer;
+}
+.pr-schedule-input-overview:empty {
+ padding-top: 6px;
+}
+.pr-schedule-input-overview b {
+ font-weight: 500;
+}
+.pr-schedule-input-overview .timezone {
+ color: #999;
+}
+.pr-schedule-input-action {
+ display: block;
+ font-size: 13px;
+ line-height: 18px;
+ text-align: center;
+ padding: 6px 0 0;
+ cursor: pointer;
+}
+.pr-schedule-table-wrap {
+ --cell-height: 16px;
+ position: relative;
+ max-width: 620px;
+ box-shadow: inset 0 0 0 1px #d9d9d9;
+ border-radius: 6px;
+}
+.pr-schedule-table-wrap.with-labels {
+ --label-top: 24px;
+ --label-left: 15px;
+ --cell-height: 24px;
+ margin-top: var(--label-top);
+ margin-left: var(--label-left);
+ min-width: 288px;
+}
+.pr-schedule-table {
+ position: relative;
+ z-index: 1;
+ background: url('data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%20240%2070%22%20preserveAspectRatio%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M0%2010%20240%2010ZM0%2020%20240%2020ZM0%2030%20240%2030ZM0%2040%20240%2040ZM0%2050%20240%2050ZM0%2060%20240%2060ZM10%200%2010%2070ZM20%200%2020%2070ZM30%200%2030%2070ZM40%200%2040%2070ZM50%200%2050%2070ZM60%200%2060%2070ZM70%200%2070%2070ZM80%200%2080%2070ZM90%200%2090%2070ZM100%200%20100%2070ZM110%200%20110%2070ZM120%200%20120%2070ZM130%200%20130%2070ZM140%200%20140%2070ZM150%200%20150%2070ZM160%200%20160%2070ZM170%200%20170%2070ZM180%200%20180%2070ZM190%200%20190%2070ZM200%200%20200%2070ZM210%200%20210%2070ZM220%200%20220%2070ZM230%200%20230%2070Z%22%20vector-effect%3D%22non-scaling-stroke%22%20stroke%3D%22rgba%28217%2C217%2C217%2C.4%29%22%20stroke-width%3D%220.5%22%20fill%3D%22none%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E') center no-repeat;
+ cursor: pointer;
+}
+.pr-schedule-table-top-labels,
+.pr-schedule-table-left-labels {
+ position: absolute;
+ cursor: pointer;
+ -webkit-user-select: none;
+ user-select: none;
+}
+.pr-schedule-table-top-labels {
+ height: var(--label-top);
+ bottom: 100%;
+}
+.pr-schedule-table-top-labels td {
+ font-size: 10px;
+ text-align: center;
+}
+.pr-schedule-table-left-labels {
+ width: var(--label-left);
+ right: 100%;
+}
+.pr-schedule-table-left-labels td {
+ font-size: 9px;
+ text-align: center;
+}
+.pr-schedule-table-top-labels td > .label,
+.pr-schedule-table-left-labels td > .label {
+ display: inline-block;
+ transform: rotate(-90deg);
+ pointer-events: none;
+}
+.pr-layer-schedule-popup .pr-new-form .pr-form-column {
+ width: 100%;
+}
+.pr-layer-schedule-popup .pr-form {
+ padding: 0;
+}
+.pr-layer-schedule-popup .pr-form .form-group {
+ padding: 10px 0 0;
+}
+.pr-layer-schedule-popup .form-group > .form-label {
+ margin-left: 0;
+ margin-right: 0;
+}
+.pr-layer-schedule-popup .form-group .radio-group {
+ padding: 1px 0 0;
+ margin-left: 0;
+}
+.pr-layer-schedule-popup .form-group .radio-item-block {
+ margin: 4px 0;
+}
+@media screen and (min-width: 480px) {
+ .pr-schedule-input {
+ margin: 0;
+ }
+ .pr-schedule-table-wrap.with-labels {
+ --label-top: 30px;
+ --label-left: 45px;
+ --cell-height: 30px;
+ }
+ .pr-schedule-table-top-labels td {
+ font-size: 11px;
+ text-align: center;
+ }
+ .pr-schedule-table-left-labels td {
+ font-size: 12px;
+ text-align: right;
+ padding-right: 15px;
+ }
+ .pr-schedule-table-top-labels td > .label,
+ .pr-schedule-table-left-labels td > .label {
+ transform: rotate(0deg);
+ }
+}
+.pr-schedule-table td,
+.pr-schedule-table-top-labels td,
+.pr-schedule-table-left-labels td {
+ height: var(--cell-height);
+ width: 100px;
+}
+.pr-schedule-table-top-labels td {
+ height: var(--label-top);
+}
+.pr-schedule-table tr:first-child > td:first-child {
+ border-top-left-radius: 6px;
+}
+.pr-schedule-table tr:first-child > td:last-child {
+ border-top-right-radius: 6px;
+}
+.pr-schedule-table tr:last-child > td:first-child {
+ border-bottom-left-radius: 6px;
+}
+.pr-schedule-table tr:last-child > td:last-child {
+ border-bottom-right-radius: 6px;
+}
+.pr-schedule-table td.selected {
+ background-color: var(--accent-color);
+}
+.pr-schedule-table td.hover {
+ background-color: rgba(17, 154, 245, .1);
+}
+.pr-schedule-table td.selected.hover {
+ background-color: rgba(17, 154, 245, .8);
+}
+
+
+.date-picker-wrap {
+ margin: 0 -23px;
+ -webkit-user-select: none;
+ user-select: none;
+}
+.date-picker-header {
+ background: #f7f7f7;
+ padding: 0 7px;
+}
+.date-picker-body {
+ --row-height: 43px;
+ --row-offset: 0;
+ --prepend-offset: 0;
+ --animation: .3s ease;
+ padding: 0 7px;
+ height: 265px;
+ position: relative;
+ overflow: hidden;
+}
+.date-picker-body:before,
+.date-picker-body:after {
+ content: '';
+ display: block;
+ position: absolute;
+ pointer-events: none;
+ left: 0;
+ right: 0;
+ top: 0;
+ height: 18px;
+ background: -moz-linear-gradient(top, rgba(255,255,255,1) 15%, rgba(255,255,255,0) 100%);
+ background: -webkit-linear-gradient(top, rgba(255,255,255,1) 15%, rgba(255,255,255,0) 100%);
+ background: linear-gradient(to bottom, rgba(255,255,255,1) 15%, rgba(255,255,255,0) 100%);
+ z-index: 1;
+}
+.date-picker-body:after {
+ background: -moz-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 85%);
+ background: -webkit-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 85%);
+ background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 85%);
+ bottom: 0;
+ top: auto;
+}
+.date-picker-header-content,
+.date-picker-body-content {
+ display: grid;
+ grid-template-columns: repeat(7, 1fr);
+ justify-items: center;
+ width: 350px;
+ max-width: 100%;
+}
+.date-picker-header-content {
+ padding: 7px 0;
+}
+.date-picker-body-content {
+ padding: 7px 0 0;
+ transition: transform var(--animation);
+ transform: translateY(calc(var(--row-offset) * var(--row-height)));
+ margin-top: calc(var(--prepend-offset) * var(--row-height));
+}
+.date-picker-cell {
+ text-align: center;
+ width: 36px;
+}
+.date-picker-header-content .date-picker-cell {
+ font-size: 12px;
+ line-height: 14px;
+ color: #808080;
+}
+.date-picker-body-content .date-picker-cell {
+ font-size: 13px;
+ line-height: 36px;
+ height: 36px;
+ border-radius: 18px;
+ margin: 0 0 7px;
+ cursor: pointer;
+ color: #999;
+ transition: color var(--animation);
+}
+.date-picker-body-content .date-picker-cell.current {
+ color: #000;
+}
+.date-picker-body-content .date-picker-cell.disabled {
+ color: #999;
+ pointer-events: none;
+}
+.date-picker-body-content .date-picker-cell.selected {
+ font-weight: 500;
+ background-color: var(--accent-color);
+ color: #fff;
+}
+.date-picker-wrap + .popup-buttons {
+ margin-top: 7px;
+}
+.pr-layer-date-picker-popup {
+ position: relative;
+}
+.date-picker-controls {
+ position: absolute;
+ right: 12px;
+ top: 12px;
+ z-index: 1;
+}
+.date-picker-button-down,
+.date-picker-button-up {
+ display: inline-block;
+ width: 36px;
+ height: 36px;
+ vertical-align: top;
+ border-radius: 50%;
+ margin-left: 8px;
+ background: no-repeat center;
+ cursor: pointer;
+}
+.date-picker-button-down:hover,
+.date-picker-button-up:hover {
+ background-color: var(--link-bghover);
+}
+.date-picker-button-up {
+ background-image: url('data:image/svg+xml,%3Csvg%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M6%2014.5%2011.86%208.64C11.93%208.56%2012.06%208.56%2012.14%208.64L18%2014.5%2018%2014.5%22%20fill%3D%22none%22%20stroke%3D%22%230288db%22%20stroke-linecap%3D%22round%22%20stroke-width%3D%221.4%22%2F%3E%3C%2Fsvg%3E');
+}
+.date-picker-button-up.disabled {
+ background-image: url('data:image/svg+xml,%3Csvg%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M6%2014.5%2011.86%208.64C11.93%208.56%2012.06%208.56%2012.14%208.64L18%2014.5%2018%2014.5%22%20fill%3D%22none%22%20stroke%3D%22%23999%22%20stroke-linecap%3D%22round%22%20stroke-width%3D%221.4%22%2F%3E%3C%2Fsvg%3E');
+ pointer-events: none;
+}
+.date-picker-button-down {
+ background-image: url('data:image/svg+xml,%3Csvg%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M6%209.5%2011.86%2015.36C11.93%2015.44%2012.06%2015.44%2012.14%2015.36L18%209.5%22%20fill%3D%22none%22%20stroke%3D%22%230288db%22%20stroke-linecap%3D%22round%22%20stroke-width%3D%221.4%22%2F%3E%3C%2Fsvg%3E');
+}
+.date-picker-button-down.disabled {
+ background-image: url('data:image/svg+xml,%3Csvg%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M6%209.5%2011.86%2015.36C11.93%2015.44%2012.06%2015.44%2012.14%2015.36L18%209.5%22%20fill%3D%22none%22%20stroke%3D%22%23999%22%20stroke-linecap%3D%22round%22%20stroke-width%3D%221.4%22%2F%3E%3C%2Fsvg%3E');
+ pointer-events: none;
+}
+
+
.pr-article {
padding: 0 15px;
}
@@ -4158,6 +4579,13 @@ a.pr-popup-account:hover {
margin: 0 0 16px;
overflow: hidden;
}
+.pr-layer-header-right-actions {
+ font-size: 14px;
+ line-height: 20px;
+ font-weight: normal;
+ padding: 1px 0 0 10px;
+ float: right;
+}
.pr-layer-subheader {
font-size: 13px;
line-height: 17px;
@@ -4167,6 +4595,14 @@ a.pr-popup-account:hover {
white-space: nowrap;
overflow: hidden;
}
+.pr-layer-right-action {
+ cursor: pointer;
+}
+.pr-layer-right-action.ohide {
+ opacity: 0;
+ visibility: hidden;
+ pointer-events: none;
+}
.pr-layer-text {
font-size: 14px;
line-height: 21px;
@@ -4181,10 +4617,6 @@ a.pr-popup-account:hover {
max-width: 90%;
max-width: calc(100vw - 30px);
}
-.pr-layer-popup .radio-item-block,
-.pr-layer-popup .checkbox-item-block {
- margin: 10px 0;
-}
.pr-layer-popup .pr-popup-edit-form .radio-item-block,
.pr-layer-popup .pr-popup-edit-form .checkbox-item-block {
margin-left: 9px;
@@ -4198,6 +4630,9 @@ a.pr-popup-account:hover {
.pr-layer-edit-status {
width: 235px;
}
+.pr-layer-edit-status-extra {
+ width: 330px;
+}
.pr-layer-edit-advertiser {
width: 520px;
}
diff --git a/data/web/promote.telegram.org/js/promote.js b/data/web/promote.telegram.org/js/promote.js
index 4fc4c9028d..1b01d94605 100644
--- a/data/web/promote.telegram.org/js/promote.js
+++ b/data/web/promote.telegram.org/js/promote.js
@@ -56,6 +56,26 @@ var Ads = {
}
});
},
+ eShownDropdown: function(e) {
+ $('.dropdown-menu > li.selected', this).scrollIntoView({position: 'top', padding: 40});
+ },
+ dateTimeFieldValue: function($form, date_field, time_field) {
+ var $dateFieldEl = time_field ? $form.field(date_field) : $form;
+ var $timeFieldEl = time_field ? $form.field(time_field) : date_field;
+ var date_value = $dateFieldEl.value();
+ var time_value = $timeFieldEl.value();
+ if (!date_value || !time_value) {
+ return '';
+ }
+ var tz_offset = -60 * (new Date()).getTimezoneOffset();
+ var is_pos = tz_offset >= 0;
+ if (!is_pos) tz_offset *= -1;
+ var h = Math.floor(tz_offset / 3600);
+ var m = Math.floor((tz_offset % 3600) / 60);
+ if (h < 10) h = '0' + h;
+ if (m < 10) m = '0' + m;
+ return date_value + 'T' + time_value + (tz_offset ? (is_pos ? '+' : '-') + h + m : 'Z');
+ },
wrapAmount: function(value, no_currency, field_format) {
var amount_str = formatNumber(value, 2, '.', field_format ? '' : ',');
if (no_currency) {
@@ -161,7 +181,7 @@ var Ads = {
var $msg = $formGroup.find('>.pr-form-control-msg');
if (!$msg.size() && hint_text) {
$msg = $('
');
- $formGroup.find('>.pr-form-control-wrap').after($msg);
+ $formGroup.find('>.pr-form-control-wrap,>.datetime-group').after($msg);
}
$msg.toggleClass('no-hint', !$hint.text().length);
if (hint_text) {
@@ -178,7 +198,7 @@ var Ads = {
$fieldEl.trigger('click');
$fieldEl.find('.items-list').addClass('collapsed');
$fieldEl.removeClass('open');
- } else if (!$fieldEl.is('[type="file"]')) {
+ } else if (!$fieldEl.is('[type="file"],[type="date"],[type="time"]')) {
$fieldEl.focusAndSelect();
}
}
@@ -231,8 +251,13 @@ var Ads = {
$('.pr-form-control', $form).each(function(){ Ads.fieldInit(this); });
$('.js-amount-input', $form).on('keyup change input', Ads.eUpdateAmountField);
$('input.checkbox,input.radio', $form).on('focus blur', Ads.eUpdateField);
+ $('input[data-type="schedule"]', $form).initSchedule();
+ $('input[type="date"]', $form).initDatePicker();
+ $('input[type="time"]', $form).initTimePicker();
+ $('input[type="date"],input[type="time"]', $form).on('change', Ads.eDateTimeChange);
$('.input-dropdown', $form).on('click', '.input-dropdown-item', Ads.eUpdateDropdown);
$('.input-dropdown > .input', $form).on('selectval', Ads.eSetDropdownValue);
+ $('.input-dropdown', $form).on('shown.bs.dropdown', Ads.eShownDropdown);
$('.js-hint-tooltip', $form).on('mouseover mouseout click', Ads.eHintEvent);
$('textarea.pr-form-control', $form).initAutosize();
$('.upload-input input', $form).on('change', Ads.eFileChange);
@@ -246,8 +271,13 @@ var Ads = {
$('.pr-form-control', $form).each(function(){ Ads.fieldDestroy(this); });
$('.js-amount-input', $form).off('keyup change input', Ads.eUpdateAmountField);
$('input.checkbox,input.radio', $form).off('focus blur', Ads.eUpdateField);
+ $('input[data-type="schedule"]', $form).destroySchedule();
+ $('input[type="date"]', $form).destroyDatePicker();
+ $('input[type="time"]', $form).destroyTimePicker();
+ $('input[type="date"],input[type="time"]', $form).off('change', Ads.eDateTimeChange);
$('.input-dropdown', $form).off('click', '.input-dropdown-item', Ads.eUpdateDropdown);
$('.input-dropdown > .input', $form).off('selectval', Ads.eSetDropdownValue);
+ $('.input-dropdown', $form).off('shown.bs.dropdown', Ads.eShownDropdown);
$('.js-hint-tooltip', $form).off('mouseover mouseout click', Ads.eHintEvent);
$('textarea.pr-form-control', $form).destroyAutosize();
$('.upload-input input', $form).off('change', Ads.eFileChange);
@@ -255,6 +285,9 @@ var Ads = {
$(document).off('touchstart click', Ads.eHideAllHints);
$form.off('click.curPage', '.file-upload', stopImmediatePropagation);
},
+ eDateTimeChange: function(e) {
+ Ads.hideFieldError($(this));
+ },
eClearField: function(e) {
var $fieldEl = $(this).parents('.pr-search-input-wrap').find('.pr-search-input');
$fieldEl.value('').trigger('input').focus();
@@ -446,6 +479,17 @@ var Ads = {
}
return false;
},
+ getTimezoneText: function(tz_offset) {
+ if (typeof tz_offset === 'undefined') {
+ tz_offset = -60 * (new Date()).getTimezoneOffset();
+ }
+ var is_pos = tz_offset >= 0;
+ if (!is_pos) tz_offset *= -1;
+ var h = Math.floor(tz_offset / 3600);
+ var m = Math.floor((tz_offset % 3600) / 60);
+ if (m < 10) m = '0' + m;
+ return 'UTC' + (tz_offset ? (is_pos ? '+' : '-') + h + ':' + m : '');
+ },
eLogOut: function(e) {
e.preventDefault();
e.stopImmediatePropagation();
@@ -468,6 +512,14 @@ var NewAd = {
cont.on('change.curPage', '.js-promote-photo > .file-upload', NewAd.eUploadPromotePhoto);
cont.on('click.curPage', '.clear-draft-btn', NewAd.eClearDraft);
cont.on('click.curPage', '.create-new-ad-btn', NewAd.eSubmitForm);
+ cont.on('click.curPage', '.js-open-daily-budget', NewAd.eOpenDailyBudget);
+ cont.on('click.curPage', '.js-remove-daily-budget', NewAd.eRemoveDailyBudget);
+ cont.on('click.curPage', '.js-activate-date-link', NewAd.eOpenStartDate);
+ cont.on('click.curPage', '.js-deactivate-date-link', NewAd.eOpenEndDate);
+ cont.on('click.curPage', '.js-activate-date-remove', NewAd.eRemoveStartDate);
+ cont.on('click.curPage', '.js-deactivate-date-remove', NewAd.eRemoveEndDate);
+ cont.on('click.curPage', '.js-open-schedule', NewAd.eOpenSchedule);
+ $('.js-schedule-overview', state.$form).html(NewAd.scheduleOverview(state.$form));
for (var i = 0; i < state.selectList.length; i++) {
var selectData = state.selectList[i];
if (selectData.channel_search) {
@@ -535,6 +587,10 @@ var NewAd = {
state.excludePoliticCheckbox.on('change.curPage', NewAd.onExcludePoliticChange);
state.onlyPoliticCheckbox = state.$form.field('only_politic');
state.onlyPoliticCheckbox.on('change.curPage', NewAd.onOnlyPoliticChange);
+ state.activeRadio = state.$form.field('active');
+ state.activeRadio.fieldEl().on('change.curPage', NewAd.onActiveChange);
+ state.useScheduleCheckbox = state.$form.field('use_schedule');
+ state.useScheduleCheckbox.on('change.curPage', NewAd.onUseScheduleChange);
state.deviceField = state.$form.field('device');
state.deviceField.on('ddchange.curPage', NewAd.onDeviceChange);
state.confirmedCheckbox = state.$form.field('confirmed');
@@ -547,6 +603,7 @@ var NewAd = {
Aj.onLoad(function(state) {
state.initFormData = NewAd.getFormData(state.$form);
state.initPreviewFormData = NewAd.getPreviewFormData();
+ state.draftEnabled = true;
Aj.onBeforeUnload(function() {
var curPreviewFormData = NewAd.getPreviewFormData();
if (Aj.state.initPreviewFormData != curPreviewFormData) {
@@ -576,6 +633,8 @@ var NewAd = {
state.intersectTopicsCheckbox.off('.curPage');
state.excludePoliticCheckbox.off('.curPage');
state.onlyPoliticCheckbox.off('.curPage');
+ state.activeRadio.fieldEl().off('.curPage');
+ state.useScheduleCheckbox.off('.curPage');
state.deviceField.off('.curPage');
for (var i = 0; i < state.selectList.length; i++) {
var selectData = state.selectList[i];
@@ -598,6 +657,7 @@ var NewAd = {
$('.pr-target-options', Aj.ajContainer).each(function() {
$(this).toggleClass('visible', $(this).attr('data-value') == cur_type);
});
+ $('.js-schedule-overview', Aj.state.$form).html(NewAd.scheduleOverview(Aj.state.$form));
NewAd.updateAdTargetOverview();
NewAd.saveDraftAuto(true);
},
@@ -623,6 +683,36 @@ var NewAd = {
NewAd.updateAdTargetOverview();
NewAd.saveDraftAuto(true);
},
+ onActiveChange: function() {
+ var $form = $(this.form);
+ var hasActivateDate = !!$form.field('ad_activate_date').value();
+ var hasDectivateDate = !!$form.field('ad_deactivate_date').value();
+ if ($form.field('active').value() == '1') {
+ $('.js-activate-date-link-wrap', $form).slideHide();
+ $('.js-activate-date-wrap', $form).slideHide();
+ $('.js-deactivate-date-link-wrap', $form).slideToggle(!hasDectivateDate);
+ $('.js-deactivate-date-wrap', $form).slideToggle(hasDectivateDate);
+ } else {
+ $('.js-activate-date-link-wrap', $form).slideToggle(!hasActivateDate);
+ $('.js-activate-date-wrap', $form).slideToggle(hasActivateDate);
+ $('.js-deactivate-date-link-wrap', $form).slideToggle(hasActivateDate && !hasDectivateDate);
+ $('.js-deactivate-date-wrap', $form).slideToggle(hasActivateDate && hasDectivateDate);
+ }
+ NewAd.saveDraftAuto(true);
+ },
+ onUseScheduleChange: function() {
+ var $form = Aj.state.$form;
+ if ($form.field('use_schedule').prop('checked')) {
+ var schedule = $form.field('schedule').value();
+ if (schedule == '0;0;0;0;0;0;0') {
+ NewAd.openSchedule(Aj.state);
+ }
+ $('.js-schedule-wrap', $form).slideShow();
+ } else {
+ $('.js-schedule-wrap', $form).slideHide();
+ }
+ NewAd.saveDraftAuto(true);
+ },
onConfirmedChange: function() {
$('.create-new-ad-btn', Aj.ajContainer).prop('disabled', !$(this).prop('checked'));
},
@@ -953,11 +1043,7 @@ var NewAd = {
var $fieldEl = Aj.state.$form.field(field);
if (field == 'user_topics') {
var user_topics_cnt = $fieldEl.data('value').length;
- if (user_topics_cnt > 1) {
- $('.js-intersect-topics-wrap', Aj.state.$form).slideShow();
- } else {
- $('.js-intersect-topics-wrap', Aj.state.$form).slideHide();
- }
+ $('.js-intersect-topics-wrap', Aj.state.$form).slideToggle(user_topics_cnt > 1);
}
var selOpts = $fieldEl.data('selOpts');
var paired_field = selOpts.pairedField;
@@ -982,6 +1068,60 @@ var NewAd = {
e.preventDefault();
NewAd.previewPopup();
},
+ eOpenDailyBudget: function(e) {
+ e.preventDefault();
+ var $form = $(this).parents('form');
+ $('.js-daily-budget-wrap', $form).slideShow();
+ $('.js-open-daily-budget', $form).addClass('inactive');
+ },
+ eRemoveDailyBudget: function(e) {
+ e.preventDefault();
+ var $form = $(this).parents('form');
+ $('.js-daily-budget-wrap', $form).slideHide();
+ $('.js-open-daily-budget', $form).removeClass('inactive');
+ $form.field('daily_budget').value('');
+ },
+ eOpenStartDate: function(e) {
+ e.preventDefault();
+ var $form = $(this).parents('form');
+ $('.js-activate-date-link-wrap', $form).slideHide();
+ $('.js-activate-date-wrap', $form).slideShow();
+ if ($form.field('active').value() != '1') {
+ var hasDectivateDate = !!$form.field('ad_deactivate_date').value();
+ $('.js-deactivate-date-link-wrap', $form).slideToggle(!hasDectivateDate);
+ $('.js-deactivate-date-wrap', $form).slideToggle(hasDectivateDate);
+ }
+ },
+ eOpenEndDate: function(e) {
+ e.preventDefault();
+ var $form = $(this).parents('form');
+ $('.js-deactivate-date-link-wrap', $form).slideHide();
+ $('.js-deactivate-date-wrap', $form).slideShow();
+ },
+ eRemoveStartDate: function(e) {
+ e.preventDefault();
+ var $form = $(this).parents('form');
+ $('.js-activate-date-link-wrap', $form).slideShow();
+ $('.js-activate-date-wrap', $form).slideHide();
+ $form.field('ad_activate_date').trigger('selectval', ['']);
+ $form.field('ad_activate_time').trigger('selectval', ['']);
+ if ($form.field('active').value() != '1') {
+ $('.js-deactivate-date-link-wrap', $form).slideHide();
+ $('.js-deactivate-date-wrap', $form).slideHide();
+ }
+ },
+ eRemoveEndDate: function(e) {
+ e.preventDefault();
+ var $form = $(this).parents('form');
+ $('.js-deactivate-date-link-wrap', $form).slideShow();
+ $('.js-deactivate-date-wrap', $form).slideHide();
+ $form.field('ad_deactivate_date').trigger('selectval', ['']);
+ $form.field('ad_deactivate_time').trigger('selectval', ['']);
+ },
+ eOpenSchedule: function(e) {
+ e.preventDefault();
+ NewAd.openSchedule(Aj.state);
+ },
eReplacePromotePhoto: function(e) {
if (!$(this).hasClass('can-replace')) {
return;
@@ -1085,11 +1225,7 @@ var NewAd = {
$websiteNameField.value('');
$websitePhotoField.value('');
}
- if (customButton) {
- $('.js-custom-button-wrap', $cont).slideShow();
- } else {
- $('.js-custom-button-wrap', $cont).slideHide();
- }
+ $('.js-custom-button-wrap', $cont).slideToggle(!!customButton);
}
},
checkBeforePreviewPopupUnload: function(load_fn) {
@@ -1212,6 +1348,142 @@ var NewAd = {
});
return $previewPopup;
},
+ scheduleOverview: function($form) {
+ var schedule = $form.field('schedule').value();
+ var schedule_tz_custom = $form.field('schedule_tz_custom').value();
+ var schedule_tz = $form.field('schedule_tz').value();
+ var target_type = $form.field('target_type').value();
+ if (target_type != 'users') {
+ schedule_tz_custom = '1';
+ }
+ var value = schedule.split(';').slice(0, 7);
+ var grouped = {}, list = [], val;
+ for (var w = 0; w < 7; w++) {
+ if (val = parseInt(value[w])) {
+ if (!grouped[val]) {
+ grouped[val] = {};
+ list.push(val);
+ }
+ grouped[val][w] = true;
+ }
+ }
+ if (!list.length) {
+ return '';
+ }
+ var week = function(w) {
+ return ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][w];
+ };
+ var hour = function (h) {
+ return h < 10 ? '0' + h : h;
+ };
+ var res = [];
+ for (var i = 0; i < list.length; i++) {
+ var val = list[i], group = grouped[val];
+ var days = [], sd = null, ed = null;
+ for (var w = 0; w <= 7; w++) {
+ if (group[w]) {
+ if (!sd) sd = week(w);
+ ed = week(w);
+ } else if (sd) {
+ days.push(sd == ed ? sd : sd + '-' + ed);
+ sd = ed = null;
+ }
+ }
+ var hours = [], sh = null, eh = null;
+ for (var h = 0; h <= 24; h++) {
+ if ((val & (1 << h)) > 0) {
+ if (!sh) sh = hour(h);
+ eh = hour(h + 1);
+ } else if (sh) {
+ hours.push('' + sh + '-' + eh + '');
+ sh = eh = null;
+ }
+ }
+ res.push('' + days.join(', ') + ': ' + hours.join(', '));
+ }
+ if (schedule_tz_custom == '1') {
+ var tz = Ads.getTimezoneText(schedule_tz);
+ } else {
+ var tz = l('WEB_SCHEDULE_VIEWER_TZ', "viewer's timezone");
+ }
+ return res.join('; ') + ' (' + tz + ')';
+ },
+ openSchedule: function(state) {
+ var $schedulePopup = $('');
+ state.$schedulePopup = $schedulePopup;
+ var $form = state.$form;
+ var schedule = $form.field('schedule').value();
+ var schedule_tz_custom = $form.field('schedule_tz_custom').value();
+ var schedule_tz = $form.field('schedule_tz').value();
+ if (!schedule_tz.length) {
+ schedule_tz = -60 * (new Date()).getTimezoneOffset();
+ }
+ var target_type = $form.field('target_type').value();
+
+ var $scheduleForm = $('.pr-new-form', $schedulePopup);
+ Ads.formInit($scheduleForm);
+ $scheduleForm.on('submit', preventDefault);
+
+ var scheduleChanged = function() {
+ var schedule = $scheduleForm.field('schedule').value();
+ $clearScheduleBtn.fadeToggle(schedule != '0;0;0;0;0;0;0');
+ };
+ var scheduleClear = function() {
+ $scheduleForm.field('schedule').trigger('selectval', ['']);
+ };
+ var scheduleSave = function() {
+ var schedule = $scheduleForm.field('schedule').value();
+ var schedule_tz_custom = $scheduleForm.field('schedule_tz_custom').value();
+ var schedule_tz = $scheduleForm.field('schedule_tz').data('value');
+ $form.field('schedule').trigger('selectval', [schedule]);
+ $form.field('schedule_tz_custom').value(schedule_tz_custom);
+ $form.field('schedule_tz').value(schedule_tz);
+ if (schedule == '0;0;0;0;0;0;0') {
+ $form.field('use_schedule').prop('checked', false).trigger('change');
+ }
+ $('.js-schedule-overview', $form).html(NewAd.scheduleOverview($form));
+ closePopup($schedulePopup);
+ if (state.draftEnabled) {
+ NewAd.saveDraftAuto(true);
+ }
+ };
+ var scheduleCancel = function() {
+ closePopup($schedulePopup);
+ };
+ $scheduleForm.on('change', scheduleChanged);
+ var $clearScheduleBtn = $('.js-clear-schedule', $schedulePopup);
+ $clearScheduleBtn.on('click', scheduleClear);
+ var $submitBtn = $('.submit-form-btn', $schedulePopup);
+ $submitBtn.on('click', scheduleSave);
+ var $cancelBtn = $('.cancel-form-btn', $schedulePopup);
+ $cancelBtn.on('click', scheduleCancel);
+ $schedulePopup.one('popup:close', function() {
+ Ads.formDestroy($scheduleForm);
+ $scheduleForm.off('submit', preventDefault);
+ delete state.$schedulePopup;
+ $clearScheduleBtn.off('click', scheduleClear);
+ $submitBtn.off('click', scheduleSave);
+ $cancelBtn.off('click', scheduleCancel);
+ $schedulePopup.remove();
+ var schedule = $form.field('schedule').value();
+ if (schedule == '0;0;0;0;0;0;0') {
+ $form.field('use_schedule').prop('checked', false).trigger('change');
+ }
+ });
+
+ if (target_type != 'users') {
+ $scheduleForm.field('schedule_tz_custom').fieldEl().filter('[value="0"]').prop('disabled', true);
+ schedule_tz_custom = '1';
+ }
+ $scheduleForm.field('schedule').trigger('selectval', [schedule]);
+ $scheduleForm.field('schedule_tz_custom').value(schedule_tz_custom);
+ $scheduleForm.field('schedule_tz').trigger('selectval', [schedule_tz]);
+
+ openPopup($schedulePopup, {
+ closeByClickOutside: '.popup-no-close'
+ });
+ return $schedulePopup;
+ },
isAudienceTargetOnly: function(len) {
if (!len.locations &&
!len.countries &&
@@ -1364,16 +1636,28 @@ var NewAd = {
$form.field('cpm').value(),
$form.field('views_per_user').value(),
$form.field('budget').value(),
+ $form.field('daily_budget').value(),
+ $form.field('active').value(),
+ $form.field('ad_activate_date').value(),
+ $form.field('ad_activate_time').value(),
+ $form.field('ad_deactivate_date').value(),
+ $form.field('ad_deactivate_time').value(),
+ $form.field('use_schedule').prop('checked') ? 1 : 0,
+ $form.field('schedule').value(),
+ $form.field('schedule_tz_custom').value(),
+ $form.field('schedule_tz').value(),
$form.field('target_type').value(),
$form.field('device').data('value')
];
if ($form.field('picture').prop('checked')) {
values.push('picture');
}
- for (var i = 0; i < Aj.state.selectList.length; i++) {
- var selectData = Aj.state.selectList[i];
- var vals = $form.field(selectData.field).data('value') || [];
- values.push(vals.join(';'));
+ if (Aj.state.selectList) {
+ for (var i = 0; i < Aj.state.selectList.length; i++) {
+ var selectData = Aj.state.selectList[i];
+ var vals = $form.field(selectData.field).data('value') || [];
+ values.push(vals.join(';'));
+ }
}
if ($form.field('intersect_topics').prop('checked')) {
values.push('intersect_topics');
@@ -1422,6 +1706,14 @@ var NewAd = {
var cpm = Ads.amountFieldValue($form, 'cpm');
var views_per_user = $form.field('views_per_user').value();
var budget = Ads.amountFieldValue($form, 'budget');
+ var daily_budget = Ads.amountFieldValue($form, 'daily_budget');
+ var active = $form.field('active').value();
+ var activate_date = Ads.dateTimeFieldValue($form, 'ad_activate_date', 'ad_activate_time');
+ var deactivate_date = Ads.dateTimeFieldValue($form, 'ad_deactivate_date', 'ad_deactivate_time');
+ var use_schedule = $form.field('use_schedule').prop('checked');
+ var schedule = $form.field('schedule').value();
+ var schedule_tz_custom = $form.field('schedule_tz_custom').value();
+ var schedule_tz = $form.field('schedule_tz').value();
var target_type = $form.field('target_type').value();
var device = $form.field('device').data('value');
@@ -1445,6 +1737,10 @@ var NewAd = {
$form.field('budget').focus();
return false;
}
+ if (daily_budget === false) {
+ $form.field('daily_budget').focus();
+ return false;
+ }
var params = {
owner_id: Aj.state.ownerId,
title: title,
@@ -1457,16 +1753,20 @@ var NewAd = {
cpm: cpm,
views_per_user: views_per_user,
budget: budget,
+ daily_budget: daily_budget,
+ active: active,
target_type: target_type,
device: device
};
if ($form.field('picture').prop('checked')) {
params.picture = 1;
}
- for (var i = 0; i < Aj.state.selectList.length; i++) {
- var selectData = Aj.state.selectList[i];
- var values = $form.field(selectData.field).data('value') || [];
- params[selectData.field] = values.join(';');
+ if (Aj.state.selectList) {
+ for (var i = 0; i < Aj.state.selectList.length; i++) {
+ var selectData = Aj.state.selectList[i];
+ var values = $form.field(selectData.field).data('value') || [];
+ params[selectData.field] = values.join(';');
+ }
}
if ($form.field('intersect_topics').prop('checked')) {
params.intersect_topics = 1;
@@ -1480,6 +1780,17 @@ var NewAd = {
if ($form.field('exclude_outside').prop('checked')) {
params.exclude_outside = 1;
}
+ if (activate_date) {
+ params.activate_date = activate_date;
+ }
+ if (deactivate_date) {
+ params.deactivate_date = deactivate_date;
+ }
+ if (use_schedule) {
+ params.schedule = schedule;
+ params.schedule_tz_custom = schedule_tz_custom;
+ params.schedule_tz = schedule_tz;
+ }
NewAd.saveDraftAuto(true);
$button.prop('disabled', true);
Aj.apiRequest('createAd', params, function(result) {
@@ -1507,6 +1818,9 @@ var NewAd = {
NewAd.clearDraft();
},
saveDraftAuto: function(with_delay) {
+ if (!Aj.state.draftEnabled) {
+ return;
+ }
if (!with_delay) {
NewAd.saveDraft();
}
@@ -1525,6 +1839,14 @@ var NewAd = {
var cpm = Ads.amountFieldValue($form, 'cpm');
var views_per_user = $form.field('views_per_user').value();
var budget = Ads.amountFieldValue($form, 'budget');
+ var daily_budget = Ads.amountFieldValue($form, 'daily_budget');
+ var active = $form.field('active').value();
+ var activate_date = Ads.dateTimeFieldValue($form, 'ad_activate_date', 'ad_activate_time');
+ var deactivate_date = Ads.dateTimeFieldValue($form, 'ad_deactivate_date', 'ad_deactivate_time');
+ var use_schedule = $form.field('use_schedule').prop('checked');
+ var schedule = $form.field('schedule').value();
+ var schedule_tz_custom = $form.field('schedule_tz_custom').value();
+ var schedule_tz = $form.field('schedule_tz').value();
var target_type = $form.field('target_type').value();
var device = $form.field('device').data('value');
@@ -1544,16 +1866,20 @@ var NewAd = {
cpm: cpm,
views_per_user: views_per_user,
budget: budget,
+ daily_budget: daily_budget,
+ active: active,
target_type: target_type,
device: device
};
if ($form.field('picture').prop('checked')) {
params.picture = 1;
}
- for (var i = 0; i < Aj.state.selectList.length; i++) {
- var selectData = Aj.state.selectList[i];
- var values = $form.field(selectData.field).data('value') || [];
- params[selectData.field] = values.join(';');
+ if (Aj.state.selectList) {
+ for (var i = 0; i < Aj.state.selectList.length; i++) {
+ var selectData = Aj.state.selectList[i];
+ var values = $form.field(selectData.field).data('value') || [];
+ params[selectData.field] = values.join(';');
+ }
}
if ($form.field('intersect_topics').prop('checked')) {
params.intersect_topics = 1;
@@ -1567,6 +1893,17 @@ var NewAd = {
if ($form.field('exclude_outside').prop('checked')) {
params.exclude_outside = 1;
}
+ if (activate_date) {
+ params.activate_date = activate_date;
+ }
+ if (deactivate_date) {
+ params.deactivate_date = deactivate_date;
+ }
+ if (use_schedule) {
+ params.schedule = schedule;
+ params.schedule_tz_custom = schedule_tz_custom;
+ params.schedule_tz = schedule_tz;
+ }
Aj.apiRequest('saveAdDraft', params, function(result) {
if (result.error) {
return showAlert(result.error);
@@ -1592,10 +1929,23 @@ var NewAd = {
$form.field('ad_info').value('');
$form.field('cpm').value('');
$form.field('budget').value('');
+ $form.field('daily_budget').value('');
+ $form.field('active').value('1');
+ $form.field('ad_activate_date').trigger('selectval', ['']);
+ $form.field('ad_activate_time').trigger('selectval', ['']);
+ $form.field('ad_deactivate_date').trigger('selectval', ['']);
+ $form.field('ad_deactivate_time').trigger('selectval', ['']);
+ NewAd.onUseScheduleChange();
+ $form.field('use_schedule').prop('checked', false);
+ $form.field('schedule').trigger('selectval', ['']);
+ $form.field('schedule_tz_custom').value('0');
+ $form.field('schedule_tz').value('');
$form.field('picture').prop('checked', false);
- for (var i = 0; i < Aj.state.selectList.length; i++) {
- var selectData = Aj.state.selectList[i];
- var values = $form.field(selectData.field).trigger('reset');
+ if (Aj.state.selectList) {
+ for (var i = 0; i < Aj.state.selectList.length; i++) {
+ var selectData = Aj.state.selectList[i];
+ var values = $form.field(selectData.field).trigger('reset');
+ }
}
$form.field('exclude_politic').prop('checked', false);
$form.field('only_politic').prop('checked', false);
@@ -2039,7 +2389,9 @@ var OwnerAds = {
var ctr = item.ctr !== false ? item.ctr + '%' : '–';
var cpc = item.cpc !== false ? Ads.wrapAmount(item.cpc) : '–';
var cps = item.cps !== false ? Ads.wrapAmount(item.cps) : '–';
- return ' | | | | | | | | | | | | | ' + Aj.state.adsDropdownTpl.replace(/\{ad_id\}/g, item.ad_id).replace(/\{promote_url\}/g, promote_url).replace(/\{promote_url_text\}/g, promote_url_text).replace(/\{ad_text\}/g, item.text) + ' | ';
+ var daily_spent = item.daily_spent !== false ? '
' + Ads.wrapAmount(item.daily_spent)+'' : '';
+ var daily_budget = item.daily_budget !== false ? '
' + Ads.wrapAmount(item.daily_budget)+'' : '';
+ return ' | | | | | | | | | | | | | ' + Aj.state.adsDropdownTpl.replace(/\{ad_id\}/g, item.ad_id).replace(/\{promote_url\}/g, promote_url).replace(/\{promote_url_text\}/g, promote_url_text).replace(/\{ad_text\}/g, item.text) + ' | ';
},
renderLoading: function() {
return '' + l('WEB_OWNER_ADS_LOADING') + ' |
';
@@ -2477,6 +2829,14 @@ var EditAd = {
cont.on('click.curPage', '.js-send-to-review-btn', EditAd.eSendToReview);
cont.on('click.curPage', '.delete-ad-btn', EditAd.deleteAd);
cont.on('click.curPage', '.pr-form-select', EditAd.eSelectPlaceholder);
+ cont.on('click.curPage', '.js-open-daily-budget', NewAd.eOpenDailyBudget);
+ cont.on('click.curPage', '.js-remove-daily-budget', NewAd.eRemoveDailyBudget);
+ cont.on('click.curPage', '.js-activate-date-link', NewAd.eOpenStartDate);
+ cont.on('click.curPage', '.js-deactivate-date-link', NewAd.eOpenEndDate);
+ cont.on('click.curPage', '.js-activate-date-remove', NewAd.eRemoveStartDate);
+ cont.on('click.curPage', '.js-deactivate-date-remove', NewAd.eRemoveEndDate);
+ cont.on('click.curPage', '.js-open-schedule', NewAd.eOpenSchedule);
+ $('.js-schedule-overview', state.$form).html(NewAd.scheduleOverview(state.$form));
state.titleField = state.$form.field('title');
state.titleField.on('change.curPage', NewAd.onTitleChange);
state.textField = state.$form.field('text');
@@ -2493,6 +2853,10 @@ var EditAd = {
state.adInfoField.on('change.curPage', NewAd.onAdInfoChange);
state.pictureCheckbox = state.$form.field('picture');
state.pictureCheckbox.on('change.curPage', NewAd.onPictureChange);
+ state.activeRadio = state.$form.field('active');
+ state.activeRadio.fieldEl().on('change.curPage', NewAd.onActiveChange);
+ state.useScheduleCheckbox = state.$form.field('use_schedule');
+ state.useScheduleCheckbox.fieldEl().on('change.curPage', NewAd.onUseScheduleChange);
NewAd.updateAdPreview(state.$form, state.previewData);
Aj.onLoad(function(state) {
state.initFormData = EditAd.getFormData(state.$form);
@@ -2518,6 +2882,10 @@ var EditAd = {
state.promoteUrlField.off('.curPage');
state.websiteNameField.off('.curPage');
state.buttonField.off('.curPage');
+ state.adInfoField.off('.curPage');
+ state.pictureCheckbox.off('.curPage');
+ state.activeRadio.fieldEl().off('.curPage');
+ state.useScheduleCheckbox.off('.curPage');
});
},
getFormData: function($form) {
@@ -2531,6 +2899,16 @@ var EditAd = {
$form.field('website_name').value(),
$form.field('website_photo').value(),
$form.field('cpm').value(),
+ $form.field('daily_budget').value(),
+ $form.field('active').value(),
+ $form.field('ad_activate_date').value(),
+ $form.field('ad_activate_time').value(),
+ $form.field('ad_deactivate_date').value(),
+ $form.field('ad_deactivate_time').value(),
+ $form.field('use_schedule').prop('checked') ? 1 : 0,
+ $form.field('schedule').value(),
+ $form.field('schedule_tz_custom').value(),
+ $form.field('schedule_tz').value(),
$form.field('views_per_user').value()
];
return values.join('|');
@@ -2714,11 +3092,78 @@ var EditAd = {
});
return false;
},
+ initEditDailyBudgetPopup: function() {
+ var cont = Aj.layer;
+ Aj.onLayerLoad(function(layerState) {
+ layerState.$form = $('.pr-popup-edit-form', cont);
+ Ads.formInit(layerState.$form);
+ layerState.dailyBudgetField = layerState.$form.field('daily_budget');
+ Aj.layer.one('popup:open', function() {
+ layerState.dailyBudgetField.focusAndSelect(true);
+ });
+ layerState.$form.on('submit', EditAd.eSubmitEditDailyBudgetPopupForm);
+ cont.on('click.curLayer', '.submit-form-btn', EditAd.eSubmitEditDailyBudgetPopupForm);
+ });
+ Aj.onLayerUnload(function(layerState) {
+ Ads.formDestroy(layerState.$form);
+ layerState.$form.off('submit', EditAd.eSubmitEditDailyBudgetPopupForm);
+ });
+ },
+ eSubmitEditDailyBudgetPopupForm: function(e) {
+ e.preventDefault();
+ var $form = Aj.layerState.$form;
+ var owner_id = $form.field('owner_id').value();
+ var ad_id = $form.field('ad_id').value();
+ var daily_budget = Ads.amountFieldValue($form, 'daily_budget');
+
+ if ($form.data('disabled')) {
+ return false;
+ }
+ if (daily_budget === false) {
+ $form.field('daily_budget').focus();
+ return false;
+ }
+ var params = {
+ owner_id: owner_id,
+ ad_id: ad_id,
+ daily_budget: daily_budget,
+ popup: 1
+ };
+ $form.data('disabled', true);
+ Aj.apiRequest('editAdDailyBudget', params, function(result) {
+ $form.data('disabled', false);
+ if (result.error) {
+ if (result.field) {
+ var $field = $form.field(result.field);
+ if ($field.size()) {
+ Ads.showFieldError($field, result.error, true);
+ return false;
+ }
+ }
+ return showAlert(result.error);
+ }
+ closePopup(Aj.layer);
+ if (result.ad) {
+ OwnerAds.updateAd(result.ad);
+ }
+ });
+ return false;
+ },
initEditStatusPopup: function() {
var cont = Aj.layer;
Aj.onLayerLoad(function(layerState) {
layerState.$form = $('.pr-popup-edit-form', cont);
Ads.formInit(layerState.$form);
+ cont.on('click.curPage', '.js-activate-date-link', NewAd.eOpenStartDate);
+ cont.on('click.curPage', '.js-deactivate-date-link', NewAd.eOpenEndDate);
+ cont.on('click.curPage', '.js-activate-date-remove', NewAd.eRemoveStartDate);
+ cont.on('click.curPage', '.js-deactivate-date-remove', NewAd.eRemoveEndDate);
+ cont.on('click.curPage', '.js-open-schedule', EditAd.eOpenEditStatusSchedule);
+ $('.js-schedule-overview', layerState.$form).html(NewAd.scheduleOverview(layerState.$form));
+ layerState.activeRadio = layerState.$form.field('active');
+ layerState.activeRadio.fieldEl().on('change.curPage', NewAd.onActiveChange);
+ layerState.useScheduleCheckbox = layerState.$form.field('use_schedule');
+ layerState.useScheduleCheckbox.on('change.curPage', EditAd.onUseEditStatusScheduleChange);
layerState.$form.on('submit', EditAd.eSubmitEditStatusForm);
cont.on('click.curLayer', '.submit-form-btn', EditAd.eSubmitEditStatusForm);
});
@@ -2727,12 +3172,34 @@ var EditAd = {
layerState.$form.off('submit', EditAd.eSubmitEditStatusForm);
});
},
+ eOpenEditStatusSchedule: function(e) {
+ e.preventDefault();
+ NewAd.openSchedule(Aj.layerState);
+ },
+ onUseEditStatusScheduleChange: function() {
+ var $form = Aj.layerState.$form;
+ if ($form.field('use_schedule').prop('checked')) {
+ var schedule = $form.field('schedule').value();
+ if (schedule == '0;0;0;0;0;0;0') {
+ NewAd.openSchedule(Aj.layerState);
+ }
+ $('.js-schedule-wrap', $form).slideShow();
+ } else {
+ $('.js-schedule-wrap', $form).slideHide();
+ }
+ },
eSubmitEditStatusForm: function(e) {
e.preventDefault();
var $form = Aj.layerState.$form;
var owner_id = $form.field('owner_id').value();
var ad_id = $form.field('ad_id').value();
var active = $form.field('active').value();
+ var activate_date = Ads.dateTimeFieldValue($form, 'ad_activate_date', 'ad_activate_time');
+ var deactivate_date = Ads.dateTimeFieldValue($form, 'ad_deactivate_date', 'ad_deactivate_time');
+ var use_schedule = $form.field('use_schedule').prop('checked');
+ var schedule = $form.field('schedule').value();
+ var schedule_tz_custom = $form.field('schedule_tz_custom').value();
+ var schedule_tz = $form.field('schedule_tz').value();
if ($form.data('disabled')) {
return false;
}
@@ -2741,6 +3208,17 @@ var EditAd = {
ad_id: ad_id,
active: active
};
+ if (activate_date) {
+ params.activate_date = activate_date;
+ }
+ if (deactivate_date) {
+ params.deactivate_date = deactivate_date;
+ }
+ if (use_schedule) {
+ params.schedule = schedule;
+ params.schedule_tz_custom = schedule_tz_custom;
+ params.schedule_tz = schedule_tz;
+ }
$form.data('disabled', true);
Aj.apiRequest('editAdStatus', params, function(result) {
$form.data('disabled', false);
@@ -2881,6 +3359,14 @@ var EditAd = {
var website_photo = $form.field('website_photo').value();
var ad_info = $form.field('ad_info').value();
var cpm = Ads.amountFieldValue($form, 'cpm');
+ var daily_budget = Ads.amountFieldValue($form, 'daily_budget');
+ var active = $form.field('active').value();
+ var activate_date = Ads.dateTimeFieldValue($form, 'ad_activate_date', 'ad_activate_time');
+ var deactivate_date = Ads.dateTimeFieldValue($form, 'ad_deactivate_date', 'ad_deactivate_time');
+ var use_schedule = $form.field('use_schedule').prop('checked');
+ var schedule = $form.field('schedule').value();
+ var schedule_tz_custom = $form.field('schedule_tz_custom').value();
+ var schedule_tz = $form.field('schedule_tz').value();
var views_per_user = $form.field('views_per_user').value();
if (!title.length) {
@@ -2899,6 +3385,10 @@ var EditAd = {
$form.field('cpm').focus();
return false;
}
+ if (daily_budget === false) {
+ $form.field('daily_budget').focus();
+ return false;
+ }
var params = {
owner_id: Aj.state.ownerId,
ad_id: Aj.state.adId,
@@ -2910,11 +3400,24 @@ var EditAd = {
website_photo: website_photo,
ad_info: ad_info,
cpm: cpm,
+ daily_budget: daily_budget,
+ active: active,
views_per_user: views_per_user
};
if ($form.field('picture').prop('checked')) {
params.picture = 1;
}
+ if (activate_date) {
+ params.activate_date = activate_date;
+ }
+ if (deactivate_date) {
+ params.deactivate_date = deactivate_date;
+ }
+ if (use_schedule) {
+ params.schedule = schedule;
+ params.schedule_tz_custom = schedule_tz_custom;
+ params.schedule_tz = schedule_tz;
+ }
$button.prop('disabled', true);
Aj.apiRequest('editAd', params, function(result) {
if (result.error) {
@@ -3607,3 +4110,724 @@ var Audiences = {
AB.on(function() {
openPopup('');
});
+
+(function($) {
+
+ $.fn.initSchedule = function() {
+ function getTargetElement(e) {
+ if (e.toElement) {
+ return e.toElement;
+ }
+ if (e.type == 'touchstart' ||
+ e.type == 'touchmove') {
+ var x = e.originalEvent.touches[0].clientX;
+ var y = e.originalEvent.touches[0].clientY;
+ } else {
+ var x = e.clientX;
+ var y = e.clientY;
+ }
+ return document.elementFromPoint(x, y);
+ }
+ function onMouseDown(e) {
+ var state = $(this).data('state');
+ state.onMouseMove = function(e) {
+ var target = getTargetElement(e);
+ if (target.tagName == 'TD') {
+ var cell = $(target).data('cell');
+ state.hoverValue = rectValue(state.startCell, cell);
+ updateTableHover(state, state.hoverValue);
+ }
+ };
+ state.onMouseUp = function() {
+ var intersectValue = intersectValues(state.curValue, state.hoverValue);
+ if (compareValues(intersectValue, state.hoverValue)) {
+ state.curValue = diffValues(state.curValue, state.hoverValue);
+ } else {
+ state.curValue = mergeValues(state.curValue, state.hoverValue);
+ }
+ updateTableHover(state, emptyValue());
+ updateTableValue(state, state.curValue);
+ $(document).off('touchmove mousemove', state.onMouseMove);
+ $(document).off('touchend touchcancel mouseup', state.onMouseUp);
+ };
+
+ var target = getTargetElement(e);
+ if (target.tagName == 'TD') {
+ var cell = $(target).data('cell');
+ state.startCell = cell;
+ state.hoverValue = rectValue(cell, cell);
+ updateTableHover(state, state.hoverValue);
+ $(document).on('touchmove mousemove', state.onMouseMove);
+ $(document).on('touchend touchcancel mouseup', state.onMouseUp);
+ }
+ }
+ function onMouseOver(e) {
+ var state = $(this).data('state');
+ var target = getTargetElement(e);
+ if (target.tagName == 'TD') {
+ var cell = $(target).data('cell');
+ if (typeof cell.w === 'undefined') {
+ var hoverValue = rectValue({w: 0, h: cell.h}, {w: 6, h: cell.h});
+ } else if (typeof cell.h === 'undefined') {
+ var hoverValue = rectValue({w: cell.w, h: 0}, {w: cell.w, h: 23});
+ } else {
+ var hoverValue = rectValue(cell, cell);
+ }
+ updateTableHover(state, hoverValue);
+ }
+ }
+ function onClick(e) {
+ var state = $(this).data('state');
+ if (e.target.tagName == 'TD') {
+ var cell = $(e.target).data('cell');
+ if (typeof cell.w === 'undefined') {
+ var hoverValue = rectValue({w: 0, h: cell.h}, {w: 6, h: cell.h});
+ } else if (typeof cell.h === 'undefined') {
+ var hoverValue = rectValue({w: cell.w, h: 0}, {w: cell.w, h: 23});
+ } else {
+ var hoverValue = null;
+ }
+ if (hoverValue) {
+ var intersectValue = intersectValues(state.curValue, hoverValue);
+ if (compareValues(intersectValue, hoverValue)) {
+ state.curValue = diffValues(state.curValue, hoverValue);
+ } else {
+ state.curValue = mergeValues(state.curValue, hoverValue);
+ }
+ updateTableHover(state, emptyValue());
+ updateTableValue(state, state.curValue);
+ }
+ }
+ }
+ function onMouseOut(e) {
+ var state = $(this).data('state');
+ updateTableHover(state, emptyValue());
+ }
+ function eSetValue(e, value) {
+ var state = $(this).data('state');
+ setValue(state, value);
+ }
+
+ function emptyValue() {
+ return [0, 0, 0, 0, 0, 0, 0];
+ }
+ function rectValue(start, end) {
+ var res = emptyValue();
+ var sw = Math.min(start.w, end.w);
+ var ew = Math.max(start.w, end.w);
+ var sh = Math.min(start.h, end.h);
+ var eh = Math.max(start.h, end.h);
+ for (var w = sw; w <= ew; w++) {
+ for (var h = sh; h <= eh; h++) {
+ res[w] |= 1 << h;
+ }
+ }
+ return res;
+ }
+ function mergeValues(val1, val2) {
+ var res = emptyValue();
+ for (var w = 0; w < 7; w++) {
+ res[w] = val1[w] | val2[w];
+ }
+ return res;
+ }
+ function intersectValues(val1, val2) {
+ var res = emptyValue();
+ for (var w = 0; w < 7; w++) {
+ res[w] = val1[w] & val2[w];
+ }
+ return res;
+ }
+ function diffValues(val1, val2) {
+ var res = emptyValue();
+ for (var w = 0; w < 7; w++) {
+ res[w] = val1[w] & ~val2[w];
+ }
+ return res;
+ }
+ function compareValues(val1, val2) {
+ for (var w = 0; w < 7; w++) {
+ if (val1[w] != val2[w]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ function updateTableHover(state, val) {
+ state.$table.find('tr').each(function(w) {
+ $(this).find('td').each(function(h) {
+ var sel = (val[w] & (1 << h)) > 0;
+ $(this).toggleClass('hover', sel);
+ });
+ });
+ }
+ function updateTableValue(state, val) {
+ state.$table.find('tr').each(function(w) {
+ $(this).find('td').each(function(h) {
+ var sel = (val[w] & (1 << h)) > 0;
+ $(this).toggleClass('selected', sel);
+ });
+ });
+ state.$input.value(val.join(';')).trigger('change');
+ }
+
+ function setValue(state, value) {
+ value = value.toString();
+ var init_val = value.split(';').slice(0, 7);
+ for (var w = 0; w < 7; w++) {
+ init_val[w] = parseInt(init_val[w]) || 0;
+ }
+ state.curValue = init_val;
+ updateTableValue(state, state.curValue);
+ }
+
+ return this.each(function() {
+ var $input = $(this);
+ var $field = $input.parents('.js-schedule-input');
+ var $table = $('.js-schedule-table', $field);
+ var $table_weeks = $('.js-schedule-table-weeks', $field);
+ var $table_hours = $('.js-schedule-table-hours', $field);
+ var state = {
+ curValue: emptyValue(),
+ $input: $input,
+ $field: $field,
+ $table: $table,
+ $table_weeks: $table_weeks,
+ $table_hours: $table_hours
+ };
+ if ($input.data('inited')) {
+ return;
+ }
+ $input.data('inited', true);
+ $input.data('state', state);
+ $input.on('selectval.tr-schedule', eSetValue);
+ $table.find('tr').each(function(w) {
+ $(this).find('td').each(function(h) {
+ $(this).data('cell', {w: w, h: h});
+ });
+ });
+ $table_weeks.find('td').each(function(w) {
+ $(this).data('cell', {w: w});
+ });
+ $table_hours.find('td').each(function(h) {
+ $(this).data('cell', {h: h});
+ });
+ if (!this.hasAttribute('readonly')) {
+ $table.data('state', state);
+ $table.on('mouseover.tr-schedule', onMouseOver);
+ $table.on('mouseout.tr-schedule', onMouseOut);
+ $table.on('touchstart.tr-schedule', onMouseDown);
+ $table.on('mousedown.tr-schedule', onMouseDown);
+ $table_weeks.data('state', state);
+ $table_weeks.on('mouseover.tr-schedule', onMouseOver);
+ $table_weeks.on('mouseout.tr-schedule', onMouseOut);
+ $table_weeks.on('click.tr-schedule', onClick);
+ $table_hours.data('state', state);
+ $table_hours.on('mouseover.tr-schedule', onMouseOver);
+ $table_hours.on('mouseout.tr-schedule', onMouseOut);
+ $table_hours.on('click.tr-schedule', onClick);
+ }
+ setValue(state, $input.value());
+ });
+ };
+ $.fn.destroySchedule = function() {
+ return this.each(function() {
+ var $input = $(this);
+ var state = $input.data('state');
+ $input.off('.tr-schedule');
+ state.$table.off('.tr-schedule');
+ state.$table_weeks.off('.tr-schedule');
+ state.$table_hours.off('.tr-schedule');
+ });
+ };
+
+ $.fn.initDatePicker = function() {
+
+ function getStartOfDay(d) {
+ if (isNaN(d)) {
+ return null;
+ }
+ return new Date(d.getFullYear(), d.getMonth(), d.getDate());
+ }
+ function getStartOfWeek(d) {
+ if (isNaN(d)) {
+ return null;
+ }
+ d = new Date(d.getFullYear(), d.getMonth(), 1);
+ var day = d.getDay() || 7;
+ d.setDate(2 - day);
+ return d;
+ }
+ function getWeekDiff(d1, d2) {
+ var diff = (d2.getTime() - d1.getTime()) / 86400000;
+ return Math.round(diff / 7);
+ }
+ function getStartOfMonth(d) {
+ if (isNaN(d)) {
+ return null;
+ }
+ return new Date(d.getFullYear(), d.getMonth(), 1);
+ }
+ function getDateValue(d) {
+ if (isNaN(d) || d === null) {
+ return '';
+ }
+ var y = d.getFullYear();
+ var m = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'][d.getMonth()];
+ var d = d.getDate();
+ if (d < 10) {
+ d = '0' + d;
+ }
+ return y + '-' + m + '-' + d;
+ }
+ function getDateText(d) {
+ if (isNaN(d) || d === null) {
+ return '';
+ }
+ var y = d.getFullYear();
+ var M = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][d.getMonth()];
+ var j = d.getDate();
+ return j + ' ' + M + ' ' + y;
+ }
+
+ function openDatePicker(state, selD) {
+ if (state.$dpPopup) {
+ closePopup(state.$dpPopup);
+ }
+ var $dpPopup = $('');
+ var $dpBody = $('.js-body', $dpPopup);
+ var $dpMonthDown = $('.js-month-down', $dpPopup);
+ var $dpMonthUp = $('.js-month-up', $dpPopup);
+
+ function setHeader() {
+ var year = currentD.getFullYear();
+ var month = currentD.getMonth();
+ var header = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'][month] + ' ' + year;
+ $('.js-header', $dpPopup).html(header);
+ var prevMonth = true, nextMonth = true, newD;
+ newD = getStartOfMonth(currentD);
+ newD.setMonth(month - 1);
+ if (state.minMonthD && newD < state.minMonthD ||
+ state.maxMonthD && newD > state.maxMonthD) {
+ prevMonth = false;
+ }
+ newD = getStartOfMonth(currentD);
+ newD.setMonth(month + 1);
+ if (state.minMonthD && newD < state.minMonthD ||
+ state.maxMonthD && newD > state.maxMonthD) {
+ nextMonth = false;
+ }
+ $dpMonthDown.toggleClass('disabled', !nextMonth);
+ $dpMonthUp.toggleClass('disabled', !prevMonth);
+ }
+ function cellWrap(d) {
+ var curDate = d.getDate();
+ var curMonth = d.getMonth();
+ var curYear = d.getFullYear();
+ var cellClass = ' month-' + curYear + '-' + curMonth;
+ if (curYear == selYear && curMonth == selMonth && curDate == selDate) {
+ cellClass += ' selected';
+ }
+ if (state.minDayD && d < state.minDayD ||
+ state.maxDayD && d > state.maxDayD) {
+ cellClass += ' disabled';
+ }
+ return '' + curDate + '
';
+ }
+ function updateMonth() {
+ var year = currentD.getFullYear();
+ var month = currentD.getMonth();
+ var body = '';
+ var curD = getStartOfWeek(currentD);
+ fromWeekD = new Date(curD);
+ curWeekD = new Date(curD);
+ for (var i = 0; i < 42; i++) {
+ body += cellWrap(curD);
+ curD.setDate(curD.getDate() + 1);
+ }
+ toWeekD = new Date(curD);
+ setHeader();
+ $dpBody.animOff().html(body).cssProp('--row-offset', '').cssProp('--prepend-offset', '');
+ $('.date-picker-cell.month-' + year + '-' + month, $dpBody).addClass('current');
+ $dpBody.animOn();
+ }
+ function appendMonth(diff) {
+ diff = diff > 0 ? 1 : -1;
+ var newD = getStartOfMonth(currentD);
+ newD.setMonth(newD.getMonth() + diff);
+ if (state.minMonthD && newD < state.minMonthD ||
+ state.maxMonthD && newD > state.maxMonthD) {
+ return;
+ }
+ currentD = newD;
+ var year = currentD.getFullYear();
+ var month = currentD.getMonth();
+ var body = '';
+ var curD = getStartOfWeek(currentD);
+ var weeks = getWeekDiff(curWeekD, curD);
+ if (curD >= fromWeekD) {
+ var curToD = new Date(curD);
+ curToD.setDate(curToD.getDate() + 42);
+ while (toWeekD < curToD) {
+ body += cellWrap(toWeekD);
+ toWeekD.setDate(toWeekD.getDate() + 1);
+ }
+ $dpBody.append(body).redraw();
+ } else {
+ var curFromD = new Date(curD);
+ while (curD < fromWeekD) {
+ body += cellWrap(curD);
+ curD.setDate(curD.getDate() + 1);
+ }
+ fromWeekD = new Date(curFromD);
+ var weeksOffset = getWeekDiff(fromWeekD, curWeekD);
+ $dpBody.prepend(body).cssProp('--prepend-offset', -weeksOffset).redraw();
+ }
+ $dpBody.cssProp('--row-offset', -weeks);
+ $('.date-picker-cell.current', $dpBody).removeClass('current');
+ $('.date-picker-cell.month-' + year + '-' + month, $dpBody).addClass('current');
+ setHeader();
+ }
+ function onKeyDown(e) {
+ if (e.keyCode == Keys.DOWN) {
+ e.preventDefault();
+ appendMonth(1);
+ }
+ else if (e.keyCode == Keys.UP) {
+ e.preventDefault();
+ appendMonth(-1);
+ }
+ else if (e.keyCode == Keys.TAB) {
+ e.preventDefault();
+ }
+ }
+ function onSelect(e) {
+ var value = $(this).attr('data-value');
+ setValue(state, value);
+ closePopup($dpPopup);
+ if (state.$time) {
+ state.$time.trigger('focusval');
+ }
+ }
+ function datePickerClear() {
+ setValue(state, '');
+ closePopup($dpPopup);
+ if (state.$time) {
+ state.$time.trigger('selectval', ['']);
+ }
+ }
+ function onMonthDown(e) {
+ appendMonth(1);
+ }
+ function onMonthUp(e) {
+ appendMonth(-1);
+ }
+ function onTransitionEnd(e) {
+ if (this === e.target) {
+ updateMonth();
+ }
+ }
+
+ if (isNaN(selD) || selD === null) {
+ selD = getStartOfDay(new Date);
+ }
+ if (state.minDayD && selD < state.minDayD) {
+ selD = getStartOfDay(state.minDayD);
+ }
+ if (state.maxDayD && selD > state.maxDayD) {
+ selD = getStartOfDay(state.maxDayD);
+ }
+ var selDate = selD.getDate();
+ var selMonth = selD.getMonth();
+ var selYear = selD.getFullYear();
+
+ var fromWeekD, curWeekD, toWeekD;
+
+ var currentD = getStartOfMonth(selD);
+ updateMonth();
+
+ $(document).on('keydown', onKeyDown);
+ $dpMonthDown.on('click', onMonthDown);
+ $dpMonthUp.on('click', onMonthUp);
+ $dpBody.on('click', '.date-picker-cell', onSelect);
+ $dpBody.on('transitionend', onTransitionEnd);
+
+ var datePickerCancel = function() {
+ closePopup($dpPopup);
+ };
+ var $clearBtn = $('.clear-form-btn', $dpPopup);
+ $clearBtn.on('click', datePickerClear);
+ var $cancelBtn = $('.cancel-form-btn', $dpPopup);
+ $cancelBtn.on('click', datePickerCancel);
+ $dpPopup.one('popup:close', function() {
+ delete state.$dpPopup;
+ $clearBtn.off('click', datePickerClear);
+ $cancelBtn.off('click', datePickerCancel);
+ $(document).off('keydown', onKeyDown);
+ $dpMonthDown.off('click', onMonthDown);
+ $dpMonthUp.off('click', onMonthUp);
+ $dpBody.off('click', '.date-picker-cell', onSelect);
+ $dpBody.off('transitionend', onTransitionEnd);
+ $dpPopup.remove();
+ });
+
+ openPopup($dpPopup, {
+ closeByClickOutside: '.popup-no-close'
+ });
+ state.$dpPopup = $dpPopup;
+ return $dpPopup;
+ }
+
+ function onFocusValue(e) {
+ var state = $(this).data('state');
+ openDatePicker(state, state.curValue);
+ }
+ function onFocus(e) {
+ var state = $(this).data('state');
+ openDatePicker(state, state.curValue);
+ }
+ function onClick(e) {
+ var state = $(this).data('state');
+ openDatePicker(state, state.curValue);
+ }
+ function eSetValue(e, value) {
+ var state = $(this).data('state');
+ setValue(state, value);
+ }
+
+ function setValue(state, value) {
+ state.curValue = getStartOfDay(new Date(value));
+ state.$input.value(getDateValue(state.curValue)).trigger('change');
+ state.$value.value(getDateText(state.curValue));
+ }
+
+ return this.each(function() {
+ var $input = $(this);
+ var $field = $input.parents('.js-date-input');
+ var $value = $('.js-date-value', $field);
+ var minValue = new Date($input.attr('min'));
+ var maxValue = new Date($input.attr('max'));
+ var state = {
+ curValue: null,
+ minDayD: getStartOfDay(minValue),
+ maxDayD: getStartOfDay(maxValue),
+ minMonthD: getStartOfMonth(minValue),
+ maxMonthD: getStartOfMonth(maxValue),
+ $input: $input,
+ $field: $field,
+ $value: $value
+ };
+ var $datetime = $input.parents('.datetime-group');
+ if ($datetime.size()) {
+ state.$time = $('input[type="time"]', $datetime);
+ }
+ if ($input.data('inited')) {
+ return;
+ }
+ $input.data('inited', true);
+ $input.data('state', state);
+ $input.on('selectval.tr-datepicker', eSetValue);
+ $input.on('focusval.tr-datepicker', onFocusValue);
+ $value.data('state', state);
+ $value.on('focus.tr-datepicker', onFocus);
+ $value.on('click.tr-datepicker', onClick);
+ setValue(state, $input.attr('value'));
+ });
+ };
+ $.fn.destroyDatePicker = function() {
+ return this.each(function() {
+ var $input = $(this);
+ var state = $input.data('state');
+ $input.off('.tr-datepicker');
+ state.$value.off('.tr-datepicker');
+ });
+ };
+
+ $.fn.initTimePicker = function() {
+
+ function selectHours(state) {
+ state.hoursSelected = true;
+ state.minutesSelected = false;
+ updateSelection(state);
+ state.curHoursStr = '';
+ }
+ function selectMinutes(state) {
+ state.hoursSelected = false;
+ state.minutesSelected = true;
+ updateSelection(state);
+ state.curMinutesStr = '';
+ }
+ function updateSelection(state) {
+ state.$value.each(function(){
+ if (state.hoursSelected) {
+ this.setSelectionRange(0, 2);
+ } else if (state.minutesSelected) {
+ this.setSelectionRange(3, 5);
+ }
+ });
+ }
+ function updateValue(state, apply) {
+ if (state.hasValue) {
+ var h = state.curHours || 0;
+ var m = state.curMinutes || 0;
+ if (h < 10) h = '0' + h;
+ if (h > 23) h = state.curHours = 23;
+ if (m < 10) m = '0' + m;
+ if (m > 59 && apply) m = state.curMinutes = 59;
+ var val = h + ':' + m;
+ } else {
+ var val = '';
+ }
+ state.$value.val(val);
+ if (apply) {
+ state.$input.val(val).trigger('change');
+ }
+ }
+
+ function onFocusValue(e) {
+ var state = $(this).data('state');
+ state.$value.focus();
+ }
+ function onFocus(e) {
+ var state = $(this).data('state');
+ if (!state.hasValue && state.$date && !state.$date.value()) {
+ state.$date.trigger('focusval');
+ } else {
+ if (!state.hasValue) {
+ setValue(state, new Date());
+ } else {
+ updateValue(state);
+ }
+ selectHours(state);
+ }
+ }
+ function onBlur(e) {
+ var state = $(this).data('state');
+ updateValue(state, true);
+ }
+ function onKeyDown(e) {
+ var state = $(this).data('state');
+ if (e.keyCode == Keys.LEFT) {
+ e.preventDefault();
+ selectHours(state);
+ }
+ else if (e.keyCode == Keys.RIGHT) {
+ e.preventDefault();
+ selectMinutes(state);
+ }
+ else if (e.keyCode == Keys.TAB) {
+ if (state.hoursSelected && !e.shiftKey) {
+ selectMinutes(state);
+ e.preventDefault();
+ } else if (state.minutesSelected && e.shiftKey) {
+ selectHours(state);
+ e.preventDefault();
+ }
+ }
+ else if (e.keyCode == Keys.BACKSPACE || e.keyCode == 46 || e.keyCode == 12) {
+ e.preventDefault();
+ if (state.hoursSelected) {
+ state.curHoursStr = '';
+ state.curHours = 0;
+ } else if (state.minutesSelected) {
+ state.curMinutesStr = '';
+ state.curMinutes = 0;
+ }
+ }
+ else if (e.keyCode >= 48 && e.keyCode < 58 || e.keyCode >= 96 && e.keyCode < 106) {
+ e.preventDefault();
+ var digit = e.keyCode >= 96 ? e.keyCode - 96 : e.keyCode - 48;
+ if (state.hoursSelected) {
+ state.curHoursStr += digit;
+ state.curHours = parseInt(state.curHoursStr);
+ if (state.curHoursStr.length == 2 || state.curHoursStr > 2) {
+ selectMinutes(state);
+ }
+ } else if (state.minutesSelected) {
+ state.curMinutesStr += digit;
+ state.curMinutesStr = state.curMinutesStr.substr(-2);
+ state.curMinutes = parseInt(state.curMinutesStr);
+ }
+ }
+ updateValue(state);
+ updateSelection(state);
+ }
+ function onSelect(e) {
+ if (!(this.selectionStart == 0 && this.selectionEnd == 2) &&
+ !(this.selectionStart == 3 && this.selectionEnd == 5)) {
+ var state = $(this).data('state');
+ if (this.selectionStart >= 3) {
+ selectMinutes(state);
+ } else {
+ selectHours(state);
+ }
+ }
+ }
+
+ function eSetValue(e, value) {
+ var state = $(this).data('state');
+ setValue(state, value);
+ }
+
+ function setValue(state, value) {
+ var curD = (value instanceof Date) ? value : new Date('2013-08-14T' + value);
+ if (isNaN(curD)) {
+ state.curHours = 0;
+ state.curMinutes = 0;
+ state.hasValue = false;
+ } else {
+ state.curHours = curD.getHours();
+ state.curMinutes = curD.getMinutes();
+ state.hasValue = true;
+ }
+ updateValue(state, true);
+ }
+
+ return this.each(function() {
+ var $input = $(this);
+ var $field = $input.parents('.js-time-input');
+ var $value = $('.js-time-value', $field);
+ var $timezone = $('.js-time-timezone', $field);
+ var state = {
+ hasValue: false,
+ curHoursStr: '',
+ curHours: 0,
+ curMinutesStr: '',
+ curMinutes: 0,
+ hoursSelected: true,
+ minutesSelected: false,
+ $input: $input,
+ $field: $field,
+ $value: $value
+ };
+ var $datetime = $input.parents('.datetime-group');
+ if ($datetime.size()) {
+ state.$date = $('input[type="date"]', $datetime);
+ }
+ if ($input.data('inited')) {
+ return;
+ }
+ $timezone.text(Ads.getTimezoneText());
+ $input.data('inited', true);
+ $input.data('state', state);
+ $value.on('focus.tr-timepicker', onFocus);
+ $value.on('click.tr-timepicker', onSelect);
+ $value.on('blur.tr-timepicker', onBlur);
+ $value.on('select.tr-timepicker', onSelect);
+ $value.on('keydown.tr-timepicker', onKeyDown);
+ $input.on('selectval.tr-timepicker', eSetValue);
+ $input.on('focusval.tr-timepicker', onFocusValue);
+ $value.data('state', state);
+ setValue(state, $input.attr('value'));
+ });
+ };
+ $.fn.destroyTimePicker = function() {
+ return this.each(function() {
+ var $input = $(this);
+ var state = $input.data('state');
+ $input.off('.tr-timepicker');
+ state.$value.off('.tr-timepicker');
+ });
+ };
+
+})(jQuery);