diff --git a/module/Core/public/js/jquery.summary-form.js b/module/Core/public/js/jquery.summary-form.js index 45c24f6f0..30ac51f7f 100644 --- a/module/Core/public/js/jquery.summary-form.js +++ b/module/Core/public/js/jquery.summary-form.js @@ -117,7 +117,11 @@ holdupRefUntiliFramesAreSaved = function (targetRef, triggerRef) { this.$summaryContainer.hide().css('opacity', 0); } - this.$formContainer.find('form').on('yk.forms.done', $.proxy(this.submit, this)); + this.$formContainer.find('form').on('yk.forms.done', $.proxy(this.submit, this)) + .find(':input') + .change(function(e) { + $(e.target).parents('.sf-container').addClass("yk-changed"); + }); this.$formContainer.find('.sf-cancel').click($.proxy(this.cancel, this)); } @@ -137,61 +141,55 @@ holdupRefUntiliFramesAreSaved = function (targetRef, triggerRef) { /** * ensures that all forms in the summary-form are saved before executing a link */ - $.fn.summaryformEnsureSave = function () + $.fn.summaryform.ensureSave = function (event) { - //console.log("a onClick", this); - $(this).click(function(event) { - var returnValue = true; - var eventTarget = event.target; - $(".sf-container").each(function() { - var containers = $(this); - if (containers.hasClass("yk-changed")) { - //console.log("test-container", containers, containers.hasClass("yk-changed")); - var sfForm = $(this).find(".sf-form"); - var sfSummary = $(this).find(".sf-summary"); - var title = $(this).find(".sf-headline").text(); - if (sfForm.length == 1 && sfSummary.length == 1) { - //console.log(title, sfForm.css("display"), sfSummary.css("display")); - if (sfForm.css("display") == "block" && sfSummary.css("display") == "none") { - var res = confirm("Form '" + title + "' has not been saved\ncontinue ?"); - if (!res) { - // set the return-value and end the loop, so that you don't have to go through all other open forms - returnValue = false; - // this return is intentional, it ends the each loop primarily - like a break statement would end a normal for-loop - return false; - } - else { - containers.removeClass('yk-changed'); - } + var returnValue = true; + var eventTarget = event.target; + + if (eventTarget.href.match(/#/)) { + return true; + } + + $(".sf-container").each(function() { + var containers = $(this); + if (containers.hasClass("yk-changed")) { + //console.log("test-container", containers, containers.hasClass("yk-changed")); + var sfForm = $(this).find(".sf-form"); + var sfSummary = $(this).find(".sf-summary"); + var title = $(this).find(".sf-headline").text(); + if (sfForm.length == 1 && sfSummary.length == 1) { + //console.log(title, sfForm.css("display"), sfSummary.css("display")); + if (sfForm.css("display") == "block" && sfSummary.css("display") == "none") { + var res = confirm("Form '" + title + "' has not been saved\ncontinue ?"); + if (!res) { + // set the return-value and end the loop, so that you don't have to go through all other open forms + returnValue = false; + // this return is intentional, it ends the each loop primarily - like a break statement would end a normal for-loop + return false; + } + else { + containers.removeClass('yk-changed'); } } } - }); - //console.log("returnValue", returnValue); + } + }); + //console.log("returnValue", returnValue); - // test for not saved tinyMC-Editoren in the iFrame - returnValue = returnValue && holdupRefUntiliFramesAreSaved(eventTarget, false); + // test for not saved tinyMC-Editoren in the iFrame + returnValue = returnValue && holdupRefUntiliFramesAreSaved(eventTarget, false); - return returnValue; - }); - } + return returnValue; - $.fn.markChangeTrigger = function () - { - $(this).find(":input").change(function(event) { - var target = event.target; - console.log('changed', target); - $(target).parents(".sf-container").addClass("yk-changed"); - }); - } + }; /** * initialize on DocumentReady here */ $(function() { $(".sf-container").summaryform(); - $("a").summaryformEnsureSave(); - $(".sf-container").markChangeTrigger(); + $("a").click($.fn.summaryform.ensureSave); + //$(".sf-container").markChangeTrigger(); }); })(jQuery); \ No newline at end of file diff --git a/module/Jobs/public/js/form.multiposting-select.js b/module/Jobs/public/js/form.multiposting-select.js index 209a0be36..40b719f9e 100644 --- a/module/Jobs/public/js/form.multiposting-select.js +++ b/module/Jobs/public/js/form.multiposting-select.js @@ -13,48 +13,67 @@ ; (function ($) { + var resultTmpl = null; + var selectTmpl = null; + var numberFormat = { + 'delimiter': ',', + 'decimal': '.' + }; + + function displayResult(item) { if (item.children) { return item.text; } - console.debug(item); - var data = parseTextToJson(item.text); - console.debug(data); + var data = $.fn.multipostingSelect.getOptionData(item.text); var link = '' + data.linkText + ''; - var desc = data.desc.replace(/%s/, link); + data.desc = data.desc.replace(/%s/, link); - return $('' + data.name + ' - ' + data.headline + '
' + desc + ''); + return tmpl(resultTmpl, data); } function displaySelection(item) { - var data = parseTextToJson(item.text); + var data = $.fn.multipostingSelect.getOptionData(item.text); - return data.name + ' ( ' + data.duration + ' )'; + return tmpl(selectTmpl, data); } - function parseTextToJson(text) + function updatePrice(e) { - var textArr = text.split('|'); + var $select = $(e.target); + var selected = $select.find('option:selected'); + var sum = $.fn.multipostingSelect.calculatePrice(selected); + var price = $.fn.multipostingSelect.formatPrice(sum, numberFormat); + + $('#' + $select.attr('id') + '-total span').text(price); - return { - name: textArr[0], - headline: textArr[1], - desc: textArr[2], - linkText: textArr[3], - link: textArr[4], - duration: textArr[5] - }; } + function tmpl(template, vars) + { + for (var key in vars) { + var search = new RegExp('%' + key, 'gi'); + template = template.replace(search, vars[key]); + } + + return template; + } $(function() { - var $select = $('#jobPortals-channel'); + var $select = $('#jobPortals-portals'); var data = $select.data(); - //var $eventSelect = $(".js-example-events"); + + // get templates + var id = $select.attr('id'); + resultTmpl = $('span#' + id + '-result-tmpl').data('template'); + selectTmpl = $('span#' + id + '-select-tmpl').data('template'); + numberTmpl = $('span#' + id + '-currency-tmpl').data('template'); + numberFormat.delimiter = numberTmpl.substr(1,1); + numberFormat.decimal = numberTmpl.substr(5,1); $select.select2({ //allowClear: true, @@ -62,8 +81,50 @@ formatResult: displayResult, formatSelection: displaySelection }); - console.debug($select); + + $select.on("change", updatePrice); + $select.trigger('change'); }); + $.fn.multipostingSelect = {}; + $.fn.multipostingSelect.formatPrice = function(price, numberFormat) + { + price = price.toFixed(2) + .replace(".", numberFormat.decimal) + .replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1" + numberFormat.delimiter); + + return price; + + }; + + $.fn.multipostingSelect.calculatePrice = function(selectedOptions) + { + var sum = 0; + + for (var i= 0, c=selectedOptions.length; igetHeadLine() . '|' . $channel->getDescription() . '|' . $channel->getLinkText() . '|' - . $link . '|' . $channel->getPublishDuration(); + . $link . '|' . $channel->getPublishDuration() . '|' + . $channel->getFormattedPrice() . '|' + . $channel->getPrice(); } diff --git a/module/Jobs/src/Jobs/Form/MultipostFieldset.php b/module/Jobs/src/Jobs/Form/MultipostFieldset.php index c1b8a7070..21988dab1 100644 --- a/module/Jobs/src/Jobs/Form/MultipostFieldset.php +++ b/module/Jobs/src/Jobs/Form/MultipostFieldset.php @@ -10,13 +10,17 @@ namespace Jobs\Form; +use Core\Entity\DraftableEntityInterface; use Zend\Form\Fieldset; use Core\Entity\Hydrator\EntityHydrator; -use Zend\Stdlib\ArrayUtils; -use Core\Form\ViewPartialProviderInterface; -use Core\Form\propagateAttributeInterface; -class MultipostFieldset extends Fieldset implements propagateAttributeInterface +/** + * + * @author Mathias Weitz + * @author Mathias Gelhausen + * @todo write test + */ +class MultipostFieldset extends Fieldset { public function getHydrator() @@ -33,110 +37,28 @@ public function getHydrator() */ public function init() { - $portals = $this->getFormFactory()->getFormElementManager()->getServiceLocator()->get('Jobs/Options/Provider'); $this->setAttribute('id', 'jobportals-fieldset'); $this->setName('jobPortals'); - - foreach ($portals as $key=>$portal) { - if (empty($portal->label)) { - throw new \RuntimeException('missing label'); - } - - $options=array( - 'long_label' => $portal->description, - 'headline' => $portal->headLine, - 'linktext' => $portal->linkText, - 'route' => $portal->route, - 'params' => $portal->params, - 'label' => $portal->label, - ); - - $this->add( - array( - // at some point we need an own Element for additional specific information like duration or premiums - // InfoCheckbox is just a surrogate - //'type' => 'Jobs/portalsElement', - 'label' => $portal->label, - 'type' => 'InfoCheckbox', - 'property' => true, - 'name' => $key, - 'options' => $options, - 'attributes' => array( - 'data-trigger' => 'submit', - ), - ) - ); - } - } - - public function enableAll($enable = true) - { - foreach ($this as $forms) { - $forms->setAttribute('disabled', 'disabled'); - } - return $this; - } - - /** - * @return array - */ - protected function extract() - { - $object = $this->getObject(); - $values = $object->getPortals(); - $formValues = array(); - foreach ($values as $key => $value) { - $formValues[$key] = $value['active']; - } - return $formValues; - } - - public function bindValues(array $values = array()) - { - $aggregateValues = $this->makeAggregateValues($values); - $object = $this->getObject(); - $object->setPortals($aggregateValues); - return $this->object; + $this->add( + array( + 'type' => 'Jobs\MultipostingSelect', + 'property' => true, + 'name' => 'portals', + 'options' => array( + 'label' => /*@translate*/ 'Portals', + ), + ) + ); } - /** - * usual this function should write all values into the - * @param array|\Traversable $data - * @throws \InvalidArgumentException - * @return void - */ - public function populateValues($data) + public function setObject($object) { - if (!is_array($data) && !$data instanceof \Traversable) { - throw new \InvalidArgumentException(sprintf( - '%s expects an array or Traversable set of data; received "%s"', - __METHOD__, - (is_object($data) ? get_class($data) : gettype($data)) - )); - } - - $aggregateValues = $this->makeAggregateValues($data); - } - - public function makeAggregateValues($data) - { - $aggregateValues = array(); - foreach ($data as $portalName => $portalValue) { - $valueExists = array_key_exists($portalName, $this->byName); - if (!$valueExists) { - # throw new Exception\InvalidArgumentException('value does not exist'); - continue; + if ($object instanceOf DraftableEntityInterface && !$object->isDraft()) + foreach ($this as $element) { + $element->setAttribute('disabled', 'disabled'); } - - // set the element Values - // @TODO set the element values in populateValues (that means untwisting them there) - $element = $this->byName[$portalName]; - $element->setValue($data[$portalName]); - $aggregateValues[$portalName] = array('active' => $portalValue, 'name' => $portalName); - } - return $aggregateValues; + return parent::setObject($object); } - -} \ No newline at end of file +} diff --git a/module/Jobs/src/Jobs/Form/PreviewFieldset.php b/module/Jobs/src/Jobs/Form/PreviewFieldset.php index 3c8a9efaf..5fac5883e 100644 --- a/module/Jobs/src/Jobs/Form/PreviewFieldset.php +++ b/module/Jobs/src/Jobs/Form/PreviewFieldset.php @@ -10,16 +10,16 @@ namespace Jobs\Form; +use Core\Entity\DraftableEntityInterface; use Zend\Form\Fieldset; use Core\Entity\Hydrator\EntityHydrator; -use Core\Form\propagateAttributeInterface; /** * Defines the formular files of the 3rd formular for entering a job opening * * @package Jobs\Form */ -class PreviewFieldset extends Fieldset implements propagateAttributeInterface +class PreviewFieldset extends Fieldset { public function getHydrator() { @@ -54,11 +54,12 @@ public function init() } - public function enableAll($enable = true) + public function setObject($object) { - foreach ($this as $forms) { - $forms->setAttribute('disabled', 'disabled'); + if ($object instanceOf DraftableEntityInterface && !$object->isDraft()) + foreach ($this as $element) { + $element->setAttribute('disabled', 'disabled'); } - return $this; + return parent::setObject($object); } } \ No newline at end of file diff --git a/module/Jobs/src/Jobs/Options/ChannelOptions.php b/module/Jobs/src/Jobs/Options/ChannelOptions.php index 36727b552..9835cc316 100644 --- a/module/Jobs/src/Jobs/Options/ChannelOptions.php +++ b/module/Jobs/src/Jobs/Options/ChannelOptions.php @@ -135,6 +135,24 @@ public function getKey() return $this->key; } + public function getFormattedPrice($currencyPosition = 'right') + { + + $price = sprintf('%01.2f', $this->getPrice()); + + if ('none' === $currencyPosition) { + return $price; + } + + $currency = $this->getCurrency(); + + if ('left' == $currencyPosition) { + return $currency . ' ' . $price; + } + + return $price . ' ' . $currency; + } + /** * Gets the price of a channel * diff --git a/module/Jobs/view/form/multiposting-select.phtml b/module/Jobs/view/form/multiposting-select.phtml index e24e05c25..cdac9c016 100644 --- a/module/Jobs/view/form/multiposting-select.phtml +++ b/module/Jobs/view/form/multiposting-select.phtml @@ -10,16 +10,18 @@ if ($this->renderSummary):?>
-
- -
-
+ +
element->getValueOptions(); $valueKey= $this->element->getValue(); $activePortals = array(); if ($valueKey && !empty($valueKey)): + + $this->plugin('currencyformat')->setCurrencyCode('EUR'); + $dispPrice = function($d) { return sprintf('%01.2f €', $d); }; + $total = 0; foreach ($options as $category => $categoryOptions): foreach ($categoryOptions['options'] as $channelName => $channel): if (in_array($channelName, $valueKey)): @@ -28,21 +30,69 @@ if ($this->renderSummary):?> endforeach; endforeach; - foreach ($activePortals as $category => $channels): + ?>
+ + - ?>
+ $channels):?> + + + + $spec): $data = explode('|', $spec); - ?>


