コード例 #1
0
ファイル: location-new.view.js プロジェクト: adimka/ddf
const Marionette = require('marionette')
const _ = require('underscore')
const CustomElements = require('js/CustomElements')
const LocationNewModel = require('./location-new')

module.exports = Marionette.LayoutView.extend({
  template: () => `<div class="location-input"></div>`,
  tagName: CustomElements.register('location-new'),
  regions: {
    location: '.location-input',
  },
  initialize(options) {
    this.propertyModel = this.model
    this.model = new LocationNewModel()
    _.bindAll.apply(_, [this].concat(_.functions(this))) // underscore bindAll does not take array arg
  },
  onRender() {
    this.location.show(
      new LocationInput({
        model: this.model,
      })
    )
  },
  getCurrentValue() {
    return this.model.getValue()
  },
  isValid() {
    return this.model.isValid()
  },
})
コード例 #2
0
ファイル: hide-attribute.view.js プロジェクト: emmberk/ddf
module.exports = Marionette.LayoutView.extend({
    tagName: CustomElements.register('hide-attribute'),
    template: template,
    regions: {
        attributeSelector: '> .attribute-selector'
    },
    onBeforeShow: function () {
        var attributes = calculateAvailableAttributesFromSelection(this.options.selectionInterface);
        var detailsAttributes = calculateDetailsAttributes();
        var totalAttributes = filterAndSort(_.union(attributes, detailsAttributes));
        var detailsHidden = user.get('user').get('preferences').get('inspector-detailsHidden');
        this.attributeSelector.show(new PropertyView({
            model: new Property({
                enum: totalAttributes.map((attr) => {
                    return {
                        label: metacardDefinitions.getLabel(attr),
                        value: attr
                    };
                }),
                id: 'Attributes To Hide',
                value: [
                    detailsHidden
                ],
                showValidationIssues: false,
                enumFiltering: true,
                enumMulti: true
            })
        }));
        this.attributeSelector.currentView.turnOnEditing();
        this.attributeSelector.currentView.turnOnLimitedWidth();
        this.listenTo(this.attributeSelector.currentView.model, 'change:value', this.handleSave);
    },
    handleSave: function () {
        var prefs = user.get('user').get('preferences');
        prefs.set('inspector-detailsHidden', this.attributeSelector.currentView.model.get('value')[0]);
        prefs.savePreferences();
    }
});
コード例 #3
0
const CustomElements = require('../../js/CustomElements.js')
import * as React from 'react'
import ExtensionPoints from '../../extension-points'

