<commit_before>var Form = function(router, templating, admin, translator)
{
  var self = this;

  var MessageType = {
    Info: 'info',
    Error: 'error',
    Success: 'success'
  };

  this.initDataPicker = function(form)
  {
    $(form).find('input.datetimepicker').datetimepicker({
      timeFormat: 'hh:mm',
      timeText: 'Zeit',
      hourText: 'Std.',
      minuteText: 'Min.',
      currentText: 'Jetzt',
      closeText: 'Fertig',
      dateFormat: 'dd.mm.yy',
      stepMinute: 5,
      firstDay: 1
    });

    $(form).find('input.datepicker').datepicker({
      closeText: 'Fertig',
      dateFormat: 'dd.mm.yy',
      firstDay: 1
    });
  };

  this.initRadioAndCheckbox = function (form) {
    $(form).find('input[type=radio],input[type=checkbox]').iCheck({
      checkboxClass: 'icheckbox-esperanto',
      radioClass: 'icheckbox-esperanto'
    });
  };

  this.initSelect = function (form) {
    $(form).find('select').select2();
  };

  this.destroyWysiwyg = function(content) {
    content.find('.wysiwyg').each(function() {
      tinymce.remove('#'.$(this).attr('id'));
    });
  };

  this.initWysiwyg = function(form)
  {
    var addTinymce = function(element) {

      var options = {
          // Location of TinyMCE script
          script_url : '/js/lib/tinymce/tinymce.min.js',
          //content_css: "/css/editor.css",
          menubar: false,
          // General options
          plugins: ["advlist autolink lists link image charmap print preview anchor",
              "searchreplace visualblocks code fullscreen",
              "insertdatetime media table contextmenu paste"],
          force_br_newlines : false,
          force_p_newlines : true,
          forced_root_block : "p",
          cleanup : false,
          cleanup_on_startup : false,
          font_size_style_values : "xx-small,x-small,small,medium,large,x-large,xx-large",
          convert_fonts_to_spans : true,
          resize: false,
          relative_urls : false,
          oninit: function(ed) {
              $(ed.contentAreaContainer).droppable({
                  accept: ".imgList li.imgContainer",
                  drop: function(event, ui) {
                      var draggedImg = ui.draggable.find("img");
                      var src = '';
                      if(typeof draggedImg.attr("largesrc") == "undefined") {
                          src = draggedImg.attr("src")
                      } else {
                          src = draggedImg.attr("largesrc");
                      }
                      ed.execCommand('mceInsertContent', false, "");
                  }
              });
          }
      };

      var config = $(element).data('config');

      if(config.height) {
          options.height = config.height;
      }

      if(config.style_formats) {
         options.style_formats = config.style_formats;
      }

      if(config.formats) {
          options.formats = config.formats;
      }

      if(config.toolbar1) {
          options.toolbar1 = config.toolbar1
      }

      if(config.toolbar2) {
          options.toolbar2 = config.toolbar2
      }

      if(config.content_css) {
        options.content_css = config.content_css
      }

      $(element).tinymce(options);
    };

    $(form).find('[data-wysiwyg]').each(function(index, element) {
      addTinymce(element);
    });
  };

  this.initSave = function (form) {
    $(form).find('[data-button][data-type=save]').click(function() {
      $(this).trigger('formSaveBefore', form);

      form = $(form);
      var data = form.serialize();
      var action = form.attr('action');
      $.ajax({
        type: 'POST',
        data: data,
        url: action,
        success: function(data) {
          $(form).trigger('formSaveAfter', form);
        },
        error: function(jqXHR) {
          var data = JSON.parse(jqXHR.responseText);

          if(data.code == 400) {
            var getErrors = function(data, errors) {
              if(typeof errors == 'undefined') {
                errors = [];
              }

              for (var key in data) {
                if(data.hasOwnProperty(key)) {

                  if(key == 'errors') {
                    for (var error in data[key]) {
                      if (data[key].hasOwnProperty(error) && typeof data[key][error] == 'string') {
                        errors.push(data[key][error]);
                      }
                    }
                  }

                  if (typeof data[key] == 'object') {
                    getErrors(data[key], errors);
                  }

                }
              }

              return errors
            };

            var errors = getErrors(data.errors);
            var message = '' + errors.join('

') + '';
            admin.overlayMessage(message, MessageType.Error);
          } else {
            admin.overlayMessage(translator.trans('error.occurred'), MessageType.Error);
          }
        }
      });
    });
  };

  this.initPreviewButton = function(form) {
    $(form).find('[data-button][data-type=preview]').click(function(e) {
      e.preventDefault();
      e.stopPropagation();
      var route = $(this).data('route');
      var link = router.generate(route);
      admin.iframeOverlay(form,link,{
        submit: true
      });
    });
  };

  this.initDelete = function(form)
  {
    $(form).find('[data-button][data-type=delete]').click(function() {
      var url = $(form).data('delete');
      if(confirm(translator.trans('form.delete.question'))) {
        $.ajax({
          type: 'POST',
          data: {
            _method: 'DELETE'
          },
          url: url,
          success: function() {
            $(form).trigger('formSaveAfter', form);
          },
          error: function() {
            alert(translator.trans('error.occurred'));
          }
        });
      }
    });
  };

  this.initSorting = function(form) {
    var setOrder = function() {
      $(form).find('[data-sort-order]').each(function(index, element) {
        $(element).val(index);
      });
    };

    $(form).find('[data-sort-up-button]').click(function() {
      var item = $(this).parents('[data-sort-row]');
      var container = item.parents('[data-sort-container]');
      var index = container.children().index(item);
      if(index > 0) { // is not first element
        $(container.children().get(index - 1)).before(item); //move element before last
      }
      setOrder();
    });

    $(form).find('[data-sort-down-button]').click(function() {
      var item = $(this).parents('[data-sort-row]');
      var container = item.parents('[data-sort-container]');
      var index = container.children().index(item);
      var size = container.children().size();

      if(index < (size - 1)) { // is not last element
        $(container.children().get(index + 1)).after(item); //move element after next
      }
      setOrder();
    });

    $(form).find('[data-sort-container]').sortable({
      update: function() {
        setOrder();
      },
      axis: 'y',
      cursor: "move",
      handle: '[data-sort-handle]'
    });

    setOrder();
  };

  this.initInput = function(form) {
    $(form).find('input').focus(function() {
      $(this).keypress(function(e) {
        if(e.which == 13) {
          event.preventDefault();
        }
      });
    })
  };

  var init = function() {
    $(document).on('formOpenAfter', function(event, form) {
      self.initDataPicker(form);
      self.initRadioAndCheckbox(form);
      self.initPreviewButton(form);
      self.initWysiwyg(form);
      self.initSave(form);
      self.initDelete(form);
      self.initSelect(form);
      self.initSorting(form);
      self.initInput(form);
    });

    $(document).on('formSaveAfter', function() {
      admin.overlayClose();
    });

    $(document).on('formCloseAfter', function(event, content) {
      self.destroyWysiwyg(content);
    });
  };

  init();
};
<commit_msg>initInput function changed<commit_after>var Form = function(router, templating, admin, translator)
{
  var self = this;

  var MessageType = {
    Info: 'info',
    Error: 'error',
    Success: 'success'
  };

  this.initDataPicker = function(form)
  {
    $(form).find('input.datetimepicker').datetimepicker({
      timeFormat: 'hh:mm',
      timeText: 'Zeit',
      hourText: 'Std.',
      minuteText: 'Min.',
      currentText: 'Jetzt',
      closeText: 'Fertig',
      dateFormat: 'dd.mm.yy',
      stepMinute: 5,
      firstDay: 1
    });

    $(form).find('input.datepicker').datepicker({
      closeText: 'Fertig',
      dateFormat: 'dd.mm.yy',
      firstDay: 1
    });
  };

  this.initRadioAndCheckbox = function (form) {
    $(form).find('input[type=radio],input[type=checkbox]').iCheck({
      checkboxClass: 'icheckbox-esperanto',
      radioClass: 'icheckbox-esperanto'
    });
  };

  this.initSelect = function (form) {
    $(form).find('select').select2();
  };

  this.destroyWysiwyg = function(content) {
    content.find('.wysiwyg').each(function() {
      tinymce.remove('#'.$(this).attr('id'));
    });
  };

  this.initWysiwyg = function(form)
  {
    var addTinymce = function(element) {

      var options = {
          // Location of TinyMCE script
          script_url : '/js/lib/tinymce/tinymce.min.js',
          //content_css: "/css/editor.css",
          menubar: false,
          // General options
          plugins: ["advlist autolink lists link image charmap print preview anchor",
              "searchreplace visualblocks code fullscreen",
              "insertdatetime media table contextmenu paste"],
          force_br_newlines : false,
          force_p_newlines : true,
          forced_root_block : "p",
          cleanup : false,
          cleanup_on_startup : false,
          font_size_style_values : "xx-small,x-small,small,medium,large,x-large,xx-large",
          convert_fonts_to_spans : true,
          resize: false,
          relative_urls : false,
          oninit: function(ed) {
              $(ed.contentAreaContainer).droppable({
                  accept: ".imgList li.imgContainer",
                  drop: function(event, ui) {
                      var draggedImg = ui.draggable.find("img");
                      var src = '';
                      if(typeof draggedImg.attr("largesrc") == "undefined") {
                          src = draggedImg.attr("src")
                      } else {
                          src = draggedImg.attr("largesrc");
                      }
                      ed.execCommand('mceInsertContent', false, "");
                  }
              });
          }
      };

      var config = $(element).data('config');

      if(config.height) {
          options.height = config.height;
      }

      if(config.style_formats) {
         options.style_formats = config.style_formats;
      }

      if(config.formats) {
          options.formats = config.formats;
      }

      if(config.toolbar1) {
          options.toolbar1 = config.toolbar1
      }

      if(config.toolbar2) {
          options.toolbar2 = config.toolbar2
      }

      if(config.content_css) {
        options.content_css = config.content_css
      }

      $(element).tinymce(options);
    };

    $(form).find('[data-wysiwyg]').each(function(index, element) {
      addTinymce(element);
    });
  };

  this.initSave = function (form) {
    $(form).find('[data-button][data-type=save]').click(function() {
      $(this).trigger('formSaveBefore', form);

      form = $(form);
      var data = form.serialize();
      var action = form.attr('action');
      $.ajax({
        type: 'POST',
        data: data,
        url: action,
        success: function(data) {
          $(form).trigger('formSaveAfter', form);
        },
        error: function(jqXHR) {
          var data = JSON.parse(jqXHR.responseText);

          if(data.code == 400) {
            var getErrors = function(data, errors) {
              if(typeof errors == 'undefined') {
                errors = [];
              }

              for (var key in data) {
                if(data.hasOwnProperty(key)) {

                  if(key == 'errors') {
                    for (var error in data[key]) {
                      if (data[key].hasOwnProperty(error) && typeof data[key][error] == 'string') {
                        errors.push(data[key][error]);
                      }
                    }
                  }

                  if (typeof data[key] == 'object') {
                    getErrors(data[key], errors);
                  }

                }
              }

              return errors
            };

            var errors = getErrors(data.errors);
            var message = '' + errors.join('

') + '';
            admin.overlayMessage(message, MessageType.Error);
          } else {
            admin.overlayMessage(translator.trans('error.occurred'), MessageType.Error);
          }
        }
      });
    });
  };

  this.initPreviewButton = function(form) {
    $(form).find('[data-button][data-type=preview]').click(function(e) {
      e.preventDefault();
      e.stopPropagation();
      var route = $(this).data('route');
      var link = router.generate(route);
      admin.iframeOverlay(form,link,{
        submit: true
      });
    });
  };

  this.initDelete = function(form)
  {
    $(form).find('[data-button][data-type=delete]').click(function() {
      var url = $(form).data('delete');
      if(confirm(translator.trans('form.delete.question'))) {
        $.ajax({
          type: 'POST',
          data: {
            _method: 'DELETE'
          },
          url: url,
          success: function() {
            $(form).trigger('formSaveAfter', form);
          },
          error: function() {
            alert(translator.trans('error.occurred'));
          }
        });
      }
    });
  };

  this.initSorting = function(form) {
    var setOrder = function() {
      $(form).find('[data-sort-order]').each(function(index, element) {
        $(element).val(index);
      });
    };

    $(form).find('[data-sort-up-button]').click(function() {
      var item = $(this).parents('[data-sort-row]');
      var container = item.parents('[data-sort-container]');
      var index = container.children().index(item);
      if(index > 0) { // is not first element
        $(container.children().get(index - 1)).before(item); //move element before last
      }
      setOrder();
    });

    $(form).find('[data-sort-down-button]').click(function() {
      var item = $(this).parents('[data-sort-row]');
      var container = item.parents('[data-sort-container]');
      var index = container.children().index(item);
      var size = container.children().size();

      if(index < (size - 1)) { // is not last element
        $(container.children().get(index + 1)).after(item); //move element after next
      }
      setOrder();
    });

    $(form).find('[data-sort-container]').sortable({
      update: function() {
        setOrder();
      },
      axis: 'y',
      cursor: "move",
      handle: '[data-sort-handle]'
    });

    setOrder();
  };

  this.initInput = function(form) {
    $('input').keypress(function(e) {
      if(e.which == 13) {
        event.preventDefault();
      }
    });
  };

  var init = function() {
    $(document).on('formOpenAfter', function(event, form) {
      self.initDataPicker(form);
      self.initRadioAndCheckbox(form);
      self.initPreviewButton(form);
      self.initWysiwyg(form);
      self.initSave(form);
      self.initDelete(form);
      self.initSelect(form);
      self.initSorting(form);
      self.initInput(form);
    });

    $(document).on('formSaveAfter', function() {
      admin.overlayClose();
    });

    $(document).on('formCloseAfter', function(event, content) {
      self.destroyWysiwyg(content);
    });
  };

  init();
};
<|endoftext|>


<commit_before>/**
 * Created by gseidel on 30/08/14.
 */

function UploadForm(routing)
{
  var self = this;

  this.initUploadForm = function(form) {
    var currentIndexes = [];
    var isMultiple = [];
    var selected = [];
    $(form).find('.uploadForm').each(function(formIndex, uploadForm) {
      isMultiple[formIndex] = $(this).data('multiple') == '1';

      if (isMultiple[formIndex]) {
        $(this).find('[data-file-list]').sortable({
          delay: 150,
          update: function() {
            self.setFileOrder(uploadForm);
          }
        });
      }

      currentIndexes[formIndex] = $(this).find('[data-file-element]').length-1;
      $(uploadForm).find('.fileupload').fileupload({
        dataType: 'json',

        done: function (event, data) {
          var list = $(uploadForm).find('.list');
          var inputName = list.attr('data-name');
          if (!isMultiple[formIndex]) {
            $(uploadForm).find('[data-file-list]').empty();
            if (data.result.files.length > 0) {
              var html = templating.render($(uploadForm).find('script[data-id=files-template]'), {
                file_id: data.result.files[0].id,
                full_name: inputName,
                file_index: 0,
                file_name: data.result.files[0].filename,
                file_slug: data.result.files[0].slug
              });
              $(uploadForm).find('[data-file-list]').append(html);
            }
          } else {
            $.each(data.result.files, function (index, file) {
              var html = templating.render($(uploadForm).find('script[data-id=files-template]'), {
                file_id: file.id,
                full_name: inputName,
                file_index: ++currentIndexes[formIndex],
                file_name: file.filename,
                file_slug: file.slug
              });
              $(uploadForm).find('[data-file-list]').append(html);
            });
            self.setFileOrder(uploadForm);
          }
          $(uploadForm).find('.progress .bar').css('width', '0%');
          $(uploadForm).find('.dropzone').removeClass('empty');
        },

        add: function (event, data) {
          data.submit();
        },

        progressall: function (event, data) {
          var progress = parseInt(data.loaded / data.total * 100, 10);
          $(uploadForm).find('.progress .bar').css('width', progress + '%');
        },

        dropZone: $(uploadForm).find('.dropzone')
      });

      $(uploadForm).find('.upload-button').click(function(event) {
        event.stopPropagation();
        event.preventDefault();
        $(uploadForm).find('.fileupload').trigger('click');
      });

      $(uploadForm).on('click', '.imgdelete', function(event)
      {
        var imageContainer = $(event.target).parents('.imgContainer');
        if(imageContainer != null) {
          if (imageContainer.hasClass('selected')) {
            $(uploadForm).find('.fileupload-fields').addClass('hidden').addClass('disabled');
          }
          var dropZone = imageContainer.parents('.dropzone');
          imageContainer.remove();
          if (dropZone.find('[data-file-element]').length == 0) {
            dropZone.addClass('empty');
          }
          event.stopPropagation();
        }
      });

      $(uploadForm).on('mouseenter', '.imgContainer', function(event) {
        var fileUploadFields = $(uploadForm).find('.fileupload-fields');
        $(uploadForm).find('.imgContainer').removeClass('selected');
        $(this).addClass('selected');
        if (typeof selected[formIndex] != 'undefined') {
          if (selected[formIndex].data('id') == $(this).data('id')) {
            fileUploadFields.removeClass('disabled');
            fileUploadFields.find('input').prop('disabled', false);
            self.loadFields(uploadForm, selected[formIndex]);
          } else {
            fileUploadFields.addClass('disabled');
            fileUploadFields.find('input').prop('disabled', true);
            self.loadFields(uploadForm, $(this));
          }
        } else {
          fileUploadFields.addClass('disabled');
          fileUploadFields.find('input').prop('disabled', true);
          self.loadFields(uploadForm, $(this));
        }
      });
      $(uploadForm).on('mouseleave', '.imgContainer', function(event) {
        var fileUploadFields = $(uploadForm).find('.fileupload-fields');
        $(uploadForm).find('.imgContainer').removeClass('selected');

        if (typeof selected[formIndex] != 'undefined') {
          selected[formIndex].addClass('selected');
          fileUploadFields.removeClass('disabled');
          fileUploadFields.find('input').prop('disabled', false);
          self.loadFields(uploadForm, selected[formIndex]);
        } else {
          fileUploadFields.addClass('disabled');
          fileUploadFields.find('input').each(function() {
            $(this).prop('disabled', true);
            $(this).val('');
         });
        }
      });
      $(uploadForm).on('click', '.imgContainer', function(event) {
        selected[formIndex] = $(this);
        selected[formIndex].addClass('selected');
        var fileUploadFields = $(uploadForm).find('.fileupload-fields');
        fileUploadFields.removeClass('hidden');
        fileUploadFields.removeClass('disabled');
        fileUploadFields.find('input').prop('disabled', false);
        event.stopPropagation();
      }).on('click', '.fileupload-fields', function(event) {
        event.stopPropagation();
      });
      $(form).on('click', function() {
        $(uploadForm).find('.fileupload-fields').addClass('hidden').addClass('disabled');
        $(uploadForm).find('.imgContainer.selected').removeClass('selected');
      });
      $(uploadForm).on('input', '.fileupload-field-input', function(event) {
        if (typeof selected[formIndex] != 'undefined') {
          selected[formIndex].find('[data-field-name="' + $(this).data('field-name') + '"]').val($(this).val());
          if ($(this).data('field-name') == "filename") {
            var slug = self.slugifyFileName($(this).val());
            selected[formIndex].find('[data-field-name="slug"]').val(slug);
            $(uploadForm).find('#fileupload-field-slug').html(slug);
          }
        }
      });
    });
    self.start();
  };

  this.setFileOrder = function(form) {
    $(form).find('[data-file-element-order]').each(function(index) {
      $(this).val(index);
    });
  };

  this.loadFields = function(form, source) {
    var fileUploadFields = $(form).find('.fileupload-fields');
    var slugField = $(form).find('#fileupload-field-slug');
    fileUploadFields.find('input').each(function() {
      $(this).val(source.find('[data-field-name="' + $(this).data('field-name') + '"]').val());
    });
    var slug = source.find('[data-field-name="' + slugField.data('field-name') + '"]').val();
    if (slug == "") {
      slug = self.slugifyFileName(source.find('[data-field-name="filename"]').val());
      source.find('[data-field-name="slug"]').val(slug);
    }
    slugField.html(slug);
  };

  this.slugifyFileName = function(text) {
    return text.toLowerCase()
      .replace(/\s+/g, '-')           // Replace spaces with -
      .replace(/[^\w\-\.]+/g, '')     // Remove all non-word chars
      .replace(/\-\-+/g, '-')         // Replace multiple - with single -
      .replace(/^-+/, '')             // Trim - from start of text
      .replace(/-+$/, '');            // Trim - from end of text
  };

  this.start = function() {
    $(document).bind('dragover', function (e)
    {
      $('.dropzone').css('background-color', '#49a4e5');
    });

    $(document).bind('dragleave drop', function (e)
    {
      $('.dropzone').css('background-color', '');
    });
  };

  this.init = function() {
    $(document).on('formOpenAfter', function(event, form) {
      self.initUploadForm(form);
    });
  };

  this.init();
}
var uploadForm = new UploadForm(Routing);

<commit_msg>Fixed bug where saving would not work for newly added media files<commit_after>/**
 * Created by gseidel on 30/08/14.
 */

function UploadForm(routing)
{
  var self = this;

  this.initUploadForm = function(form) {
    var currentIndexes = [];
    var isMultiple = [];
    var selected = [];
    $(form).find('.uploadForm').each(function(formIndex, uploadForm) {
      isMultiple[formIndex] = $(this).data('multiple') == '1';

      if (isMultiple[formIndex]) {
        $(this).find('[data-file-list]').sortable({
          delay: 150,
          update: function() {
            self.setFileOrder(uploadForm);
          }
        });
      }

      currentIndexes[formIndex] = $(this).find('[data-file-element]').length-1;
      $(uploadForm).find('.fileupload').fileupload({
        dataType: 'json',

        done: function (event, data) {
          var list = $(uploadForm).find('.list');
          var inputName = list.attr('data-name');
          if (!isMultiple[formIndex]) {
            $(uploadForm).find('[data-file-list]').empty();
            if (data.result.files.length > 0) {
              var html = templating.render($(uploadForm).find('script[data-id=files-template]'), {
                file_id: data.result.files[0].id,
                full_name: inputName,
                file_index: 0,
                file_name: data.result.files[0].filename,
                file_slug: data.result.files[0].slug
              });
              $(uploadForm).find('[data-file-list]').append(html);
            }
          } else {
            $.each(data.result.files, function (index, file) {
              var html = templating.render($(uploadForm).find('script[data-id=files-template]'), {
                file_id: file.id,
                full_name: inputName,
                file_index: ++currentIndexes[formIndex],
                file_name: file.filename,
                file_slug: file.slug
              });
              $(uploadForm).find('[data-file-list]').append(html);
            });
          }
          self.setFileOrder(uploadForm);
          $(uploadForm).find('.progress .bar').css('width', '0%');
          $(uploadForm).find('.dropzone').removeClass('empty');
        },

        add: function (event, data) {
          data.submit();
        },

        progressall: function (event, data) {
          var progress = parseInt(data.loaded / data.total * 100, 10);
          $(uploadForm).find('.progress .bar').css('width', progress + '%');
        },

        dropZone: $(uploadForm).find('.dropzone')
      });

      $(uploadForm).find('.upload-button').click(function(event) {
        event.stopPropagation();
        event.preventDefault();
        $(uploadForm).find('.fileupload').trigger('click');
      });

      $(uploadForm).on('click', '.imgdelete', function(event)
      {
        var imageContainer = $(event.target).parents('.imgContainer');
        if(imageContainer != null) {
          if (imageContainer.hasClass('selected')) {
            $(uploadForm).find('.fileupload-fields').addClass('hidden').addClass('disabled');
          }
          var dropZone = imageContainer.parents('.dropzone');
          imageContainer.remove();
          if (dropZone.find('[data-file-element]').length == 0) {
            dropZone.addClass('empty');
          }
          event.stopPropagation();
        }
      });

      $(uploadForm).on('mouseenter', '.imgContainer', function(event) {
        var fileUploadFields = $(uploadForm).find('.fileupload-fields');
        $(uploadForm).find('.imgContainer').removeClass('selected');
        $(this).addClass('selected');
        if (typeof selected[formIndex] != 'undefined') {
          if (selected[formIndex].data('id') == $(this).data('id')) {
            fileUploadFields.removeClass('disabled');
            fileUploadFields.find('input').prop('disabled', false);
            self.loadFields(uploadForm, selected[formIndex]);
          } else {
            fileUploadFields.addClass('disabled');
            fileUploadFields.find('input').prop('disabled', true);
            self.loadFields(uploadForm, $(this));
          }
        } else {
          fileUploadFields.addClass('disabled');
          fileUploadFields.find('input').prop('disabled', true);
          self.loadFields(uploadForm, $(this));
        }
      });
      $(uploadForm).on('mouseleave', '.imgContainer', function(event) {
        var fileUploadFields = $(uploadForm).find('.fileupload-fields');
        $(uploadForm).find('.imgContainer').removeClass('selected');

        if (typeof selected[formIndex] != 'undefined') {
          selected[formIndex].addClass('selected');
          fileUploadFields.removeClass('disabled');
          fileUploadFields.find('input').prop('disabled', false);
          self.loadFields(uploadForm, selected[formIndex]);
        } else {
          fileUploadFields.addClass('disabled');
          fileUploadFields.find('input').each(function() {
            $(this).prop('disabled', true);
            $(this).val('');
         });
        }
      });
      $(uploadForm).on('click', '.imgContainer', function(event) {
        selected[formIndex] = $(this);
        selected[formIndex].addClass('selected');
        var fileUploadFields = $(uploadForm).find('.fileupload-fields');
        fileUploadFields.removeClass('hidden');
        fileUploadFields.removeClass('disabled');
        fileUploadFields.find('input').prop('disabled', false);
        event.stopPropagation();
      }).on('click', '.fileupload-fields', function(event) {
        event.stopPropagation();
      });
      $(form).on('click', function() {
        $(uploadForm).find('.fileupload-fields').addClass('hidden').addClass('disabled');
        $(uploadForm).find('.imgContainer.selected').removeClass('selected');
      });
      $(uploadForm).on('input', '.fileupload-field-input', function(event) {
        if (typeof selected[formIndex] != 'undefined') {
          selected[formIndex].find('[data-field-name="' + $(this).data('field-name') + '"]').val($(this).val());
          if ($(this).data('field-name') == "filename") {
            var slug = self.slugifyFileName($(this).val());
            selected[formIndex].find('[data-field-name="slug"]').val(slug);
            $(uploadForm).find('#fileupload-field-slug').html(slug);
          }
        }
      });
    });
    self.start();
  };

  this.setFileOrder = function(form) {
    $(form).find('[data-file-element-order]').each(function(index) {
      $(this).val(index);
    });
  };

  this.loadFields = function(form, source) {
    var fileUploadFields = $(form).find('.fileupload-fields');
    var slugField = $(form).find('#fileupload-field-slug');
    fileUploadFields.find('input').each(function() {
      $(this).val(source.find('[data-field-name="' + $(this).data('field-name') + '"]').val());
    });
    var slug = source.find('[data-field-name="' + slugField.data('field-name') + '"]').val();
    if (slug == "") {
      slug = self.slugifyFileName(source.find('[data-field-name="filename"]').val());
      source.find('[data-field-name="slug"]').val(slug);
    }
    slugField.html(slug);
  };

  this.slugifyFileName = function(text) {
    return text.toLowerCase()
      .replace(/\s+/g, '-')           // Replace spaces with -
      .replace(/[^\w\-\.]+/g, '')     // Remove all non-word chars
      .replace(/\-\-+/g, '-')         // Replace multiple - with single -
      .replace(/^-+/, '')             // Trim - from start of text
      .replace(/-+$/, '');            // Trim - from end of text
  };

  this.start = function() {
    $(document).bind('dragover', function (e)
    {
      $('.dropzone').css('background-color', '#49a4e5');
    });

    $(document).bind('dragleave drop', function (e)
    {
      $('.dropzone').css('background-color', '');
    });
  };

  this.init = function() {
    $(document).on('formOpenAfter', function(event, form) {
      self.initUploadForm(form);
    });
  };

  this.init();
}
var uploadForm = new UploadForm(Routing);

<|endoftext|>


<commit_before>const moment = require('moment')
const { mapValues, get } = require('lodash')
const { buildCompanyUrl } = require('./company.service')

function getInvestmentDetailsDisplay (investmentSummary) {
  if (!investmentSummary.id || !investmentSummary.investment_tier || investmentSummary.investment_tier.length === 0) return null

  const result = {}
  result.account_management_tier = investmentSummary.investment_tier

  if (investmentSummary.investment_account_manager) {
    result.investment_account_manager = `<a href="/adviser/${investmentSummary.investment_account_manager.id}/">${investmentSummary.investment_account_manager.name}</a>`
  }
  if (investmentSummary.client_relationship_manager) {
    result.client_relationship_manager = `<a href="/adviser/${investmentSummary.client_relationship_manager.id}/">${investmentSummary.client_relationship_manager.name}</a>`
  }

  result.ownership = investmentSummary.ownership

  if (investmentSummary.ownership === 'uk') {
    result.ownership = 'UK Owned'
  } else if (investmentSummary.ownership === 'both') {
    result.ownership = 'Both UK and Foreign owned'
  } else {
    result.ownership = `${investmentSummary.ownership_country} owned`
  }

  return result
}

function getOpenInvestmentProjects (investmentProjects) {
  if (!investmentProjects) return null

  return investmentProjects
    .filter(project => project.open)
    .map((project) => {
      return {
        name: `<a href="/investmentprojects/${project.id}/">${project.name}</a>`,
        value: project.value,
        state: project.state,
        land_date: formatLongDate(project.land_date),
      }
    })
}
function getClosedInvestmentProjects (investmentProjects) {
  if (!investmentProjects) return null

  return investmentProjects
    .filter(project => !project.open)
    .map((project) => {
      return {
        name: `<a href="/investmentprojects/${project.id}/">${project.name}</a>`,
        value: project.value,
        state: project.state,
        state_date: formatLongDate(project.state_date),
      }
    })
}

function transformToApi (body) {
  const schema = {
    'client_relationship_manager': Object,
    'referral_source_adviser': Object,
    'referral_source_activity': Object,
    'referral_source_activity_marketing': Object,
    'referral_source_activity_website': Object,
    'investor_company': Object,
    'investment_type': Object,
    'fdi_type': Object,
    'non_fdi_type': Object,
    'sector': Object,
    'client_contacts': Array,
    'business_activities': Array,
  }

  const relationshipMgr = body['is-relationship-manager']
  if (relationshipMgr !== 'No') {
    body.client_relationship_manager = relationshipMgr
  }

  const referralSource = body['is-relationship-manager']
  if (referralSource !== 'No') {
    body.referral_source_adviser = referralSource
  }

  const formatted = mapValues(schema, (type, key) => {
    const value = body[key]

    if (!value) {
      return
    }

    if (type === Array) {
      return [{ id: value }]
    }

    return { id: value }
  })

  formatted['estimated_land_date'] = `${body['land-date_year']}-${body['land-date_month']}-01`

  return Object.assign({}, body, formatted)
}

function transformFromApi (body) {
  const schema = {
    'client_relationship_manager': String,
    'referral_source_adviser': String,
    'referral_source_activity': String,
    'investor_company': String,
    'investment_type': String,
    'sector': String,
    'client_contacts': Array,
    'business_activities': Array,
  }

  const formatted = mapValues(schema, (type, key) => {
    if (type === Array) {
      return get(body, `${key}[0].id`, '')
    }
    return get(body, `${key}.id`)
  })

  const date = new Date(body['estimated_land_date'])
  formatted['land-date_year'] = date.getFullYear()
  formatted['land-date_month'] = date.getMonth() + 1 // month is zero based index

  return Object.assign({}, body, formatted)
}

function formatProjectData (data) {
  return {
    'Client': {
      name: data.investor_company.name,
      url: buildCompanyUrl(data.investor_company),
    },
    'Type of investment': data.investment_type.name,
    'Primary sector': get(data, 'sector.name', null),
    'Sub-sector': null,
    'Business activity': data.business_activity,
    'Project description': data.description,
    'Non-disclosure agreement': data.nda_signed ? 'Signed' : 'Not signed',
    'Shareable with UK partners': null,
    'Anonymous description': null,
    'Estimated land date': data.estimated_land_date ? moment(data.estimated_land_date).format('MMMM YYYY') : null,
  }
}

function formatValueData (data) {
  return {
    'Total investment': data.total_investment,
    'Foreign equity investment': data.foreign_equity_investment,
    'Government assistance': data.government_assistance,
    'New jobs': data.number_new_jobs,
    'Average salary': data.average_salary,
    'Safeguarded jobs': data.number_safeguarded_jobs,
    'R&D budget': data.r_and_d_budget,
    'Non-FDI R&D project': data.non_fdi_r_and_d_budget,
    'New-to-world tech': data.new_tech_to_uk,
    'Export revenue': data.export_revenue,
  }
}

function formatRequirementsData (data) {
  return {
    'Main strategic drivers': data.strategic_drivers,
    'Client requirements': data.client_requirements,
    'Competitor countries': data.competitor_countries,
    'Possible UK locations': data.uk_region_locations,
    'Investment location': null,
    'UK recipient company': data.uk_company,
  }
}

function formatProjectStatusData (data) {
  return {
    id: data.id,
    name: data.name,
    projectCode: data.project_code,
    phaseName: data.phase.name,
  }
}

module.exports = {
  getInvestmentDetailsDisplay,
  getOpenInvestmentProjects,
  getClosedInvestmentProjects,
  formatProjectData,
  formatValueData,
  formatRequirementsData,
  formatProjectStatusData,
  transformToApi,
  transformFromApi,
}
<commit_msg>Remove unused code in investment formatting service<commit_after>const moment = require('moment')
const { mapValues, get } = require('lodash')
const { buildCompanyUrl } = require('./company.service')

function transformToApi (body) {
  const schema = {
    'client_relationship_manager': Object,
    'referral_source_adviser': Object,
    'referral_source_activity': Object,
    'referral_source_activity_marketing': Object,
    'referral_source_activity_website': Object,
    'investor_company': Object,
    'investment_type': Object,
    'fdi_type': Object,
    'non_fdi_type': Object,
    'sector': Object,
    'client_contacts': Array,
    'business_activities': Array,
  }

  const relationshipMgr = body['is-relationship-manager']
  if (relationshipMgr !== 'No') {
    body.client_relationship_manager = relationshipMgr
  }

  const referralSource = body['is-relationship-manager']
  if (referralSource !== 'No') {
    body.referral_source_adviser = referralSource
  }

  const formatted = mapValues(schema, (type, key) => {
    const value = body[key]

    if (!value) {
      return
    }

    if (type === Array) {
      return [{ id: value }]
    }

    return { id: value }
  })

  formatted['estimated_land_date'] = `${body['land-date_year']}-${body['land-date_month']}-01`

  return Object.assign({}, body, formatted)
}

function transformFromApi (body) {
  const schema = {
    'client_relationship_manager': String,
    'referral_source_adviser': String,
    'referral_source_activity': String,
    'investor_company': String,
    'investment_type': String,
    'sector': String,
    'client_contacts': Array,
    'business_activities': Array,
  }

  const formatted = mapValues(schema, (type, key) => {
    if (type === Array) {
      return get(body, `${key}[0].id`, '')
    }
    return get(body, `${key}.id`)
  })

  const date = new Date(body['estimated_land_date'])
  formatted['land-date_year'] = date.getFullYear()
  formatted['land-date_month'] = date.getMonth() + 1 // month is zero based index

  return Object.assign({}, body, formatted)
}

function formatProjectData (data) {
  return {
    'Client': {
      name: data.investor_company.name,
      url: buildCompanyUrl(data.investor_company),
    },
    'Type of investment': data.investment_type.name,
    'Primary sector': get(data, 'sector.name', null),
    'Sub-sector': null,
    'Business activity': data.business_activity,
    'Project description': data.description,
    'Non-disclosure agreement': data.nda_signed ? 'Signed' : 'Not signed',
    'Shareable with UK partners': null,
    'Anonymous description': null,
    'Estimated land date': data.estimated_land_date ? moment(data.estimated_land_date).format('MMMM YYYY') : null,
  }
}

function formatValueData (data) {
  return {
    'Total investment': data.total_investment,
    'Foreign equity investment': data.foreign_equity_investment,
    'Government assistance': data.government_assistance,
    'New jobs': data.number_new_jobs,
    'Average salary': data.average_salary,
    'Safeguarded jobs': data.number_safeguarded_jobs,
    'R&D budget': data.r_and_d_budget,
    'Non-FDI R&D project': data.non_fdi_r_and_d_budget,
    'New-to-world tech': data.new_tech_to_uk,
    'Export revenue': data.export_revenue,
  }
}

function formatRequirementsData (data) {
  return {
    'Main strategic drivers': data.strategic_drivers,
    'Client requirements': data.client_requirements,
    'Competitor countries': data.competitor_countries,
    'Possible UK locations': data.uk_region_locations,
    'Investment location': null,
    'UK recipient company': data.uk_company,
  }
}

function formatProjectStatusData (data) {
  return {
    id: data.id,
    name: data.name,
    projectCode: data.project_code,
    phaseName: data.phase.name,
  }
}

module.exports = {
  formatProjectData,
  formatValueData,
  formatRequirementsData,
  formatProjectStatusData,
  transformToApi,
  transformFromApi,
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';

import SPELLS from 'common/SPELLS';
import ITEMS from 'common/ITEMS';
import SpellLink from 'common/SpellLink';
import ItemLink from 'common/ItemLink';
import ResourceLink from 'common/ResourceLink';
import RESOURCE_TYPES from 'common/RESOURCE_TYPES';
import Checklist from 'Parser/Core/Modules/Features/Checklist2';
import Rule from 'Parser/Core/Modules/Features/Checklist2/Rule';
import Requirement from 'Parser/Core/Modules/Features/Checklist2/Requirement';
import PreparationRule from 'Parser/Core/Modules/Features/Checklist2/PreparationRule';
import GenericCastEfficiencyRequirement from 'Parser/Core/Modules/Features/Checklist2/GenericCastEfficiencyRequirement';

class HolyPaladinChecklist extends React.PureComponent {
  static propTypes = {
    castEfficiency: PropTypes.object.isRequired,
    combatant: PropTypes.shape({
      hasTalent: PropTypes.func.isRequired,
      hasTrinket: PropTypes.func.isRequired,
    }).isRequired,
    thresholds: PropTypes.object.isRequired,
  };

  render() {
    const { combatant, castEfficiency, thresholds } = this.props;

    const AbilityRequirement = props => (
      <GenericCastEfficiencyRequirement
        castEfficiency={castEfficiency.getCastEfficiencyForSpellId(props.spell)}
        {...props}
      />
    );

    return (
      <Checklist>
        <Rule
          name="Use core abilities as often as possible"
          description={(
            <React.Fragment>
              Spells such as <SpellLink id={SPELLS.HOLY_SHOCK_CAST.id} />, <SpellLink id={SPELLS.LIGHT_OF_DAWN_CAST.id} /> and <SpellLink id={SPELLS.JUDGMENT_CAST.id} /> (with <SpellLink id={SPELLS.JUDGMENT_OF_LIGHT_HEAL.id} />) are your most efficient spells available. Try to cast them as much as possible without overhealing. <dfn data-tip="When you're not bringing too many healers.">On Mythic*</dfn> you can often still cast these spells more even if you were overhealing by casting it quicker when it comes off cooldown and improving your target selection.{' '}
              More info.
            </React.Fragment>
          )}
        >
          <AbilityRequirement spell={SPELLS.HOLY_SHOCK_CAST.id} />
          <AbilityRequirement spell={SPELLS.LIGHT_OF_DAWN_CAST.id} />
          {combatant.hasTalent(SPELLS.JUDGMENT_OF_LIGHT_TALENT.id) && <AbilityRequirement spell={SPELLS.JUDGMENT_CAST.id} />}
          {combatant.hasTalent(SPELLS.BESTOW_FAITH_TALENT.id) && <AbilityRequirement spell={SPELLS.BESTOW_FAITH_TALENT.id} />}
          {combatant.hasTalent(SPELLS.LIGHTS_HAMMER_TALENT.id) && <AbilityRequirement spell={SPELLS.LIGHTS_HAMMER_TALENT.id} />}
          {combatant.hasTalent(SPELLS.CRUSADERS_MIGHT_TALENT.id) && <AbilityRequirement spell={SPELLS.CRUSADER_STRIKE.id} />}
          {combatant.hasTalent(SPELLS.HOLY_PRISM_TALENT.id) && <AbilityRequirement spell={SPELLS.HOLY_PRISM_TALENT.id} />}
          <Requirement
            name={(
              <React.Fragment>
                Total filler <SpellLink id={SPELLS.FLASH_OF_LIGHT.id} />s cast while{' '}
                <SpellLink id={SPELLS.HOLY_SHOCK_CAST.id} /> was available
              </React.Fragment>
            )}
            thresholds={thresholds.fillerFlashOfLight}
          />
        </Rule>
        <Rule
          name="Use cooldowns effectively"
          description={(
            <React.Fragment>
              Your cooldowns are an important contributor to your healing throughput. Try to get in as many efficient casts as the fight allows.{' '}
              More info.
            </React.Fragment>
          )}
        >
          {/* Avenging Crusader replaces Avenging Wrath */}
          {!combatant.hasTalent(SPELLS.AVENGING_CRUSADER_TALENT.id) && (
            <AbilityRequirement spell={SPELLS.AVENGING_WRATH.id} />
          )}
          {combatant.hasTalent(SPELLS.AVENGING_CRUSADER_TALENT.id) && (
            <AbilityRequirement spell={SPELLS.AVENGING_CRUSADER_TALENT.id} />
          )}
          {combatant.hasTalent(SPELLS.HOLY_AVENGER_TALENT.id) && (
            <AbilityRequirement spell={SPELLS.HOLY_AVENGER_TALENT.id} />
          )}
          <AbilityRequirement spell={SPELLS.TYRS_DELIVERANCE_CAST.id} />
          {combatant.hasTrinket(ITEMS.VELENS_FUTURE_SIGHT.id) && (
            <AbilityRequirement
              spell={SPELLS.VELENS_FUTURE_SIGHT_BUFF.id}
              name={<ItemLink id={ITEMS.VELENS_FUTURE_SIGHT.id} />}
            />
          )}
          <AbilityRequirement spell={SPELLS.AURA_MASTERY.id} />
          {/* We can't detect race, so disable this when it has never been cast. */}
          {castEfficiency.getCastEfficiencyForSpellId(SPELLS.ARCANE_TORRENT_MANA.id) && (
            <AbilityRequirement spell={SPELLS.ARCANE_TORRENT_MANA.id} />
          )}
        </Rule>
        <Rule
          name="Use your supportive abilities"
          description="While you shouldn't aim to cast defensives and externals on cooldown, be aware of them and try to use them whenever effective. Not using them at all indicates you might not be aware of them enough or not utilizing them optimally."
        >
          {combatant.hasTalent(SPELLS.RULE_OF_LAW_TALENT.id) && <AbilityRequirement spell={SPELLS.RULE_OF_LAW_TALENT.id} />}
          <AbilityRequirement spell={SPELLS.DIVINE_STEED.id} />
          <AbilityRequirement spell={SPELLS.DIVINE_PROTECTION.id} />
          <AbilityRequirement spell={SPELLS.BLESSING_OF_SACRIFICE.id} />
          <AbilityRequirement spell={SPELLS.LAY_ON_HANDS.id} />
        </Rule>
        <Rule
          name={<React.Fragment>Position yourself well to maximize <SpellLink id={SPELLS.MASTERY_LIGHTBRINGER.id} /></React.Fragment>}
          description={(
            <React.Fragment>
              <SpellLink id={SPELLS.MASTERY_LIGHTBRINGER.id} /> has a big impact on the strength of your heals. Try to stay close to the people you are healing to benefit the most from your Mastery. Use <SpellLink id={SPELLS.RULE_OF_LAW_TALENT.id} /> when healing people further away.
            </React.Fragment>
          )}
        >
          <Requirement name="Mastery effectiveness" thresholds={thresholds.masteryEffectiveness} />
        </Rule>
        <Rule
          name="Try to avoid being inactive for a large portion of the fight"
          description={(
            <React.Fragment>
              While it's suboptimal to always be casting as a healer you should still try to always be doing something during the entire fight and high downtime is inexcusable. You can reduce your downtime by reducing the delay between casting spells, anticipating movement, moving during the GCD, and <dfn data-tip="While helping with damage would be optimal, it's much less important as a healer than any of the other suggestions on this checklist. You should ignore this suggestion while you are having difficulties with anything else.">when you're not healing try to contribute some damage*</dfn>.
            </React.Fragment>
          )}
        >
          <Requirement name="Non healing time" thresholds={thresholds.nonHealingTimeSuggestionThresholds} />
          <Requirement name="Downtime" thresholds={thresholds.downtimeSuggestionThresholds} />
        </Rule>
        <Rule
          name="Don't tunnel the tanks"
          description="A common misconception about Holy Paladins is that we should focus tanks when healing. This is actually inefficient. Let your beacons do most of the work, ask your co-healers to keep efficient HoTs on the tanks and only directly heal the tanks when they would otherwise die."
        >
          <Requirement name="Direct beacon healing" thresholds={thresholds.beaconHealing} />
        </Rule>
        <Rule
          name={<React.Fragment>Only use <SpellLink id={SPELLS.LIGHT_OF_THE_MARTYR.id} /> when absolutely necessary</React.Fragment>}
          description={(
            <React.Fragment>
              <SpellLink id={SPELLS.LIGHT_OF_THE_MARTYR.id} /> is an inefficient spell to cast compared to the alternatives. Try to only cast <SpellLink id={SPELLS.LIGHT_OF_THE_MARTYR.id} /> when it will save someone's life or when you have to move and all other instant cast spells are on cooldown.
            </React.Fragment>
          )}
        >
          <Requirement name="Total filler casts per minute" thresholds={thresholds.fillerLightOfTheMartyrsCpm} />
          <Requirement
            name={(
              <React.Fragment>
                Total filler casts while <SpellLink id={SPELLS.HOLY_SHOCK_CAST.id} /> was available
              </React.Fragment>
            )}
            thresholds={thresholds.fillerLightOfTheMartyrsInefficientCpm}
          />
        </Rule>
        <Rule
          name={<React.Fragment>Use all of your <ResourceLink id={RESOURCE_TYPES.MANA.id} /> effectively</React.Fragment>}
          description="If you have a large amount of mana left at the end of the fight that's mana you could have turned into healing. Try to use all your mana during a fight. A good rule of thumb is to try to match your mana level with the boss's health."
        >
          <Requirement name="Mana left" thresholds={thresholds.manaLeft} />
        </Rule>
        <PreparationRule thresholds={thresholds} />
        <Rule
          name="Avoid overhealing"
          description="Pick the right targets when healing and use the right abilities at the right time. While overhealing still transfers to your beacons, it's still inefficient. Overhealing might be unavoidable when there's not a lot of damage taken (such as in normal mode) or when bringing too many healers."
        >
          <Requirement name={<SpellLink id={SPELLS.HOLY_SHOCK_HEAL.id} />} thresholds={thresholds.overhealing.holyShock} />
          <Requirement name={<SpellLink id={SPELLS.LIGHT_OF_DAWN_HEAL.id} />} thresholds={thresholds.overhealing.lightOfDawn} />
          <Requirement name={<SpellLink id={SPELLS.FLASH_OF_LIGHT.id} />} thresholds={thresholds.overhealing.flashOfLight} />
          {combatant.hasTalent(SPELLS.BESTOW_FAITH_TALENT.id) && (
            <Requirement
              name={<SpellLink id={SPELLS.BESTOW_FAITH_TALENT.id} />}
              thresholds={thresholds.overhealing.bestowFaith}
            />
          )}
        </Rule>
      </Checklist>
    );
  }
}

export default HolyPaladinChecklist;
<commit_msg>Don't wrap Holy Shock's spell name<commit_after>import React from 'react';
import PropTypes from 'prop-types';

import SPELLS from 'common/SPELLS';
import ITEMS from 'common/ITEMS';
import SpellLink from 'common/SpellLink';
import ItemLink from 'common/ItemLink';
import ResourceLink from 'common/ResourceLink';
import RESOURCE_TYPES from 'common/RESOURCE_TYPES';
import Checklist from 'Parser/Core/Modules/Features/Checklist2';
import Rule from 'Parser/Core/Modules/Features/Checklist2/Rule';
import Requirement from 'Parser/Core/Modules/Features/Checklist2/Requirement';
import PreparationRule from 'Parser/Core/Modules/Features/Checklist2/PreparationRule';
import GenericCastEfficiencyRequirement from 'Parser/Core/Modules/Features/Checklist2/GenericCastEfficiencyRequirement';

class HolyPaladinChecklist extends React.PureComponent {
  static propTypes = {
    castEfficiency: PropTypes.object.isRequired,
    combatant: PropTypes.shape({
      hasTalent: PropTypes.func.isRequired,
      hasTrinket: PropTypes.func.isRequired,
    }).isRequired,
    thresholds: PropTypes.object.isRequired,
  };

  render() {
    const { combatant, castEfficiency, thresholds } = this.props;

    const AbilityRequirement = props => (
      <GenericCastEfficiencyRequirement
        castEfficiency={castEfficiency.getCastEfficiencyForSpellId(props.spell)}
        {...props}
      />
    );

    return (
      <Checklist>
        <Rule
          name="Use core abilities as often as possible"
          description={(
            <React.Fragment>
              Spells such as <SpellLink id={SPELLS.HOLY_SHOCK_CAST.id} />, <SpellLink id={SPELLS.LIGHT_OF_DAWN_CAST.id} /> and <SpellLink id={SPELLS.JUDGMENT_CAST.id} /> (with <SpellLink id={SPELLS.JUDGMENT_OF_LIGHT_HEAL.id} />) are your most efficient spells available. Try to cast them as much as possible without overhealing. <dfn data-tip="When you're not bringing too many healers.">On Mythic*</dfn> you can often still cast these spells more even if you were overhealing by casting it quicker when it comes off cooldown and improving your target selection.{' '}
              More info.
            </React.Fragment>
          )}
        >
          <AbilityRequirement spell={SPELLS.HOLY_SHOCK_CAST.id} />
          <AbilityRequirement spell={SPELLS.LIGHT_OF_DAWN_CAST.id} />
          {combatant.hasTalent(SPELLS.JUDGMENT_OF_LIGHT_TALENT.id) && <AbilityRequirement spell={SPELLS.JUDGMENT_CAST.id} />}
          {combatant.hasTalent(SPELLS.BESTOW_FAITH_TALENT.id) && <AbilityRequirement spell={SPELLS.BESTOW_FAITH_TALENT.id} />}
          {combatant.hasTalent(SPELLS.LIGHTS_HAMMER_TALENT.id) && <AbilityRequirement spell={SPELLS.LIGHTS_HAMMER_TALENT.id} />}
          {combatant.hasTalent(SPELLS.CRUSADERS_MIGHT_TALENT.id) && <AbilityRequirement spell={SPELLS.CRUSADER_STRIKE.id} />}
          {combatant.hasTalent(SPELLS.HOLY_PRISM_TALENT.id) && <AbilityRequirement spell={SPELLS.HOLY_PRISM_TALENT.id} />}
          <Requirement
            name={(
              <React.Fragment>
                Total filler <SpellLink id={SPELLS.FLASH_OF_LIGHT.id} />s cast while{' '}
                <SpellLink id={SPELLS.HOLY_SHOCK_CAST.id} /> was available
              </React.Fragment>
            )}
            thresholds={thresholds.fillerFlashOfLight}
          />
        </Rule>
        <Rule
          name="Use cooldowns effectively"
          description={(
            <React.Fragment>
              Your cooldowns are an important contributor to your healing throughput. Try to get in as many efficient casts as the fight allows.{' '}
              More info.
            </React.Fragment>
          )}
        >
          {/* Avenging Crusader replaces Avenging Wrath */}
          {!combatant.hasTalent(SPELLS.AVENGING_CRUSADER_TALENT.id) && (
            <AbilityRequirement spell={SPELLS.AVENGING_WRATH.id} />
          )}
          {combatant.hasTalent(SPELLS.AVENGING_CRUSADER_TALENT.id) && (
            <AbilityRequirement spell={SPELLS.AVENGING_CRUSADER_TALENT.id} />
          )}
          {combatant.hasTalent(SPELLS.HOLY_AVENGER_TALENT.id) && (
            <AbilityRequirement spell={SPELLS.HOLY_AVENGER_TALENT.id} />
          )}
          <AbilityRequirement spell={SPELLS.TYRS_DELIVERANCE_CAST.id} />
          {combatant.hasTrinket(ITEMS.VELENS_FUTURE_SIGHT.id) && (
            <AbilityRequirement
              spell={SPELLS.VELENS_FUTURE_SIGHT_BUFF.id}
              name={<ItemLink id={ITEMS.VELENS_FUTURE_SIGHT.id} />}
            />
          )}
          <AbilityRequirement spell={SPELLS.AURA_MASTERY.id} />
          {/* We can't detect race, so disable this when it has never been cast. */}
          {castEfficiency.getCastEfficiencyForSpellId(SPELLS.ARCANE_TORRENT_MANA.id) && (
            <AbilityRequirement spell={SPELLS.ARCANE_TORRENT_MANA.id} />
          )}
        </Rule>
        <Rule
          name="Use your supportive abilities"
          description="While you shouldn't aim to cast defensives and externals on cooldown, be aware of them and try to use them whenever effective. Not using them at all indicates you might not be aware of them enough or not utilizing them optimally."
        >
          {combatant.hasTalent(SPELLS.RULE_OF_LAW_TALENT.id) && <AbilityRequirement spell={SPELLS.RULE_OF_LAW_TALENT.id} />}
          <AbilityRequirement spell={SPELLS.DIVINE_STEED.id} />
          <AbilityRequirement spell={SPELLS.DIVINE_PROTECTION.id} />
          <AbilityRequirement spell={SPELLS.BLESSING_OF_SACRIFICE.id} />
          <AbilityRequirement spell={SPELLS.LAY_ON_HANDS.id} />
        </Rule>
        <Rule
          name={<React.Fragment>Position yourself well to maximize <SpellLink id={SPELLS.MASTERY_LIGHTBRINGER.id} /></React.Fragment>}
          description={(
            <React.Fragment>
              <SpellLink id={SPELLS.MASTERY_LIGHTBRINGER.id} /> has a big impact on the strength of your heals. Try to stay close to the people you are healing to benefit the most from your Mastery. Use <SpellLink id={SPELLS.RULE_OF_LAW_TALENT.id} /> when healing people further away.
            </React.Fragment>
          )}
        >
          <Requirement name="Mastery effectiveness" thresholds={thresholds.masteryEffectiveness} />
        </Rule>
        <Rule
          name="Try to avoid being inactive for a large portion of the fight"
          description={(
            <React.Fragment>
              While it's suboptimal to always be casting as a healer you should still try to always be doing something during the entire fight and high downtime is inexcusable. You can reduce your downtime by reducing the delay between casting spells, anticipating movement, moving during the GCD, and <dfn data-tip="While helping with damage would be optimal, it's much less important as a healer than any of the other suggestions on this checklist. You should ignore this suggestion while you are having difficulties with anything else.">when you're not healing try to contribute some damage*</dfn>.
            </React.Fragment>
          )}
        >
          <Requirement name="Non healing time" thresholds={thresholds.nonHealingTimeSuggestionThresholds} />
          <Requirement name="Downtime" thresholds={thresholds.downtimeSuggestionThresholds} />
        </Rule>
        <Rule
          name="Don't tunnel the tanks"
          description="A common misconception about Holy Paladins is that we should focus tanks when healing. This is actually inefficient. Let your beacons do most of the work, ask your co-healers to keep efficient HoTs on the tanks and only directly heal the tanks when they would otherwise die."
        >
          <Requirement name="Direct beacon healing" thresholds={thresholds.beaconHealing} />
        </Rule>
        <Rule
          name={<React.Fragment>Only use <SpellLink id={SPELLS.LIGHT_OF_THE_MARTYR.id} /> when absolutely necessary</React.Fragment>}
          description={(
            <React.Fragment>
              <SpellLink id={SPELLS.LIGHT_OF_THE_MARTYR.id} /> is an inefficient spell to cast compared to the alternatives. Try to only cast <SpellLink id={SPELLS.LIGHT_OF_THE_MARTYR.id} /> when it will save someone's life or when you have to move and all other instant cast spells are on cooldown.
            </React.Fragment>
          )}
        >
          <Requirement name="Total filler casts per minute" thresholds={thresholds.fillerLightOfTheMartyrsCpm} />
          <Requirement
            name={(
              <React.Fragment>
                Total filler casts while <SpellLink id={SPELLS.HOLY_SHOCK_CAST.id} /> was available
              </React.Fragment>
            )}
            thresholds={thresholds.fillerLightOfTheMartyrsInefficientCpm}
          />
        </Rule>
        <Rule
          name={<React.Fragment>Use all of your <ResourceLink id={RESOURCE_TYPES.MANA.id} /> effectively</React.Fragment>}
          description="If you have a large amount of mana left at the end of the fight that's mana you could have turned into healing. Try to use all your mana during a fight. A good rule of thumb is to try to match your mana level with the boss's health."
        >
          <Requirement name="Mana left" thresholds={thresholds.manaLeft} />
        </Rule>
        <PreparationRule thresholds={thresholds} />
        <Rule
          name="Avoid overhealing"
          description="Pick the right targets when healing and use the right abilities at the right time. While overhealing still transfers to your beacons, it's still inefficient. Overhealing might be unavoidable when there's not a lot of damage taken (such as in normal mode) or when bringing too many healers."
        >
          <Requirement name={<SpellLink id={SPELLS.HOLY_SHOCK_HEAL.id} />} thresholds={thresholds.overhealing.holyShock} />
          <Requirement name={<SpellLink id={SPELLS.LIGHT_OF_DAWN_HEAL.id} />} thresholds={thresholds.overhealing.lightOfDawn} />
          <Requirement name={<SpellLink id={SPELLS.FLASH_OF_LIGHT.id} />} thresholds={thresholds.overhealing.flashOfLight} />
          {combatant.hasTalent(SPELLS.BESTOW_FAITH_TALENT.id) && (
            <Requirement
              name={<SpellLink id={SPELLS.BESTOW_FAITH_TALENT.id} />}
              thresholds={thresholds.overhealing.bestowFaith}
            />
          )}
        </Rule>
      </Checklist>
    );
  }
}

export default HolyPaladinChecklist;
<|endoftext|>


<commit_before>(function(angular) {
	'use strict';

	angular.module('xpsui:controllers')
	.controller('xpsui:RegistryCustomTemplateCtrl', ['$scope', '$routeParams', '$http',
		'xpsui:SchemaUtil', 'xpsui:NotificationFactory', '$location', 'xpsui:NavigationService',
		function($scope, $routeParams, $http, schemaUtilFactory, notificationFactory, $location, navigationService) {
			$scope.model = {};
			$scope.currentSchemaUri = schemaUtilFactory.decodeUri($routeParams.schema);

			if ($routeParams.template == 'createMember.html') {
				$http({ method : 'GET',
					url: '/udao/getBySchema/uri~3A~2F~2Fregistries~2Frequisitions~23views~2FpeopleRegistrationApplicant~2Fview'
						+ '/' + $routeParams.id})
				.success(function(data, status, headers, config) {
					var copyFields = [
					                  { 'path': 'model.obj', 'value': data }
					];
					var uri = '/registry/new/uri~3A~2F~2Fregistries~2Fpeople~23views~2Ffullperson';
					navigationService.navigateToPath(uri, copyFields);
					$location.path(uri);
				}).error(function(err) {
					notificationFactory.error(err);
				});
				return;
			}

			if ($routeParams.template == 'createTransfer.html') {
				$http({ method : 'GET',
					url: '/udao/getBySchema/uri~3A~2F~2Fregistries~2Frequisitions~23views~2FtransferApplicant~2Fview'
						+ '/' + $routeParams.id})
				.success(function(data, status, headers, config) {
					if (data.id) {
						delete data.id;
					}
					var copyFields = [
					                  { 'path': 'model.obj', 'value': data }
					];
					var uri = '/registry/new/uri~3A~2F~2Fregistries~2Ftransfers~23views~2Ftransfers';
					navigationService.navigateToPath(uri, copyFields);
					$location.path(uri);
				}).error(function(err) {
					notificationFactory.error(err);
				});
				return;
			}

			if ($routeParams.template == 'personalAccountActivation.html') {
				$http({ method : 'GET',
					url: '/udao/getBySchema/uri~3A~2F~2Fregistries~2Fpeople~23views~2Ffullperson~2Fview'
						+ '/' + $routeParams.id})
				.success(function(data, status, headers, config) {
					$http({ method : 'GET', url: '/security/profiles' })
					.success(function(dataProfiles, statusProfiles, headersProfiles, configProfiles) {
						var defaultProfile = {};
						for (var pos = 0; pos < dataProfiles.length; pos++) {
							if (dataProfiles[pos].baseData.name == 'default') {
								defaultProfile = dataProfiles[pos];
							}
						}
						var email = '';
						if (data && data.contactInfo) {
							email = data.contactInfo.email;
						}
						var accountName = '';
						if (data && data.baseData) {
							accountName = data.baseData.name;
						}
						var copyFields = [
							{ 'path': 'model.obj.account.email', 'value': email },
							{ 'path': 'model.obj.account.name', 'value': accountName },
							{ 'path': 'model.obj.account.profiles', 'value': [defaultProfile] }
						];
						var uri = '/registry/new/uri~3A~2F~2Fregistries~2FpersonalAccount~23views~2FpersonalAccount';
						navigationService.navigateToPath(uri, copyFields);
						$location.path(uri);
					}).error(function(err) {
						notificationFactory.error(err);
					});
				}).error(function(err) {
					notificationFactory.error(err);
				});
				return;
			}

		}
	]);
}(window.angular));
<commit_msg>Ranking widget for city downhill portal.<commit_after>(function(angular) {
	'use strict';

	angular.module('xpsui:controllers')
	.controller('xpsui:RegistryCustomTemplateCtrl', ['$scope', '$routeParams', '$http',
		'xpsui:SchemaUtil', 'xpsui:NotificationFactory', '$location', 'xpsui:NavigationService',
		function($scope, $routeParams, $http, schemaUtilFactory, notificationFactory, $location, navigationService) {
			$scope.model = {};
			$scope.currentSchemaUri = schemaUtilFactory.decodeUri($routeParams.schema);

			if ($routeParams.template == 'createMember.html') {
				$http({ method : 'GET',
					url: '/udao/getBySchema/uri~3A~2F~2Fregistries~2Frequisitions~23views~2FpeopleRegistrationApplicant~2Fview'
						+ '/' + $routeParams.id})
				.success(function(data, status, headers, config) {
					var copyFields = [
					                  { 'path': 'model.obj', 'value': data }
					];
					var uri = '/registry/new/uri~3A~2F~2Fregistries~2Fpeople~23views~2Ffullperson';
					navigationService.navigateToPath(uri, copyFields);
					$location.path(uri);
				}).error(function(err) {
					notificationFactory.error(err);
				});
				return;
			}

			if ($routeParams.template == 'createTransfer.html') {
				$http({ method : 'GET',
					url: '/udao/getBySchema/uri~3A~2F~2Fregistries~2Frequisitions~23views~2FtransferApplicant~2Fview'
						+ '/' + $routeParams.id})
				.success(function(data, status, headers, config) {
					if (data.id) {
						delete data.id;
					}
					var copyFields = [
					                  { 'path': 'model.obj', 'value': data }
					];
					var uri = '/registry/new/uri~3A~2F~2Fregistries~2Ftransfers~23views~2Ftransfers';
					navigationService.navigateToPath(uri, copyFields);
					$location.path(uri);
				}).error(function(err) {
					notificationFactory.error(err);
				});
				return;
			}

			if ($routeParams.template == 'personalAccountActivation.html') {
				$http({ method : 'GET',
					url: '/udao/getBySchema/uri~3A~2F~2Fregistries~2Fpeople~23views~2Ffullperson~2Fview'
						+ '/' + $routeParams.id})
				.success(function(data, status, headers, config) {
					$http({ method : 'GET', url: '/security/profiles' })
					.success(function(dataProfiles, statusProfiles, headersProfiles, configProfiles) {
						var defaultProfile = {};
						for (var pos = 0; pos < dataProfiles.length; pos++) {
							if (dataProfiles[pos].baseData.name == 'default') {
								defaultProfile = {};
								defaultProfile.oid = dataProfiles[pos].id;
								defaultProfile.refData = { name: dataProfiles[pos].baseData.name };
							}
						}
						var email = '';
						if (data && data.contactInfo) {
							email = data.contactInfo.email;
						}
						var accountName = '';
						if (data && data.baseData) {
							accountName = data.baseData.name;
						}
						var copyFields = [
							{ 'path': 'model.obj.account.email', 'value': email },
							{ 'path': 'model.obj.account.name', 'value': accountName },
							{ 'path': 'model.obj.account.profiles', 'value': [defaultProfile] }
						];
						var uri = '/registry/new/uri~3A~2F~2Fregistries~2FpersonalAccount~23views~2FpersonalAccount';
						navigationService.navigateToPath(uri, copyFields);
						$location.path(uri);
					}).error(function(err) {
						notificationFactory.error(err);
					});
				}).error(function(err) {
					notificationFactory.error(err);
				});
				return;
			}

		}
	]);
}(window.angular));
<|endoftext|>


<commit_before>(function($) {
"use strict";

var nbsp = ' ';

zeit.cms.declare_namespace('zeit.cms.tagging');

zeit.cms.tagging.Widget = gocept.Class.extend({

    construct: function(id) {
        var self = this;
        self.id = id;
        self.element = document.getElementById(id + '.wrapper');
        self.list = document.getElementById(id + '.list');
        self.data = document.getElementById(id);
        self.autocomplete = document.getElementById(id + '.add');
        self.populate_keywords($.parseJSON($(self.data).val()));
        MochiKit.Signal.connect(
            id + '.wrapper', 'onclick', self, self.handle_click);
        self._initialize_autocomplete();
        self._initialize_sortable();
        self.get_tags_with_topicpages();
    },

    _initialize_autocomplete: function() {
        var self = this;
        $(self.autocomplete).autocomplete({
            source: self.autocomplete.getAttribute('cms:autocomplete-source'),
            minLength: 3,
            focus: function(event, ui) {
                $(self.autocomplete).val(ui.item.label);
                return false;
            },
            select: function(event, ui) {
                self.add(ui.item.value, ui.item.label, /*pinned=*/true,
                         /*position=*/'start');
                $(self.autocomplete).val('');
                return false;
            },
            appendTo: self.element
        });
    },

    _initialize_sortable: function() {
        var self = this;
        $(self.list).sortable({
            items: '> li',
            axis: 'y',
            scroll: false,
            update: function(event, ui) {
                self._sync_json_widget_value();
                $(self.data).trigger('change');
            }
        });
    },

    handle_click: function(event) {
        var self = this;
        var method = event.target().getAttribute('cms:call');
        if (isNull(method)) {
            return;
        }

        method = self[method];
        method.call(self, event);
        event.stop();
    },

    to_json: function() {
        var self = this;
        var result = [];
        $('> li', self.list).each(function(i, el) {
            el = $(el);
            result.push({code: el.attr('cms:uniqueId'),
                         label: el.text(),
                         pinned: Boolean(el.find('.pinned').length)});
        });
        return result;
    },

    delete: function(event) {
        var self = this;
        $(event.target()).closest('li').remove();
        self._sync_json_widget_value();
        $(self.data).trigger('change');
    },

    add: function(code, label, pinned, position) {
        var self = this;
        self._add(code, label, pinned, position);
        self._sync_json_widget_value();
    },

    _add: function(code, label, pinned, position) {
        var self = this;
        if (isUndefined(position)) {
            position = 'end';
        }
        var pinned = pinned ? 'pinned' : 'toggle-pin';
        var item = LI(
            {'cms:uniqueId': code},
            SPAN({'class': 'icon delete', 'cms:call': 'delete'}),
            SPAN({'class': 'icon ' + pinned, 'cms:call': 'toggle_pinned'}),
            A({'href': ''}, label)
        );
        if (position === 'end') {
            $(self.list).append(item);
        } else {
            $(self.list).prepend(item);
        }
    },

    toggle_pinned: function(event) {
        var self = this;
        var icon = $(event.target());
        var currently_pinned = icon.hasClass('pinned');
        if (currently_pinned) {
            icon.removeClass('pinned');
            icon.addClass('toggle-pin');
        } else {
            icon.removeClass('toggle-pin');
            icon.addClass('pinned');
        }
        self._sync_json_widget_value();
        $(self.data).trigger('change');
    },

    populate_keywords: function(tags) {
        var self = this;
        $.each(tags, function(i, tag) {
            self._add(tag.code, tag.label, tag.pinned);
        });
        self._sync_json_widget_value();
    },

    update_tags: function() {
        var self = this;
        var d = MochiKit.Async.doXHR('@@update_tags', {method: 'POST'});
        MochiKit.DOM.addElementClass(self.list, 'busy');
        d.addCallback(function(result) {
            var json = MochiKit.Async.evalJSONRequest(result);
            self.list.innerHTML = '';
            self.populate_keywords(json.tags);
            self._initialize_sortable();
            self.get_tags_with_topicpages();
            $(self.data).trigger('change');
            return result;
        });
        d.addBoth(function(result_or_error) {
            MochiKit.DOM.removeElementClass(self.list, 'busy');
        });
    },

    get_tags_with_topicpages: function() {
        var self = this;
        var d = MochiKit.Async.doXHR(
            '@@tags_with_topicpages',
            {method: 'POST'});
        d.addCallback(function(result) {
            var json_result = MochiKit.Async.evalJSONRequest(result);
            self._highlight_tags_with_topic_pages(json_result);
        });
    },

    _highlight_tags_with_topic_pages: function(tags_with_topic_page) {
        var self = this;
        $('li', self.list).each(function(index) {
                if (tags_with_topic_page[this.getAttribute('cms:uniqueId')]){
                    var el = $('a', this);
                    el.css( 'font-weight', 'bold');
                    el.attr('href',
                        tags_with_topic_page[this.getAttribute('cms:uniqueId')]);
                }
            });
    },

    _sync_json_widget_value: function() {
        var self = this;
        $(self.data).val(JSON.stringify(self.to_json()));
        $(self.list).css('width', $(self.list).width() + 'px');
    }

});

})(jQuery);
<commit_msg>MAINT: Inline post-processing of xhr results<commit_after>(function($) {
"use strict";

var nbsp = ' ';

zeit.cms.declare_namespace('zeit.cms.tagging');

zeit.cms.tagging.Widget = gocept.Class.extend({

    construct: function(id) {
        var self = this;
        self.id = id;
        self.element = document.getElementById(id + '.wrapper');
        self.list = document.getElementById(id + '.list');
        self.data = document.getElementById(id);
        self.autocomplete = document.getElementById(id + '.add');
        self.populate_keywords($.parseJSON($(self.data).val()));
        MochiKit.Signal.connect(
            id + '.wrapper', 'onclick', self, self.handle_click);
        self._initialize_autocomplete();
        self._initialize_sortable();
        self._highlight_tags_with_topicpages();
    },

    _initialize_autocomplete: function() {
        var self = this;
        $(self.autocomplete).autocomplete({
            source: self.autocomplete.getAttribute('cms:autocomplete-source'),
            minLength: 3,
            focus: function(event, ui) {
                $(self.autocomplete).val(ui.item.label);
                return false;
            },
            select: function(event, ui) {
                self.add(ui.item.value, ui.item.label, /*pinned=*/true,
                         /*position=*/'start');
                $(self.autocomplete).val('');
                return false;
            },
            appendTo: self.element
        });
    },

    _initialize_sortable: function() {
        var self = this;
        $(self.list).sortable({
            items: '> li',
            axis: 'y',
            scroll: false,
            update: function(event, ui) {
                self._sync_json_widget_value();
                $(self.data).trigger('change');
            }
        });
    },

    handle_click: function(event) {
        var self = this;
        var method = event.target().getAttribute('cms:call');
        if (isNull(method)) {
            return;
        }

        method = self[method];
        method.call(self, event);
        event.stop();
    },

    to_json: function() {
        var self = this;
        var result = [];
        $('> li', self.list).each(function(i, el) {
            el = $(el);
            result.push({code: el.attr('cms:uniqueId'),
                         label: el.text(),
                         pinned: Boolean(el.find('.pinned').length)});
        });
        return result;
    },

    delete: function(event) {
        var self = this;
        $(event.target()).closest('li').remove();
        self._sync_json_widget_value();
        $(self.data).trigger('change');
    },

    add: function(code, label, pinned, position) {
        var self = this;
        self._add(code, label, pinned, position);
        self._sync_json_widget_value();
    },

    _add: function(code, label, pinned, position) {
        var self = this;
        if (isUndefined(position)) {
            position = 'end';
        }
        var pinned = pinned ? 'pinned' : 'toggle-pin';
        var item = LI(
            {'cms:uniqueId': code},
            SPAN({'class': 'icon delete', 'cms:call': 'delete'}),
            SPAN({'class': 'icon ' + pinned, 'cms:call': 'toggle_pinned'}),
            A({'href': ''}, label)
        );
        if (position === 'end') {
            $(self.list).append(item);
        } else {
            $(self.list).prepend(item);
        }
    },

    toggle_pinned: function(event) {
        var self = this;
        var icon = $(event.target());
        var currently_pinned = icon.hasClass('pinned');
        if (currently_pinned) {
            icon.removeClass('pinned');
            icon.addClass('toggle-pin');
        } else {
            icon.removeClass('toggle-pin');
            icon.addClass('pinned');
        }
        self._sync_json_widget_value();
        $(self.data).trigger('change');
    },

    populate_keywords: function(tags) {
        var self = this;
        $.each(tags, function(i, tag) {
            self._add(tag.code, tag.label, tag.pinned);
        });
        self._sync_json_widget_value();
    },

    update_tags: function() {
        var self = this;
        var d = MochiKit.Async.doXHR('@@update_tags', {method: 'POST'});
        MochiKit.DOM.addElementClass(self.list, 'busy');
        d.addCallback(function(result) {
            var json = MochiKit.Async.evalJSONRequest(result);
            self.list.innerHTML = '';
            self.populate_keywords(json.tags);
            self._initialize_sortable();
            self._highlight_tags_with_topicpages();
            $(self.data).trigger('change');
            return result;
        });
        d.addBoth(function(result_or_error) {
            MochiKit.DOM.removeElementClass(self.list, 'busy');
        });
    },

    _highlight_tags_with_topicpages: function() {
        var self = this;
        var d = MochiKit.Async.doXHR(
            '@@tags_with_topicpages',
            {method: 'POST'});
        d.addCallback(function(result) {
            var json_result = MochiKit.Async.evalJSONRequest(result);
            $('li', self.list).each(function(index) {
                if (json_result[this.getAttribute('cms:uniqueId')]){
                    var el = $('a', this);
                    el.css( 'font-weight', 'bold');
                    el.attr('href',
                            json_result[this.getAttribute('cms:uniqueId')]);
                }
            });
        });
    },

    _sync_json_widget_value: function() {
        var self = this;
        $(self.data).val(JSON.stringify(self.to_json()));
        $(self.list).css('width', $(self.list).width() + 'px');
    }

});

})(jQuery);
<|endoftext|>


<commit_before>/**
 * Titanium SDK Library for Node.js
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * Please see the LICENSE file for information about licensing.
 */

var ti = require('./titanium'),
	appc = require('node-appc'),
	i18n = appc.i18n(__dirname),
	__ = i18n.__,
	__n = i18n.__n,
	afs = appc.fs,
	xml = appc.xml,
	fs = require('fs'),
	path = require('path'),
	DOMParser = require('xmldom').DOMParser;

exports.load = function (projectDir, logger) {
	var i18nDir = path.join(projectDir, 'i18n'),
		data = {};

	if (afs.exists(i18nDir)) {
		logger.info(__('Compiling localization files'));
		fs.readdirSync(i18nDir).forEach(function (lang) {
			var langDir = path.join(i18nDir, lang);

			if (fs.lstatSync(langDir).isDirectory()) {
				var s = data[lang] = {};

				fs.readdirSync(langDir).forEach(function (file) {
					if (/.+\.xml$/.test(file)) {
						logger.debug(__('Processing i18n file: %s', (lang + '/' + file).cyan));

						var dest = file == 'app.xml' ? 'app' : 'strings',
							obj = s[dest] = s[dest] || {},
							dom = new DOMParser().parseFromString(fs.readFileSync(path.join(langDir, file)).toString(), 'text/xml');

						xml.forEachElement(dom.documentElement, function (elem) {
							if (elem.nodeType == 1 && elem.tagName == 'string') {
								var name = xml.getAttr(elem, 'name');
								name && (obj[name] = xml.getValue(elem));
							}
						});
					}
				});
			}
		});
	}

	return data;
};

exports.splashScreens = function (projectDir, logger) {

	var i18nDir = path.join(projectDir, 'i18n'),
		data = [];

	if (afs.exists(i18nDir)) {
		logger.info(__('Checking for Splash Screen localization'));
		fs.readdirSync(i18nDir).forEach(function (lang) {
			var langDir = path.join(i18nDir, lang);

			if (fs.lstatSync(langDir).isDirectory()) {
				fs.readdirSync(langDir).forEach(function (file) {
					if(/^(Default(2x|-568h@2x|-Landscape|-Landscape@2x|-Portrait|-Portriat@2x)?)\.png$/.test(file)) {
						data.push(path.join(langDir, file));
					}
				});
			}
		});
	}

	return data;
};<commit_msg>[TIMOB-8358]Forgot the '@' in front of 2x.<commit_after>/**
 * Titanium SDK Library for Node.js
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * Please see the LICENSE file for information about licensing.
 */

var ti = require('./titanium'),
	appc = require('node-appc'),
	i18n = appc.i18n(__dirname),
	__ = i18n.__,
	__n = i18n.__n,
	afs = appc.fs,
	xml = appc.xml,
	fs = require('fs'),
	path = require('path'),
	DOMParser = require('xmldom').DOMParser;

exports.load = function (projectDir, logger) {
	var i18nDir = path.join(projectDir, 'i18n'),
		data = {};

	if (afs.exists(i18nDir)) {
		logger.info(__('Compiling localization files'));
		fs.readdirSync(i18nDir).forEach(function (lang) {
			var langDir = path.join(i18nDir, lang);

			if (fs.lstatSync(langDir).isDirectory()) {
				var s = data[lang] = {};

				fs.readdirSync(langDir).forEach(function (file) {
					if (/.+\.xml$/.test(file)) {
						logger.debug(__('Processing i18n file: %s', (lang + '/' + file).cyan));

						var dest = file == 'app.xml' ? 'app' : 'strings',
							obj = s[dest] = s[dest] || {},
							dom = new DOMParser().parseFromString(fs.readFileSync(path.join(langDir, file)).toString(), 'text/xml');

						xml.forEachElement(dom.documentElement, function (elem) {
							if (elem.nodeType == 1 && elem.tagName == 'string') {
								var name = xml.getAttr(elem, 'name');
								name && (obj[name] = xml.getValue(elem));
							}
						});
					}
				});
			}
		});
	}

	return data;
};

exports.splashScreens = function (projectDir, logger) {

	var i18nDir = path.join(projectDir, 'i18n'),
		data = [];

	if (afs.exists(i18nDir)) {
		logger.info(__('Checking for Splash Screen localization'));
		fs.readdirSync(i18nDir).forEach(function (lang) {
			var langDir = path.join(i18nDir, lang);

			if (fs.lstatSync(langDir).isDirectory()) {
				fs.readdirSync(langDir).forEach(function (file) {
					if(/^(Default(@2x|-568h@2x|-Landscape|-Landscape@2x|-Portrait|-Portriat@2x)?)\.png$/.test(file)) {
						data.push(path.join(langDir, file));
					}
				});
			}
		});
	}

	return data;
};<|endoftext|>


<commit_before>/**
 * Module dependencies
 */
var util = require( 'util' ),
	actionUtil = require( './_util/actionUtil' ),
	pluralize = require( 'pluralize' );

/**
 * Populate (or "expand") an association
 *
 * get /model/:parentid/relation
 * get /model/:parentid/relation/:id
 *
 * @param {Integer|String} parentid  - the unique id of the parent instance
 * @param {Integer|String} id  - the unique id of the particular child instance you'd like to look up within this relation
 * @param {Object} where       - the find criteria (passed directly to the ORM)
 * @param {Integer} limit      - the maximum number of records to send back (useful for pagination)
 * @param {Integer} skip       - the number of records to skip (useful for pagination)
 * @param {String} sort        - the order of returned records, e.g. `name ASC` or `age DESC`
 *
 * @option {String} model  - the identity of the model
 * @option {String} alias  - the name of the association attribute (aka "alias")
 */

module.exports = function expand( req, res ) {

	var Model = actionUtil.parseModel( req );
	var relation = req.options.alias;
	if ( !relation || !Model ) return res.serverError();

	// Allow customizable blacklist for params.
	req.options.criteria = req.options.criteria || {};
	req.options.criteria.blacklist = req.options.criteria.blacklist || [ 'limit', 'skip', 'sort', 'id', 'parentid' ];

	var parentPk = req.param( 'parentid' );

	// Determine whether to populate using a criteria, or the
	// specified primary key of the child record, or with no
	// filter at all.
	var childPk = actionUtil.parsePk( req );
	var where = childPk ? [ childPk ] : actionUtil.parseCriteria( req );
	var skip = actionUtil.parseSkip( req );
	var limit = actionUtil.parseLimit( req );
	var sort = actionUtil.parseSort( req );

	var populateOptions = {
		where: where
	};

	if ( skip ) populateOptions.skip = skip;
	if ( limit ) populateOptions.limit = limit;
	if ( sort ) populateOptions.sort = sort;

	Model
		.findOne( parentPk )
		.populate( relation, populateOptions )
		.exec( function found( err, matchingRecord ) {
			if ( err ) return res.serverError( err );
			if ( !matchingRecord ) return res.notFound( 'No record found with the specified id.' );
			if ( !matchingRecord[ relation ] ) return res.notFound( util.format( 'Specified record (%s) is missing relation `%s`', parentPk, relation ) );

			// Subcribe to instance, if relevant
			// TODO: only subscribe to populated attribute- not the entire model
			if ( sails.hooks.pubsub && req.isSocket ) {
				Model.subscribe( req, matchingRecord );
				actionUtil.subscribeDeep( req, matchingRecord );
			}

			// find the model identity and the Collection for this relation
			var association = _.find( req.options.associations, {
				alias: relation
			} );
			var relationIdentity, documentIdentifier;

			if ( association.type === "model" ) {
				documentIdentifier = relationIdentity = association.model;
			} else {
				relationIdentity = association.collection;
				documentIdentifier = pluralize( association.collection );
			}

			var RelatedModel = req._sails.models[ relationIdentity ];
			if ( !RelatedModel ) throw new Error( util.format( 'Invalid route option, "model".\nI don\'t know about any models named: `%s`', relationIdentity ) );

			var related = Ember.linkAssociations( RelatedModel, matchingRecord[ relation ] );

			var json = {};
			json[ documentIdentifier ] = related;
			res.ok( json );
		} );
};
<commit_msg>Bring over some fixes from Sails 0.11 blueprints<commit_after>/**
 * Module dependencies
 */
var util = require( 'util' ),
	actionUtil = require( './_util/actionUtil' ),
	pluralize = require( 'pluralize' );

/**
 * Populate (or "expand") an association
 *
 * get /model/:parentid/relation
 * get /model/:parentid/relation/:id
 *
 * @param {Integer|String} parentid  - the unique id of the parent instance
 * @param {Integer|String} id  - the unique id of the particular child instance you'd like to look up within this relation
 * @param {Object} where       - the find criteria (passed directly to the ORM)
 * @param {Integer} limit      - the maximum number of records to send back (useful for pagination)
 * @param {Integer} skip       - the number of records to skip (useful for pagination)
 * @param {String} sort        - the order of returned records, e.g. `name ASC` or `age DESC`
 *
 * @option {String} model  - the identity of the model
 * @option {String} alias  - the name of the association attribute (aka "alias")
 */

module.exports = function expand( req, res ) {

	var Model = actionUtil.parseModel( req );
	var relation = req.options.alias;
	if ( !relation || !Model ) return res.serverError();

	// Allow customizable blacklist for params.
	req.options.criteria = req.options.criteria || {};
	req.options.criteria.blacklist = req.options.criteria.blacklist || [ 'limit', 'skip', 'sort', 'id', 'parentid' ];

	var parentPk = req.param( 'parentid' );

	// Determine whether to populate using a criteria, or the
	// specified primary key of the child record, or with no
	// filter at all.
	var childPk = actionUtil.parsePk( req );

	// Coerce the child PK to an integer if necessary
	if ( childPk ) {
		if ( Model.attributes[ Model.primaryKey ].type == 'integer' ) {
			childPk = +childPk || 0;
		}
	}

	var where = childPk ? {id: [childPk]} : actionUtil.parseCriteria(req);

	var skip = actionUtil.parseSkip( req );
	var limit = actionUtil.parseLimit( req );
	var sort = actionUtil.parseSort( req );

	var populateOptions = {
		where: where
	};

	if ( skip ) populateOptions.skip = skip;
	if ( limit ) populateOptions.limit = limit;
	if ( sort ) populateOptions.sort = sort;

	Model
		.findOne( parentPk )
		.populate( relation, populateOptions )
		.exec( function found( err, matchingRecord ) {
			if ( err ) return res.serverError( err );
			if ( !matchingRecord ) return res.notFound( 'No record found with the specified id.' );
			if ( !matchingRecord[ relation ] ) return res.notFound( util.format( 'Specified record (%s) is missing relation `%s`', parentPk, relation ) );

			// Subcribe to instance, if relevant
			// TODO: only subscribe to populated attribute- not the entire model
			if ( sails.hooks.pubsub && req.isSocket ) {
				Model.subscribe( req, matchingRecord );
				actionUtil.subscribeDeep( req, matchingRecord );
			}

			// find the model identity and the Collection for this relation
			var association = _.find( req.options.associations, {
				alias: relation
			} );
			var relationIdentity, documentIdentifier;

			if ( association.type === "model" ) {
				documentIdentifier = relationIdentity = association.model;
			} else {
				relationIdentity = association.collection;
				documentIdentifier = pluralize( association.collection );
			}

			var RelatedModel = req._sails.models[ relationIdentity ];
			if ( !RelatedModel ) throw new Error( util.format( 'Invalid route option, "model".\nI don\'t know about any models named: `%s`', relationIdentity ) );

			var related = Ember.linkAssociations( RelatedModel, matchingRecord[ relation ] );

			var json = {};
			json[ documentIdentifier ] = related;
			res.ok( json );
		} );
};<|endoftext|>