- ' . $data[3] . '') ?> -

+ + + + +
translate('Price') ?>
translate('Total') ?> + currencyFormat($total); ?>
-formRow()->render($this->element, /* ignoreViewPartial */ true); -endif; // ($this->renderSummary) ?> \ No newline at end of file +formRow()->render($this->element, /* ignoreViewPartial */ true); + + + ?> +
+ +
+
+
+
+
+
+ +
+ %name - %headline
+ %desc +
+
+ %nicePrice +
+
+ '; + + $selectTmpl = ' + %name ( %duration ) [ %nicePrice ] + '; + + + ?> + + + $this->renderSummary) ?> \ No newline at end of file diff --git a/module/Jobs/view/jobs/manage/form.phtml b/module/Jobs/view/jobs/manage/form.phtml index 2d69967e1..4198631da 100644 --- a/module/Jobs/view/jobs/manage/form.phtml +++ b/module/Jobs/view/jobs/manage/form.phtml @@ -81,25 +81,41 @@ if ($this->page == 2):
translate('Your job opening is ready to be published to the following channels');?> - - - - - - job->portals as $channel):?> - - getChannel($name); ?> +
translate('Channel')?>translate('Price')?>
+ plugin('currencyFormat')->setCurrencyCode('EUR'); + + $portals = array(); + foreach($this->job->portals as $channelName): + + $channelData=$channels->getChannel($channelName); + $portals[$channelData->getCategory()][] = $channelData; + endforeach; + + foreach ($portals as $category => $channels):?> + + + + + + + + + - - - price;?> + + + price;?> - + + + + - - + + +
translate('Price') ?>
label?>price?> currency?> label?>currencyFormat($channel->price)?>
translate("Total")?> currency ?>translate("Total")?>currencyFormat($total) ?>
diff --git a/module/Jobs/view/mails/job-created.phtml b/module/Jobs/view/mails/job-created.phtml index e307194da..cfdaa9fa9 100644 --- a/module/Jobs/view/mails/job-created.phtml +++ b/module/Jobs/view/mails/job-created.phtml @@ -62,18 +62,18 @@ $sum = 0;

translate("Selected Channels") ?>

- job->portals as $portalName => $portal): ?> - + job->portals as $portalName): ?> + getChannel($portalName); ?> - + price; ?> - + - - + +
label ?>price ?> currency ?>currencyFormat($channelData->price, 'EUR') ?>
Preis (netto)
MwSt (19%)
Preis (netto)currencyFormat(round($sum / 1.19,2), 'EUR') ?>
MwSt (19%)currencyFormat(($sum - round($sum / 1.19,2)), 'EUR') ?>