module.exports = Marionette.LayoutView.extend({
  template() {
    const Navigator = ExtensionPoints.navigator
    return (
      <React.Fragment>
        <div className="content">
          <div className="message is-large-font is-centered">
            We can't find the page you requested.
          </div>
          <div className="message is-medium-font is-centered">
            Please check the url or navigate to another page.
          </div>
          <div className="navigator">
            <Navigator />
          </div>
        </div>
      </React.Fragment>
    )
  },
  tagName: CustomElements.register('notfound'),
  serializeData: function() {
    return {
      route: window.location.hash.substring(1),
    }
  },
})
コード例 #4
0
ファイル: tags-edit.js プロジェクト: NealRame/mbac
define(function(require) {
    'use strict';

    var _ = require('underscore');
    var Backbone = require('backbone');
    var Marionette = require('marionette');
    var functional = require('common/functional');
    var util = require('common/util');
    var template = require('text!common/TagsEditView/tags-edit.html');
    var TagListView = require('common/TagsEditView/tag-list');
    var AutocompleteList = require('common/TagsEditView/autocomplete-list');

    var KEY_ENTER = 13;
    var KEY_UP = 38;
    var KEY_DOWN = 40;
    var KEY_ESC = 27;

    var Tag = Backbone.Model.extend({
        idAttribute: 'tag'
    });

    var TagList = Backbone.Collection.extend({
        model: Tag
    });

    function autocomplete(prefix, available_tags, collection) {
        return new AutocompleteList({
            collection: new Backbone.Collection(
                prefix.length > 0
                    ? _.chain(available_tags)
                        .difference(collection.pluck('tag'))
                        .filter(function(tag) {
                            return tag.startsWith(prefix);
                        })
                        .map(function(tag) {
                            return {item: tag};
                        })
                        .value()
                    : []
            )
        });
    }

    return Marionette.LayoutView.extend({
        className: 'row',
        ui: {
            input: '.input > input',
            inputWrapper: '.input'
        },
        regions: {
            tagList: '.tag-list-wrapper',
            autocompleteList: '.autocomplete-list-wrapper'
        },
        childEvents: {
            'autocomplete:item:clicked': 'onAutocompleteItemClicked'
        },
        template: _.template(template),
        initialize: function(options) {
            this.tags = new TagList([]);
            this.mergeOptions(options, ['inputAttribute', 'inputAvailableTags', 'inputError', 'inputId', 'inputLabel']);
            if (!functional.existy(this.inputId)) {
                this.inputId = util.randomString({
                    prefix: 'input'
                });
            }
            if (!functional.existy(this.inputAvailableTags)) {
                this.inputAvailableTags = [];
            } else {
                this.inputAvailableTags = this.inputAvailableTags.split(',');
            }
            this.listenTo(this.tags, 'add remove', function() {
                this.triggerMethod('changed');
            });
        },
        serializeData: function() {
            return {
                inputError: this.inputError,
                inputId: this.inputId,
                inputLabel: this.inputLabel
            };
        },
        onInputChanged: function() {
            var prefix = this.ui.input.val().trim().toLowerCase();
            if (prefix) {
                this.ui.input.data('value', this.ui.input.val());
                this.showChildView(
                    'autocompleteList',
                    autocomplete(prefix, this.inputAvailableTags, this.tags)
                );
            } else {
                this.getRegion('autocompleteList').empty();
            }
        },
        onInputKeypress: function(ev) {
            var mod = ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey;
            var key_code = ev.keyCode;
            var prefix = this.ui.input.val().trim().toLowerCase();
            var region = this.getRegion('autocompleteList');

            if (!mod && (key_code === KEY_UP || key_code === KEY_DOWN)) {
                if (region.currentView) {
                    this.ui.input.val(region.currentView.next(key_code));
                }
            } else if (key_code === KEY_ESC) {
                region.empty();
                this.ui.input.val(this.ui.input.data('value'));
                this.ui.input.removeData('value');
            } else if (prefix && key_code === KEY_ENTER) {
                region.empty();
                this.tags.add({tag: prefix});
                this.ui.input.removeData();
                this.ui.input.val('');
            }
            ev.stopPropagation();
            ev.preventDefault();
        },
        onInputGainFocus: function() {
            this.ui.inputWrapper.addClass('focus');
        },
        onInputLostFocus: function() {
            this.ui.inputWrapper.removeClass('focus');
        },
        onAutocompleteItemClicked: function(view, item) {
            this.getRegion('autocompleteList').empty();
            this.tags.add({tag: item});
            this.ui.input.removeData();
            this.ui.input.val('');
        },
        onRender: function() {
            this.showChildView('tagList', new TagListView({
                collection: this.tags
            }));
            this.delegateEvents({
                'blur  @ui.input': 'onInputLostFocus',
                'focus @ui.input': 'onInputGainFocus',
                'keyup @ui.input': 'onInputKeypress',
                'input @ui.input': _.debounce(this.onInputChanged.bind(this), 200)
            });
        },
        value: function() {
            return _.object([
                [
                    this.inputAttribute,
                    this.tags.pluck('tag')
                ]
            ]);
        },
        setValue: function(value) {
            this.tags.reset(_.map(value, function(tag) {
                return {tag: tag};
            }));
        }
    });
});
コード例 #5
0
export default Marionette.LayoutView.extend({
    template,
    tagName: "tr",
    tableViewModel: undefined,

    initialize: function (options)
    {
        // Call the super constructor
        Marionette.ItemView.prototype.initialize.call(this, options);

        this.tableViewModel = options.tableViewModel;
    },

    regions: {
        "elementsRegion": ".elements",
        "classifiedElementsRegion": ".classified-elements"
    },

    onShow: function ()
    {
        var that = this;
        // setTimeout(function ()
        // {
        var view = new Marionette.CollectionView({
            childView: GlyphTableItemView,
            collection: that.model.get("glyphs")
            // sort: false
        });
        view.childViewOptions = function ()
        {
            return {
                tableViewModel: that.tableViewModel
            }
        };

        that.elementsRegion.show(view);
        // }, 2000);
    }
})
コード例 #6
0
module.exports = Marionette.LayoutView.extend({
  template: template,
  tagName: CustomElements.register('query-feedback'),
  events: {
    'click .editor-cancel': 'handleCancel',
    'click .editor-send': 'handleSend',
  },
  regions: {
    comments: '.properties-comments',
  },
  initialize: function() {
    this.listenTo(router, 'change', this.handleCancel)
  },
  onBeforeShow: function() {
    this.comments.show(
      new PropertyView({
        model: new PropertyModel({
          value: [''],
          id: 'Please enter some comments to include',
          type: 'TEXTAREA',
        }),
      })
    )
    this.edit()
  },
  edit: function() {
    this.$el.addClass('is-editing')
    this.regionManager.forEach(function(region) {
      if (region.currentView && region.currentView.turnOnEditing) {
        region.currentView.turnOnEditing()
      }
    })
  },
  handleCancel: function() {
    this.$el.trigger(CustomElements.getNamespace() + 'close-lightbox')
  },
  handleSend: function() {
    const payload = {
      user: {
        email: user.get('user').get('email'),
        name: user.get('user').get('username'),
      },
      search: {
        initiated: new Date(
          this.model.get('result').get('initiated')
        ).toISOString(),
        cql: this.model.get('cql'),
        results: this.model
          .get('result')
          .get('results')
          .toJSON(),
        status: this.model
          .get('result')
          .get('status')
          .toJSON(),
      },
      workspace: {
        id: store.getCurrentWorkspace().id,
        name: store.getCurrentWorkspace().get('title'),
      },
      comments: this.comments.currentView.model.getValue()[0],
    }
    $.post('./internal/feedback', JSON.stringify(payload))
    this.$el.trigger(CustomElements.getNamespace() + 'close-lightbox')
  },
})
コード例 #7
0
ファイル: navigation-middle.view.js プロジェクト: codice/ddf
 * <http://www.gnu.org/licenses/lgpl.html>.
 *
 **/

const Marionette = require('marionette')
const CustomElements = require('../../js/CustomElements.js')
import * as React from 'react'
import { FormattedMessage } from 'react-intl'

