<dt>
<label>{lang}wcf.poll.options{/lang}</label>
</dt>
- <dd id="pollOptionContainer" class="sortableListContainer">
+ <dd id="pollOptionContainer" class="pollOptionContainer sortableListContainer">
<ol class="sortableList"></ol>
{if $errorField == 'pollOptions'}
<small class="innerError">
--- /dev/null
+{if $__showPoll|isset && $__showPoll}
+ <script data-relocate="true">
+ //<![CDATA[
+ $(function() {
+ WCF.Language.addObject({
+ 'wcf.poll.button.addOption': '{lang}wcf.poll.button.addOption{/lang}',
+ 'wcf.poll.button.removeOption': '{lang}wcf.poll.button.removeOption{/lang}'
+ });
+
+ new WCF.Poll.Management(
+ 'pollOptionContainer_{$wysiwygSelector}',
+ [ {implode from=$pollOptions item=pollOption}{ optionID: {@$pollOption[optionID]}, optionValue: '{$pollOption[optionValue]|encodeJS}' }{/implode} ],
+ {@POLL_MAX_OPTIONS},
+ '{$wysiwygSelector}'
+ );
+ });
+ //]]>
+ </script>
+
+ <div class="jsOnly messageTabMenuContent">
+ <dl>
+ <dt>
+ <label for="pollQuestion_{$wysiwygSelector}">{lang}wcf.poll.question{/lang}</label>
+ </dt>
+ <dd>
+ <input type="text" name="pollQuestion" id="pollQuestion_{$wysiwygSelector}" value="{$pollQuestion}" class="long" maxlength="255">
+ </dd>
+ <dt>
+ <label>{lang}wcf.poll.options{/lang}</label>
+ </dt>
+ <dd id="pollOptionContainer_{$wysiwygSelector}" class="pollOptionContainer sortableListContainer">
+ <ol class="sortableList"></ol>
+ <small>{lang}wcf.poll.options.description{/lang}</small>
+ </dd>
+ </dl>
+ <dl>
+ <dt>
+ <label for="pollEndTime_{$wysiwygSelector}">{lang}wcf.poll.endTime{/lang}</label>
+ </dt>
+ <dd>
+ <input type="datetime" name="pollEndTime" id="pollEndTime_{$wysiwygSelector}" value="{if $pollEndTime}{@$pollEndTime|date:'c'}{/if}" class="medium" data-ignore-timezone="true">
+ </dd>
+ </dl>
+ <dl>
+ <dt>
+ <label for="pollMaxVotes_{$wysiwygSelector}">{lang}wcf.poll.maxVotes{/lang}</label>
+ </dt>
+ <dd>
+ <input type="number" name="pollMaxVotes" id="pollMaxVotes_{$wysiwygSelector}" value="{@$pollMaxVotes}" min="1" class="tiny">
+ </dd>
+ </dl>
+ <dl>
+ <dt></dt>
+ <dd>
+ <label><input type="checkbox" name="pollIsChangeable" value="1"{if $pollIsChangeable} checked{/if}> {lang}wcf.poll.isChangeable{/lang}</label>
+ </dd>
+ {if !$pollID && $__wcf->getPollManager()->canStartPublicPoll()}
+ <dd>
+ <label><input type="checkbox" name="pollIsPublic" value="1"{if $pollIsPublic} checked{/if}> {lang}wcf.poll.isPublic{/lang}</label>
+ </dd>
+ {/if}
+ <dd>
+ <label><input type="checkbox" name="pollResultsRequireVote" value="1"{if $pollResultsRequireVote} checked{/if}> {lang}wcf.poll.resultsRequireVote{/lang}</label>
+ <small>{lang}wcf.poll.resultsRequireVote.description{/lang}</small>
+ </dd>
+ <dd>
+ <label><input type="checkbox" name="pollSortByVotes" value="1"{if $pollSortByVotes} checked{/if}> {lang}wcf.poll.sortByVotes{/lang}</label>
+ </dd>
+ </dl>
+
+ {event name='fields'}
+ </div>
+{/if}
\ No newline at end of file
{assign var=smileyCategories value=$__wcf->getSmileyCache()->getVisibleCategories()}
{if !$permissionCanUseSmilies|isset}{assign var=permissionCanUseSmilies value='user.message.canUseSmilies'}{/if}
{if !$wysiwygContainerID|isset}{assign var=wysiwygContainerID value='text'}{/if}
+{if !$wysiwygSelector|isset}{assign var=wysiwygSelector value=$wysiwygContainerID}{/if}
{capture assign='__messageFormSettingsInlineContent'}{include file='messageFormSettingsInline'}{/capture}
{assign var='__messageFormSettingsInlineContent' value=$__messageFormSettingsInlineContent|trim}
{if MODULE_SMILEY && $__wcf->getSession()->getPermission($permissionCanUseSmilies) && $smileyCategories|count}<li data-name="smilies"><a><span class="icon icon16 fa-smile-o"></span> <span>{lang}wcf.message.smilies{/lang}</span></a></li>{/if}
{if MODULE_ATTACHMENT && !$attachmentHandler|empty && $attachmentHandler->canUpload()}<li data-name="attachments"><a><span class="icon icon16 fa-paperclip"></span> <span>{lang}wcf.attachment.attachments{/lang}</span></a></li>{/if}
{if $__messageFormSettingsInlineContent}<li data-name="settings"><a><span class="icon icon16 fa-cog"></span> <span>{lang}wcf.message.settings{/lang}</span></a></li>{/if}
+ {if $__showPoll|isset && $__showPoll}<li data-name="poll"><a><span class="icon icon16 fa-bar-chart"></span> <span>{lang}wcf.poll.management{/lang}</span></a></li>{/if}
{event name='tabMenuTabs'}
</ul>
</nav>
{if $__messageFormSettingsInlineContent}{@$__messageFormSettingsInlineContent}{/if}
+ {include file='__messageFormPollInline'}
+
{event name='tabMenuContents'}
</div>
*/
_count: 0,
+ /**
+ * editor element id
+ * @var string
+ */
+ _editorId: '',
+
/**
* maximum allowed number of options
* @var int
/**
* Initializes the WCF.Poll.Management class.
*
- * @param string containerID
- * @param array<object> optionList
- * @param integer maxOptions
+ * @param {string} containerID
+ * @param {Object[]} optionList
+ * @param {int} maxOptions
+ * @param {string} editorId
*/
- init: function(containerID, optionList, maxOptions) {
+ init: function(containerID, optionList, maxOptions, editorId) {
this._count = 0;
this._maxOptions = maxOptions || -1;
this._container = $('#' + containerID).children('ol:eq(0)');
return;
}
- optionList = optionList || [ ];
+ optionList = optionList || [];
this._createOptionList(optionList);
// bind event listener
- this._container.parents('form').submit($.proxy(this._submit, this));
+ if (editorId) {
+ this._editorId = editorId;
+
+ WCF.System.Event.addListener('com.woltlab.wcf.redactor2', 'reset_' + editorId, this._reset.bind(this));
+ WCF.System.Event.addListener('com.woltlab.wcf.redactor2', 'submit_' + editorId, this._submit.bind(this));
+ }
+ else {
+ this._container.parents('form').submit($.proxy(this._submit, this));
+ }
// init sorting
new WCF.Sortable.List(containerID, '', undefined, {
return false;
}
- var $listItem = $(event.currentTarget).parents('li');
+ var $listItem = $(event.currentTarget).closest('li', this._container[0]);
this._createOption(undefined, undefined, $listItem);
},
* @param object event
*/
_removeOption: function(event) {
- $(event.currentTarget).parents('li').remove();
+ $(event.currentTarget).closest('li', this._container[0]).remove();
this._count--;
this._container.find('span.jsAddOption').addClass('pointer').removeClass('disabled');
/**
* Inserts hidden input elements storing the option values.
+ *
+ * @param {(Event|Object)} event
*/
- _submit: function() {
- var $options = [ ];
- this._container.children('li').each(function(index, listItem) {
+ _submit: function(event) {
+ var $options = [];
+ this._container.children('li').each(function (index, listItem) {
var $listItem = $(listItem);
var $optionValue = $.trim($listItem.find('input').val());
// ignore empty values
if ($optionValue != '') {
- $options.push({
- optionID: $listItem.data('optionID'),
- optionValue: $optionValue
- });
+ $options.push($listItem.data('optionID') + '_' + $optionValue);
}
});
- // create hidden input fields
- if ($options.length) {
- var $formSubmit = this._container.parents('form').find('.formSubmit');
-
- for (var $i = 0, $length = $options.length; $i < $length; $i++) {
- var $option = $options[$i];
- $('<input type="hidden" name="pollOptions[' + $i + ']" />').val($option.optionID + '_' + $option.optionValue).appendTo($formSubmit);
+ if (event instanceof Event) {
+ // create hidden input fields
+ if ($options.length) {
+ var $formSubmit = this._container.parents('form').find('.formSubmit');
+
+ for (var $i = 0, $length = $options.length; $i < $length; $i++) {
+ $('<input type="hidden" name="pollOptions[' + $i + ']">').val($options[$i]).appendTo($formSubmit);
+ }
}
}
+ else {
+ event.poll = { pollOptions: $options };
+
+ // get form input fields
+ var parentContainer = this._container.parents('.messageTabMenuContent:eq(0)');
+ parentContainer.find('input').each(function(index, input) {
+ if (input.name) {
+ if (input.type !== 'checkbox' || input.checked) {
+ event.poll[input.name] = input.value;
+ }
+ }
+ });
+ }
+ },
+
+ /**
+ * Resets the poll option form.
+ *
+ * @private
+ */
+ _reset: function() {
+ // reset options
+ /** @type Element */
+ var container = this._container[0];
+ while (container.childElementCount > 1) {
+ container.removeChild(container.children[1]);
+ }
+
+ elBySel('input', container.children[0]).value = '';
+
+ // reset input fields and checkboxes
+ var parentContainer = this._container.parents('.messageTabMenuContent:eq(0)');
+ parentContainer.find('input').each(function(index, input) {
+ if (input.name) {
+ if (input.type === 'checkbox') {
+ input.checked = false;
+ }
+ else if (input.type === 'text') {
+ input.value = '';
+ }
+ else if (input.type === 'number') {
+ input.value = input.min;
+ }
+ }
+ });
+
+ // reset date picker
+ require(['WoltLab/WCF/Date/Picker'], (function(UiDatePicker) {
+ UiDatePicker.clear('pollEndTime_' + this._editorId);
+ }).bind(this));
}
});
* Date picker with time support.
*
* @author Alexander Ebert
- * @copyright 2001-2015 WoltLab GmbH
+ * @copyright 2001-2016 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @module WoltLab/WCF/Date/Picker
*/
/**
* Renders the full picker on init.
*
- * @param {integer} day
- * @param {integer} month
- * @param {integer} year
+ * @param {int} day
+ * @param {int} month
+ * @param {int} year
*/
_renderPicker: function(day, month, year) {
this._renderGrid(day, month, year);
/**
* Updates the date grid.
*
- * @param {integer} day
- * @param {integer} month
- * @param {integer} year
+ * @param {int} day
+ * @param {int} month
+ * @param {int} year
*/
_renderGrid: function(day, month, year) {
- var cell, hasDay = (day !== undefined), hasMonth = (month !== undefined);
+ var cell, hasDay = (day !== undefined), hasMonth = (month !== undefined), i;
day = ~~day || ~~elData(_dateGrid, 'day');
month = ~~month;
}
var selectable;
- for (var i = 0; i < 35; i++) {
+ for (i = 0; i < 35; i++) {
cell = _dateCells[i];
cell.textContent = date.getDate();
}
if (rebuildMonths) {
- for (var i = 0; i < 12; i++) {
+ for (i = 0; i < 12; i++) {
var currentMonth = _dateMonth.children[i];
currentMonth.disabled = (year === _minDate.getFullYear() && currentMonth.value < _minDate.getMonth()) || (year === _maxDate.getFullYear() && currentMonth.value > _maxDate.getMonth());
// update active day
if (day) {
- for (var i = 0; i < 35; i++) {
+ for (i = 0; i < 35; i++) {
cell = _dateCells[i];
cell.classList[(!cell.classList.contains('otherMonth') && ~~cell.textContent === day) ? 'add' : 'remove']('active');
selectWrapper.appendChild(_dateMonth);
monthYearContainer.appendChild(selectWrapper);
- var months = '', monthNames = Language.get('__monthsShort');
- for (var i = 0; i < 12; i++) {
+ var i, months = '', monthNames = Language.get('__monthsShort');
+ for (i = 0; i < 12; i++) {
months += '<option value="' + i + '">' + monthNames[i] + '</option>';
}
_dateMonth.innerHTML = months;
_dateGrid.appendChild(item);
var span, weekdays = Language.get('__daysShort');
- for (var i = 0; i < 7; i++) {
+ for (i = 0; i < 7; i++) {
var day = i + _firstDayOfWeek;
if (day > 6) day -= 7;
// create date grid
var callbackClick = this._click.bind(this), cell, row;
- for (var i = 0; i < 5; i++) {
+ for (i = 0; i < 5; i++) {
row = elCreate('li');
_dateGrid.appendChild(row);
var tmp = '';
var date = new Date(2000, 0, 1);
var timeFormat = Language.get('wcf.date.timeFormat').replace(/:/, '').replace(/[isu]/g, '');
- for (var i = 0; i < 24; i++) {
+ for (i = 0; i < 24; i++) {
date.setHours(i);
tmp += '<option value="' + i + '">' + DateUtil.format(date, timeFormat) + "</option>";
}
_dateMinute.className = 'minute';
_dateMinute.addEventListener('change', this._formatValue.bind(this));
- var tmp = '';
- for (var i = 0; i < 60; i++) {
+ tmp = '';
+ for (i = 0; i < 60; i++) {
tmp += '<option value="' + i + '">' + (i < 10 ? '0' + i.toString() : i) + '</option>';
}
_dateMinute.innerHTML = tmp;
/**
* Sets the date of given element.
*
- * @param {(Element|string)} element input element or id
- * @param {Date} date Date object
+ * @param {(HTMLInputElement|string)} element input element or id
+ * @param {Date} date Date object
*/
setDate: function(element, date) {
element = this._getElement(element);
/**
* Clears the date value of given element.
*
- * @param {(Element|string)} element input element or id
+ * @param {(HTMLInputElement|string)} element input element or id
*/
clear: function(element) {
element = this._getElement(element);
/**
* Reverts the date picker into a normal input field.
*
- * @param {(Element|string)} element input element or id
+ * @param {(HTMLInputElement|string)} element input element or id
*/
destroy: function(element) {
element = this._getElement(element);
var id = this._getEditorId();
EventHandler.fire('com.woltlab.wcf.redactor2', 'getText_' + id, parameters.data);
- EventHandler.fire('com.woltlab.wcf.messageOptionsInline', 'submit_' + id, parameters);
+ EventHandler.fire('com.woltlab.wcf.redactor2', 'submit_' + id, parameters);
Ajax.api(this, {
actionName: 'save',
}
}
+ // handle poll
+ if (typeof data.returnValues.poll === 'string') {
+ // find current poll
+ var poll = elBySel('.pollContainer', elementData.messageBody);
+ if (poll !== null) {
+ // poll contain is wrapped inside `.jsInlineEditorHideContent`
+ elRemove(poll.parentNode);
+ }
+
+ var pollContainer = elCreate('div');
+ pollContainer.className = 'jsInlineEditorHideContent';
+ DomUtil.setInnerHtml(pollContainer, data.returnValues.poll);
+
+ DomUtil.prepend(pollContainer, elementData.messageBody);
+ }
+
this._restoreMessage();
this._updateHistory(this._getHash(this._getObjectId(this._activeElement)));
return [
'lastPostTime' => $message->time,
+ 'objectID' => $message->getObjectID(),
'template' => WCF::getTPL()->fetch($templateName, $application)
];
}
else {
// redirect
- return ['url' => $object->getRedirectUrl($this->container, $message)];
+ return [
+ 'objectID' => $message->getObjectID(),
+ 'url' => $object->getRedirectUrl($this->container, $message)
+ ];
}
}
/**
* Reads form parameters for polls.
+ *
+ * @param array $postData optional post data to be used instead of $_POST
*/
- public function readFormParameters() {
+ public function readFormParameters(array $postData = array()) {
+ if (empty($postData)) {
+ $postData &= $_POST;
+ }
+
// reset poll data and options prior to reading form input
$this->pollData = $this->pollOptions = [];
// poll data
- if (isset($_POST['pollEndTime'])) {
- $d = \DateTime::createFromFormat('Y-m-d H:i', $_POST['pollEndTime'], WCF::getUser()->getTimeZone());
+ if (isset($postData['pollEndTime'])) {
+ $d = \DateTime::createFromFormat('Y-m-d H:i', $postData['pollEndTime'], WCF::getUser()->getTimeZone());
$this->pollData['endTime'] = ($d !== false) ? $d->getTimestamp() : 0;
}
- if (isset($_POST['pollMaxVotes'])) $this->pollData['maxVotes'] = max(intval($_POST['pollMaxVotes']), 1); // force a minimum of 1
- if (isset($_POST['pollQuestion'])) $this->pollData['question'] = StringUtil::trim($_POST['pollQuestion']);
+ if (isset($postData['pollMaxVotes'])) $this->pollData['maxVotes'] = max(intval($postData['pollMaxVotes']), 1); // force a minimum of 1
+ if (isset($postData['pollQuestion'])) $this->pollData['question'] = StringUtil::trim($postData['pollQuestion']);
// boolean values
- $this->pollData['isChangeable'] = (isset($_POST['pollIsChangeable'])) ? 1 : 0;
- $this->pollData['resultsRequireVote'] = (isset($_POST['pollResultsRequireVote'])) ? 1 : 0;
- $this->pollData['sortByVotes'] = (isset($_POST['pollSortByVotes'])) ? 1 : 0;
+ $this->pollData['isChangeable'] = (isset($postData['pollIsChangeable'])) ? 1 : 0;
+ $this->pollData['resultsRequireVote'] = (isset($postData['pollResultsRequireVote'])) ? 1 : 0;
+ $this->pollData['sortByVotes'] = (isset($postData['pollSortByVotes'])) ? 1 : 0;
if ($this->poll === null) {
- $this->pollData['isPublic'] = (isset($_POST['pollIsPublic']) && $this->canStartPublicPoll()) ? 1 : 0;
+ $this->pollData['isPublic'] = (isset($postData['pollIsPublic']) && $this->canStartPublicPoll()) ? 1 : 0;
}
else {
// visibility cannot be changed after creation
}
// poll options
- if (isset($_POST['pollOptions']) && is_array($_POST['pollOptions'])) {
- foreach ($_POST['pollOptions'] as $showOrder => $value) {
+ if (isset($postData['pollOptions']) && is_array($postData['pollOptions'])) {
+ foreach ($postData['pollOptions'] as $showOrder => $value) {
list($optionID, $optionValue) = explode('_', $value, 2);
$this->pollOptions[$showOrder] = [
'optionID' => intval($optionID),
/* poll create/edit form */
-#pollOptionContainer .pollOptionInput {
+.pollOptionContainer .pollOptionInput {
align-items: center;
margin: 5px 0;