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 '
' + item.title + '
' + promote_link + '
' + formatNumber(item.views) + '
' + clicks + '
' + joins + '
' + ctr + '
' + Ads.wrapAmount(item.cpm) + '
' + cpc + '
' + cps + '
' + Ads.wrapAmount(item.spent) + '
' + Ads.wrapAmount(item.budget) + '
' + item.target + '
' + item.status + '
' + Ads.formatTableDate(item.date) + '
' + 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 '
' + item.title + '
' + promote_link + '
' + formatNumber(item.views) + '
' + clicks + '
' + joins + '
' + ctr + '
' + Ads.wrapAmount(item.cpm) + '
' + cpc + '
' + cps + '
' + Ads.wrapAmount(item.spent) + daily_spent + '
' + Ads.wrapAmount(item.budget) + '' + daily_budget + '
' + item.target + '
' + item.status + '
' + Ads.formatTableDate(item.date) + '
' + 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);