module.exports = Marionette.LayoutView.extend({
  getLabel() {
    const { i18n, text } = this.options

    if (i18n) {
      const { id, defaultMessage } = this.options
      return <FormattedMessage id={id} defaultMessage={defaultMessage} />
    }

    return text
  },
  template(props) {
    return <div className={props.menuClass}>{this.getLabel()}</div>
  },
  tagName: CustomElements.register('navigation-middle'),
  serializeData() {
    return {
      menuClass: this.options.classes,
    }
  },
})
コード例 #8
0
ファイル: workspace-details.view.js プロジェクト: LinkMJB/ddf
module.exports = Marionette.LayoutView.extend({
  template: template,
  tagName: CustomElements.register('workspace-details'),
  regions: {
    unsavedIndicator: '.title-indicator',
  },
  initialize: function(options) {
    this.listenTo(
      user.get('user').get('preferences'),
      'change:homeDisplay',
      this.handleDisplayPref
    )
  },
  onRender: function() {
    this.handleDisplayPref()
  },
  onBeforeShow: function() {
    this.unsavedIndicator.show(
      new UnsavedIndicatorView({
        model: this.model,
      })
    )
  },
  handleDisplayPref: function() {
    this.$el.toggleClass(
      'as-list',
      user
        .get('user')
        .get('preferences')
        .get('homeDisplay') === 'List'
    )
  },
  serializeData: function() {
    var workspacesJSON = this.model.toJSON()
    workspacesJSON.niceDate = moment(
      workspacesJSON['metacard.modified']
    ).fromNow()
    workspacesJSON.owner = workspacesJSON['metacard.owner'] || 'Guest'
    return workspacesJSON
  },
})
コード例 #9
0
ファイル: ingest-editor.view.js プロジェクト: LinkMJB/ddf
module.exports = Marionette.LayoutView.extend({
  template: template,
  tagName: CustomElements.register('ingest-editor'),
  events: {
    'click .ingest-editor-clear': 'clear',
  },
  regions: {
    editorProperties: '.ingest-editor-properties',
  },
  onBeforeShow: function() {
    this.editorProperties.show(
      PropertyCollectionView.generateFilteredPropertyCollectionView(
        properties.editorAttributes,
        []
      )
    )
    this.editorProperties.currentView.$el.addClass('is-list')
    this.editorProperties.currentView.turnOnEditing()
  },
  clear: function() {
    this.editorProperties.currentView.revert()
    this.editorProperties.currentView.hideRequiredWarnings()
  },
  getPropertyCollectionView: function() {
    return this.editorProperties.currentView
  },
  /*
        Return a map of attributes to their corresponding value arrays. Blank values are
        filtered, and only attributes with at least one non-blank value are returned.
     */
  getAttributeOverrides: function() {
    return _.chain(
      this.editorProperties.currentView.toPropertyJSON().properties
    )
      .mapObject(function(values) {
        return values.filter(value => value.trim().length > 0)
      })
      .pick(function(values) {
        return values.length > 0
      })
      .value()
  },
})
コード例 #10
0
ファイル: list-create.view.js プロジェクト: LinkMJB/ddf
module.exports = Marionette.LayoutView.extend({
  tagName: CustomElements.register('list-create'),
  template: template,
  events: {
    'click > .editor-footer .create-list': 'createList',
    'click > .editor-footer .create-list-with-bookmarks':
      'createListWithBookmarks',
  },
  regions: {
    listEditor: '> .list-editor',
  },
  initialize: function() {
    this.handleBookmarks()
  },
  handleBookmarks: function() {
    this.$el.toggleClass(
      'with-bookmarks',
      _.get(this, ['options', 'options', 'withBookmarks']) === true
    )
  },
  onBeforeShow: function() {
    if (!this.isDestroyed) {
      this.showListEditor()
    }
  },
  showListEditor: function() {
    this.listEditor.show(
      new ListEditorView({
        model: new List(),
        showListTemplates: true,
      })
    )
  },
  createList: function() {
    this.listEditor.currentView.save()
    store
      .getCurrentWorkspace()
      .get('lists')
      .add(this.listEditor.currentView.model)
    this.onBeforeShow()
  },
  createListWithBookmarks: function() {
    this.listEditor.currentView.save()
    if (
      this.model.every(result => {
        return result.matchesCql(
          this.listEditor.currentView.model.get('list.cql')
        )
      })
    ) {
      this.listEditor.currentView.model.addBookmarks(
        this.model.map(function(result) {
          return result.get('metacard').id
        })
      )
      store
        .getCurrentWorkspace()
        .get('lists')
        .add(this.listEditor.currentView.model, { preventSwitch: true })
      this.onBeforeShow()
    } else {
      this.listenTo(
        ConfirmationView.generateConfirmation({
          prompt:
            "This list's filter prevents the result from being in the list.  Create list without result?",
          no: 'Cancel',
          yes: 'Create',
        }),
        'change:choice',
        function(confirmation) {
          if (confirmation.get('choice')) {
            store
              .getCurrentWorkspace()
              .get('lists')
              .add(this.listEditor.currentView.model, { preventSwitch: true })
            this.onBeforeShow()
          }
        }.bind(this)
      )
    }
  },
})
コード例 #11
0
module.exports = Marionette.LayoutView.extend({
  tagName: CustomElements.register('query-feed'),
  behaviors() {
    return {
      dropdown: {
        dropdowns: [
          {
            selector: '.details-view',
            view: QueryStatusView,
            viewOptions: {
              model: this.options.model,
            },
          },
        ],
      },
    }
  },
  initialize: function(options) {
    this.updateQuery = _.throttle(this.updateQuery, 200)
    this.listenTo(this.model, 'change', this.updateQuery)
    if (this.model.has('result')) {
      this.listenToStatus(this.model)
    } else {
      this.listenTo(this.model, 'change:result', this.resultAdded)
    }
  },
  template(data) {
    return (
      <React.Fragment>
        <div className="details-text">
          <div className="details-results" title={data.resultCount}>
            {data.pending ? (
              <i className="fa fa-circle-o-notch fa-spin is-critical-animation" />
            ) : (
              ''
            )}
            {data.failed ? <i className="fa fa-warning" /> : ''}
            {data.resultCount}
          </div>
          <div className="details-status" title="Last run {{queryStatus}}">
            {data.queryStatus}
          </div>
        </div>
        <button
          className="details-view is-button"
          title="Show the full status for the search."
          data-help="Show the full status for the search."
        >
          <span className="fa fa-heartbeat" />
        </button>
      </React.Fragment>
    )
  },
  updateQuery: function() {
    if (!this.isDestroyed) {
      this.render()
    }
  },
  resultAdded: function(model) {
    if (model.has('result') && _.isUndefined(model.previous('result'))) {
      this.listenToStatus(model)
    }
  },
  listenToStatus: function(model) {
    this.$el.toggleClass('has-been-run')
    this.listenTo(model.get('result>results'), 'reset', this.updateQuery)
    this.listenTo(model.get('result>results'), 'add', this.updateQuery)
    this.listenTo(model.get('result'), 'sync', this.updateQuery)
    this.listenTo(model.get('result>status'), 'change', this.updateQuery)
  },
  serializeData: function() {
    const query = this.model.toJSON({
      additionalProperties: ['cid', 'color'],
    })
    if (this.model.get('result')) {
      const status = _.filter(
        this.model
          .get('result')
          .get('status')
          .toJSON(),
        function(status) {
          return status.id !== 'cache'
        }
      )
      return {
        resultCount: getResultsFound(
          this.model.get('result').get('results').length,
          status
        ),
        pending: getPending(status),
        failed: getFailed(status),
        queryStatus: getLastRan(this.model.get('result>initiated')),
      }
    } else {
      return {
        resultCount: 'Has not been run',
        queryStatus: '',
      }
    }
  },
})
コード例 #12
0
ファイル: query-add.view.js プロジェクト: beyelerb/ddf
module.exports = Marionette.LayoutView.extend({
  template: template,
  tagName: CustomElements.register('query-add'),
  regions: {
    queryContent: '> form > .editor-content > .content-form',
    queryTitle: '> form > .editor-content > .content-title',
    queryFooter: '> form > .editor-content > .content-footer',
  },
  events: {
    'click .editor-edit': 'edit',
    'click .editor-cancel': 'cancel',
    'click .editor-save': 'save',
    'click .editor-saveRun': 'saveRun',
  },
  initialize: function() {
    this.model = new Query.Model()
    this.listenTo(this.model, 'resetToDefaults change:type', this.reshow)
    this.listenTo(this.model, 'closeDropdown', this.closeDropdown)
    this.listenForSave()
  },
  reshow: function() {
    this.$el.toggleClass(
      'is-form-builder',
      this.model.get('type') === 'new-form'
    )
    switch (this.model.get('type')) {
      case 'new-form':
        this.showFormBuilder()
        break
      case 'text':
        this.showText()
        break
      case 'basic':
        this.showBasic()
        break
      case 'advanced':
        this.showAdvanced()
        break
      case 'custom':
        this.showCustom()
        break
    }
  },
  onBeforeShow: function() {
    this.reshow()
    this.showTitle()
  },
  showTitle: function() {
    this.queryTitle.show(
      new QueryTitle({
        model: this.model,
      })
    )
  },
  showFormBuilder: function() {
    this.queryContent.show(
      new QueryAdvanced({
        model: this.model,
        isForm: true,
        isFormBuilder: true,
      })
    )
  },
  showText: function() {
    this.queryContent.show(
      new QueryAdhoc({
        model: this.model,
      })
    )
  },
  showBasic: function() {
    this.queryContent.show(
      new QueryBasic({
        model: this.model,
      })
    )
  },
  handleEditOnShow: function() {
    if (this.$el.hasClass('is-editing')) {
      this.edit()
    }
  },
  showAdvanced: function() {
    this.queryContent.show(
      new QueryAdvanced({
        model: this.model,
        isForm: false,
        isFormBuilder: false,
      })
    )
  },
  showCustom: function() {
    this.queryContent.show(
      new QueryAdvanced({
        model: this.model,
        isForm: true,
        isFormBuilder: false,
      })
    )
  },
  focus: function() {
    this.autoLoadDefaultIfSet()
    this.queryContent.currentView.focus()
  },
  autoLoadDefaultIfSet: function() {
    let userDefaultTemplate = user.getQuerySettings().get('template')
    if (userDefaultTemplate) {
      let sorts =
        userDefaultTemplate['querySettings'] &&
        userDefaultTemplate['querySettings'].sorts
      if (sorts) {
        sorts = sorts.map(sort => ({
          attribute: sort.split(',')[0],
          direction: sort.split(',')[1],
        }))
      }
      this.model.set({
        type: 'custom',
        title: userDefaultTemplate['name'],
        filterTree: userDefaultTemplate['filterTemplate'],
        src:
          (userDefaultTemplate['querySettings'] &&
            userDefaultTemplate['querySettings'].src) ||
          '',
        federation:
          (userDefaultTemplate['querySettings'] &&
            userDefaultTemplate['querySettings'].federation) ||
          'enterprise',
        sorts: sorts,
        'detail-level':
          (userDefaultTemplate['querySettings'] &&
            userDefaultTemplate['querySettings']['detail-level']) ||
          'allFields',
      })

      this.showCustom()
    }
  },
  edit: function() {
    this.$el.addClass('is-editing')
    this.queryContent.currentView.edit()
  },
  cancel: function() {
    this.$el.removeClass('is-editing')
    this.onBeforeShow()
  },
  save: function() {
    this.queryContent.currentView.save()
    this.queryTitle.currentView.save()
    if (this.$el.hasClass('is-form-builder')) {
      this.$el.trigger('closeDropdown.' + CustomElements.getNamespace())
      return
    }
    if (store.getCurrentQueries().get(this.model) === undefined) {
      store.getCurrentQueries().add(this.model)
    }
    this.cancel()
    this.$el.trigger('closeDropdown.' + CustomElements.getNamespace())
  },
  setDefaultTitle: function() {
    this.queryContent.currentView.setDefaultTitle()
  },
  saveRun: function() {
    if (!this.queryContent.currentView.isValid()) {
      announcement.announce(InvalidSearchFormMessage)
      return
    }
    this.queryContent.currentView.save()
    this.queryTitle.currentView.save()
    if (this.model.get('title') === 'Search Name') {
      this.setDefaultTitle()
    }
    if (store.getCurrentQueries().canAddQuery()) {
      store.getCurrentQueries().add(this.model)
      this.endSave()
    } else {
      this.listenTo(
        QueryConfirmationView.generateConfirmation({}),
        'change:choice',
        function(confirmation) {
          var choice = confirmation.get('choice')
          if (choice === true) {
            var loadingview = new LoadingView()
            store
              .get('workspaces')
              .once('sync', function(workspace, resp, options) {
                loadingview.remove()
                wreqr.vent.trigger('router:navigate', {
                  fragment: 'workspaces/' + workspace.id,
                  options: {
                    trigger: true,
                  },
                })
              })
            store.get('workspaces').createWorkspaceWithQuery(this.model)
          } else if (choice !== false) {
            store.getCurrentQueries().remove(choice)
            store.getCurrentQueries().add(this.model)
            this.endSave()
          }
        }.bind(this)
      )
    }
  },
  endSave: function() {
    this.model.startSearch()
    store.setCurrentQuery(this.model)
    this.initialize()
    this.cancel()
    this.$el.trigger('closeDropdown.' + CustomElements.getNamespace())
  },
  listenForSave: function() {
    this.$el.off('saveQuery.' + CustomElements.getNamespace()).on(
      'saveQuery.' + CustomElements.getNamespace(),
      function(e) {
        this.saveRun()
      }.bind(this)
    )
  },
  closeDropdown: function() {
    this.$el.trigger('closeDropdown.' + CustomElements.getNamespace())
  },
})
コード例 #13
0
define(function(require) {
	'use strict';

	var
	Marionette			= require('marionette'),
	Form				= require('src/model/form'),
	ElementView			= require('./element_view'),
	InputViews			= require('./input_view_types'),
	log					= require('src/lib/log'); /* jshint ignore: line */


	var FormView = Marionette.LayoutView.extend({
		tagName: 'form',

		elementView: ElementView,

		formViewEvents: {
			'render': 'onFormRender'
		},

		triggers: {
			'submit': 'before:form:submit',
			'reset': {
				event: 'form:reset',
				preventDefault: false,
				stopPropagation: false
			}
		},

		constructor: function(options) {
			options = options || {};

			// set up form model
			options.model = this.setupFormModel(options.model);

			// validate elementView
			if (options.elementView) this.elementView = options.elementView;
			this.validateElementView();

			Marionette.LayoutView.call(this, options);

			// bind view events
			this.bindEntityEvents(this, this.formViewEvents);

		},

		setupFormModel: function(model) {
			if (model instanceof Form) return model;

			if (model instanceof Backbone.Model) {
				model = new Form(model.attributes);
			} else {
				throw new Error('FormView requires a Form model.');
			}

			return model;
		},

		validateElementView: function() {
			if (this.elementView === ElementView) return;
			if (this.elementView.prototype instanceof ElementView) return;
			throw new Error('FormView.elementView must be an ElementView.');
		},

		onFormRender: function() {
			this.addElementViews();
		},
		onFormReset: function() {
			// form reset doesn't trigger any change event on the inputs that are changed by resetting
			// so we have to shim that event in order to reset any validation errors
			// have to defer this so the reset event can complete and values are restored
			_.defer(_.bind(function() {
				this.$('input, select, textarea').trigger('change');
			}, this));
		},

		addElementViews: function() {
			var elements = this.model.get('elements');
			elements.each(this.addElementView, this);
		},

		addElementView: function(element) {
			var View = this.getElementView(element);
			var view = new View({
				el: this.$(element.get('el')),
				model: element
			});
			view.render();
		},

		getElementView: function(element) {
			if (element.get('raw')) {
				var type = element.get('type');
				var View = InputViews[type];
				if (View) {
					return View;
				} else {
					throw new Error('No raw InputView defined for type '+ type);
				}
			} else {
				return this.elementView;
			}
		},

		onBeforeFormSubmit: function() {
			if (this.model.isValid()) {
				this.triggerMethod('form:submit');
				log('Form is valid. Implement your own onFormSubmit handler to do something with the form data.');
			} else {
				this.triggerMethod('form:submit:error', this.model.validationError);
				log('Form is not valid.', this.model.validationError);
			}
		}

	});

	return FormView;

});
コード例 #14
0
ファイル: product-edit-view.js プロジェクト: NealRame/mbac
define(function(require) {
	'use strict';

	var $ = require('jquery');
    var _ = require('underscore');
	var Backbone = require('backbone');
    var Marionette = require('marionette');
    var Dialog = require('Dialog');
	var PictureList = require('PictureList');
	var async = require('common/async');
	var errors = require('common/errors');
	var functional = require('common/functional');
    var template = require('text!pages/products/back/product-edit-view/product-edit-view.html');

	var app_channel = Backbone.Wreqr.radio.channel('app');

    return Marionette.LayoutView.extend({
		className: 'form-wrapper',
        ui: {
			addPictures: '#add-pictures',
			price: '#price',
			available: '#available',
			published: '#published',
            description: '#description',
            name: '#name',
            tags: '#tags',
			inputs: 'input, textarea'
        },
		events: {
			'click @ui.addPictures': 'onAddPicturesClick',
			'focus @ui.inputs': 'onInputFocus',
			'blur @ui.inputs': 'onInputFocus',
			'change @ui.inputs': 'onInputChanged'
		},
		childEvents: {
			'picture:added': 'onInputChanged',
			'picture:removed': 'onInputChanged'
		},
		regions: {
			pictures: '#pictures'
		},
        template: _.template(template),
		templateHelpers: function() {
			var model = this.model;
			return {
				hasError: functional.existy(this.errorMessage),
				errorMessage: this.errorMessage,
				fieldError: function(field) {
					return functional.property(
						model,
						'validationError.reason.' + field
					) || '';
				},
				fieldIsValid: function(field) {
					return !functional.existy(functional.property(
						model,
						'validationError.reason.' + field
					));
				}
			};
		},
		initialize: function(options) {
			_.bindAll(this, 'onCommand');
			this.router = options.router;
			app_channel.commands.setHandler('product', this.onCommand);
		},
		reset: function() {
			this.ui.name.val(this.model.name());
			this.ui.tags.val(this.model.tags().join(', '));
			this.ui.description.val(this.model.description());
			this.ui.available.prop('checked', this.model.available());
			this.ui.published.prop('checked', this.model.published());
			this.ui.price.val(this.model.get('price'));
			this.showChildView('pictures', new PictureList({
				collection: new Backbone.Collection(this.model.pictures()),
				editable: true,
				thumbnailsRect: {
					width: 192,
					height: 128
				}
			}));
		},
		values: function() {
			return {
				available: this.ui.available.prop('checked'),
				description: this.ui.description.val(),
				name: this.ui.name.val(),
				pictures: this.getChildView('pictures')
					.items()
					.map(function(picture) {
						return picture.attributes
					}),
				price: Number(this.ui.price.val()),
				published: this.ui.published.prop('checked'),
				resellers: [],
				tags: _.compact(this.ui.tags.val().split(',').map(function(tag) {
					return tag.trim().toLowerCase();
				}))
			};
		},
		onSave: function() {
			var router = this.router;
			var model = this.model;
			var view = this;
			async.saveModel(this.collection.add(model).set(this.values()))
				.then(function() {
					delete view.errorMessage;
					router.navigate('#' + model.id, {
						replace: true
					});
				})
				.catch(function(err) {
					view.errorMessage =
						err instanceof errors.ModelValidationError
							? 'Le formulaire contient des entrées non valides.'
							: err.message;
				})
				.then(function() {
					view.render();
				});
		},
		onRemove: function() {
			var router = this.router;
			var view = this;
			async.destroyModel(this.model)
				.catch(function(err) {
					view.errorMessage = err.message;
					view.render();
				})
				.then(function() {
					router.navigate('#', {
						replace: true,
						trigger: true
					});
				});
		},
		onCommand: functional.dispatch(
			function(cmd) {
				if (cmd !== 'save') return;
				if (this.edited) {
					Dialog.prompt(
						'Êtes vous sûr de vouloir sauvegarder les modificiations?',
						{
							accept: this.triggerMethod.bind(this, 'save'),
							acceptLabel: 'Oui',
							refuseLabel: 'Non'
						}
					);
					return true;
				}
			},
			function(cmd) {
				if (cmd !== 'remove') return;
				Dialog.prompt(
					'Êtes vous sûr de vouloir supprimer ce produit?',
					{
						accept: this.triggerMethod.bind(this, 'remove'),
						acceptLabel: 'Oui',
						refuseLabel: 'Non'
					}
				);
				return true;
			}
		),
		onInputChanged: function() {
			this.edited = !_.isEqual(
				this.values(),
				this.model.omit('_id', '__v', 'date')
			);
		},
		onInputFocus: functional.dispatch(
			function(ev) {
				if (ev.type === 'focusin') {
					$(ev.target).parent().addClass('filled');
					return true;
				}
			},
			function(ev) {
				if (ev.type === 'focusout') {
					$(ev.target).parent().removeClass('filled');
					return true;
				}
			}
		),
        onRender: function() {
			this.reset();
			this.onInputChanged();
        }
    });
});
コード例 #15
0
import Marionette from "marionette";

export default Marionette.LayoutView.extend({
    el: 'body',

    regions: {
        container: "#content",
        navigation: "#navigation",
        modal: "#root-modal"
    }
});
コード例 #16
0
module.exports = Marionette.LayoutView.extend({
    template: template,
    tagName: CustomElements.register('ingest-details'),
    events: {
        'click > .details-footer .footer-clear': 'newUpload',
        'click > .details-footer .footer-start': 'startUpload',
        'click > .details-footer .footer-cancel': 'cancelUpload',
        'click > .details-footer .footer-new': 'newUpload',
        'click > .details-dropzone .dropzone-text': 'addFiles'
    },
    regions: {
        files: '> .details-files',
        summary: '> .details-summary'
    },
    dropzone: undefined,
    uploadBatchModel: undefined,
    dropzoneAnimationRequestDetails: undefined,
    initialize: function() {},
    onBeforeShow: function() {
        this.setupDropzone();
        this.setupBatchModel();
        this.showFiles();
        this.showSummary();
    },
    setupBatchModel: function() {
        this.uploadBatchModel = new UploadBatchModel({}, {
            dropzone: this.dropzone
        });
        this.setupBatchModelListeners();
    },
    setupBatchModelListeners: function() {
        this.listenTo(this.uploadBatchModel, 'add:uploads remove:uploads reset:uploads', this.handleUploadUpdate);
        this.listenTo(this.uploadBatchModel, 'change:sending', this.handleSending);
        this.listenTo(this.uploadBatchModel, 'change:finished', this.handleFinished);
    },
    handleFinished: function() {
        this.$el.toggleClass('is-finished', this.uploadBatchModel.get('finished'));
    },
    handleSending: function() {
        this.$el.toggleClass('is-sending', this.uploadBatchModel.get('sending'));
    },
    handleUploadUpdate: function() {
        if (this.uploadBatchModel.get('uploads').length === 0 && !this.uploadBatchModel.get('sending')) {
            Common.cancelRepaintForTimeframe(this.dropzoneAnimationRequestDetails);
            this.$el.toggleClass('has-files', false);
            this.unlistenToResize();
            this.$el.find('.details-dropzone').css('height', '');
        } else {
            this.$el.toggleClass('has-files', true);
            this.updateDropzoneHeight();
        }
    },
    setupDropzone: function() {
        this.dropzone = new Dropzone(this.el.querySelector('.details-dropzone'), {
            url: '/services/catalog/',
            maxFilesize: 5000000, //MB
            method: 'post',
            autoProcessQueue: false
        });
    },
    addFiles: function(){
        this.$el.find('.details-dropzone').click();
    },
    showFiles: function() {
        this.files.show(new UploadItemCollectionView({
            collection: this.uploadBatchModel.get('uploads')
        }));
    },
    showSummary: function() {
        this.summary.show(new UploadSummary({
            model: this.uploadBatchModel
        }));
    },
    clearUploads: function() {
        this.uploadBatchModel.clear();
    },
    startUpload: function() {
        this.uploadBatchModel.start();
    },
    cancelUpload: function() {
        this.uploadBatchModel.cancel();
    },
    newUpload: function() {
        this.$el.addClass('starting-new');
        setTimeout(function() {
            this.triggerMethod('ingestDetails:new');
        }.bind(this), 250);
    },
    expandUpload: function() {
        wreqr.vent.trigger('router:navigate', {
            fragment: 'uploads/' + this.uploadBatchModel.id,
            options: {
                trigger: true
            }
        });
    },
    updateDropzoneHeight: function() {
        updateDropzoneHeight(this);
        this.listenToResize();
        Common.cancelRepaintForTimeframe(this.dropzoneAnimationRequestDetails);
        this.dropzoneAnimationRequestDetails = Common.repaintForTimeframe(500, updateDropzoneHeight.bind(this, this));
    },
    listenToResize: function() {
        $(window).off(namespacedEvent('resize', this)).on(namespacedEvent('resize', this), this.updateDropzoneHeight.bind(this));
    },
    unlistenToResize: function() {
        $(window).off(namespacedEvent('resize', this));
    },
    onBeforeDestroy: function() {
        $(window).off(namespacedEvent('resize', this));
    },
});
コード例 #17
0
ファイル: metacard-menu.view.js プロジェクト: beyelerb/ddf
module.exports = Marionette.LayoutView.extend({
  template: template,
  tagName: CustomElements.register('metacard-menu'),
  events: {
    'click > .workspace-title': 'goToWorkspace',
  },
  regions: {
    metacardTitle: '.metacard-title',
  },
  onFirstRender: function() {
    this.listenTo(metacardInstance, 'change:currentMetacard', this.render)
  },
  onRender: function() {
    if (metacardInstance.get('currentMetacard')) {
      this.metacardTitle.show(
        new MetacardTitleView({
          model: new Backbone.Collection(
            metacardInstance.get('currentMetacard')
          ),
        })
      )
    }
  },
  goToWorkspace: function(e) {
    var workspaceId = $(e.currentTarget).attr('data-workspaceid')
    wreqr.vent.trigger('router:navigate', {
      fragment: 'workspaces/' + workspaceId,
      options: {
        trigger: true,
      },
    })
  },
  serializeData: function() {
    var currentWorkspace = store.getCurrentWorkspace()
    var resultJSON, workspaceJSON
    if (metacardInstance.get('currentMetacard')) {
      resultJSON = metacardInstance.get('currentMetacard').toJSON()
    }
    if (currentWorkspace) {
      workspaceJSON = currentWorkspace.toJSON()
    }
    return {
      result: resultJSON,
      workspace: workspaceJSON,
    }
  },
})
コード例 #18
0
ファイル: main.js プロジェクト: devel-pa/marionette-freeform
define(function(require) {
	'use strict';

	var
	Marionette				= require('marionette'),
	Form					= require('src/model/form'),
	FormView				= require('src/view/form_view'),
	BasicExample			= require('./examples/basic'),
	BasicCode				= require('text!./examples/basic.js'),
	BasicTemplate			= require('text!./examples/template/basic.html'),
	RelatedExample			= require('./examples/related_model'),
	RelatedCode				= require('text!./examples/related_model.js'),
	RelatedTemplate			= require('text!./examples/template/related_model.html'),
	ButtonFieldExample		= require('./examples/buttonfield'),
	ButtonFieldCode			= require('text!./examples/buttonfield.js'),
	ButtonFieldTemplate		= require('text!./examples/template/buttonfield.html'),
	RadiosetExample			= require('./examples/radioset'),
	RadiosetCode			= require('text!./examples/radioset.js'),
	RadiosetTemplate		= require('text!./examples/template/single.html'),
	log						= require('src/lib/log'); /* jshint ignore: line */
	require('src/lib/setPrefixedClassname');


	var view_model = new Backbone.Model({
		example: 'buttonfield',
		theme: 'inline'
	});

	var examples = {
		'basic': {
			label: 'Basic form',
			description: 'A basic form with a few elements. Each element provides its own validator. The first error returned by the validator is shown. Try entering "Bob" or "David" as your first name to see an example.',
			view: BasicExample,
			code: BasicCode,
			template: BasicTemplate
		},
		'related_model': {
			label: 'Form with a related model',
			description: 'Here, all validation is defined in a separate <code>User</code> model, which is used as the <code>related_model</code> for the form. Each element uses a <code>related_key</code> to associate it with a specific attribute of the user. The element gets its initial value from that user attribute and displays any errors associated with that attribute. Try entering a long first name, or try entering a username that breaks one of the rules shown in the example code below.',
			view: RelatedExample,
			code: RelatedCode,
			template: RelatedTemplate
		},
		'buttonfield': {
			label: 'Buttonfield',
			description: 'A very simple field consisting of a combined text field and button. This one requires a bit of CSS to achieve its appearance, of course.',
			view: ButtonFieldExample,
			code: ButtonFieldCode,
			template: ButtonFieldTemplate
		},
		'radioset': {
			label: 'Radio Set',
			description: 'A set of radio buttons.',
			view: RadiosetExample,
			code: RadiosetCode,
			template: RadiosetTemplate
		},
	};

	/* regexes used for displaying example code */
	var jshint = new RegExp('\\s+\/\\* jshint.*\\*\/', 'gim');
	var begin = new RegExp('[^•]+\/\\* begin example \\*\/\n', 'gim');
	var end = new RegExp('\\s+\/\\* end example \\*\/[^•]+', 'gim');

	var ExampleViewer = Marionette.LayoutView.extend({
		template: 'script.example',
		ui: {
			form: 'form',
			title: '.title',
			description: 'article',
			code: 'pre.code code',
			template: 'pre.template code'
		},
		viewModelEvents: {
			'change:theme': 'setTheme'
		},
		initialize: function() {
			_.bindAll(this, 'focusFirstInput');
			this.bindEntityEvents(view_model, this.viewModelEvents);
		},
		onRender: function() {
			this.setTheme();
			this.showDescription();
			this.showFormView();
			this.showExampleCode();
			this.showExampleTemplate();
			this.highlightCode();
		},
		onShow: function() {
			_.defer(this.focusFirstInput);
		},
		setTheme: function() {
			var theme = view_model.get('theme');
			if (theme === 'unstyled') {
				this.ui.form.removeClass('freeform');
			} else {
				this.ui.form.addClass('freeform');
			}
			this.ui.form.setPrefixedClassname('freeform', theme);
		},
		showDescription: function() {
			this.ui.title.text(this.options.example.label);
			this.ui.description.html(this.options.example.description);
		},
		showFormView: function() {
			var view = this.options.example.view;
			view.setElement(this.ui.form);
			view.render();
		},
		showExampleCode: function() {
			var code = this.options.example.code;
			code = code.replace(jshint, '');
			code = code.replace(begin, '');
			code = code.replace(end, '');
			code += '\n\n';
			code += '\t// show the form in some region\n';
			code += '\tmy_region.show(form_view);\n';
			code = code.replace(/^\t/gim, '');

			this.ui.code.text(code);
		},
		showExampleTemplate: function() {
			var template = this.options.example.template;
			this.ui.template.text(template);
		},
		highlightCode: function() {
			this.$('pre code').each(function(i, block) {
				hljs.highlightBlock(block);
			});
		},
		focusFirstInput: function() {
			this.$('input, select, textarea').first().focus().select();
		}
	});

	var ChooserView = FormView.extend({
		className: 'chooser',
		template: 'script.chooser'
	});

	var MainView = Marionette.LayoutView.extend({
		el: 'div.main',
		template: 'script.main',
		regions: {
			chooser_region: '.chooser-region',
			example_region: '.example-region'
		},
		initialize: function() {
			this.listenTo(view_model, 'change:example', this.showCurrentExample);
		},
		onRender: function() {
			this.showChooser();
			this.showCurrentExample();
		},
		showChooser: function() {
			var chooser_form = new Form({
				elements: [
					{
						el: '.examples',
						type: 'select',
						label: 'Examples',
						placeholder: 'Choose one:',
						related_key: 'example',
						values: _.map(_.keys(examples), function(key) {
							return { value: key, label: examples[key].label };
						})
					},
					{
						el: '.themes',
						type: 'select',
						label: 'Theme',
						placeholder: 'Choose one:',
						related_key: 'theme',
						values: [
							{ value: 'inline', label: 'Inline' },
							{ value: 'stacked', label: 'Stacked' },
							{ value: 'mixed', label: 'Mixed' },
							{ value: 'unstyled', label: 'Unstyled' },
						]
					}
				],
				related_model: view_model
			});
			var chooser_view = new ChooserView({ model: chooser_form });
			this.chooser_region.show(chooser_view);
		},
		showCurrentExample: function() {
			var example_name = view_model.get('example');
			var example = examples[example_name];
			if (example) {
				this.viewer = new ExampleViewer({
					example: example
				});
				this.example_region.show(this.viewer);
			} else {
				this.example_region.empty();
				delete this.viewer;
			}
		}
	});

	var main_view = new MainView();
	main_view.render();

});