jonjamz / meteor-amethyst-components

Amethyst components for Meteor (experimental and outdated)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Amethyst components (subjects) for Meteor

Taken from an old private repository of mine, last updated Feb 26, 2014!

This was purely experimental, dealing with very granular reusable components.

From the pre-Blaze era, some of these probably won't work--not that anybody should try.

Example

# Control how subjects are namespaced inside components using methodFacade
# ------------------------------------------------------------------------

# Ensure that the component has the methodFacade subject
ensureFacade = ->
  unless @methodFacade?
    A.subjects.load @, 'methodFacade'

A.subjects.save
  name: 'CF__animations'
  options:
    loaded: ->
      ensureFacade.call @
      animations = {}
      A.subjects.load @, 'RMS__animations'

A.subjects.save
  name: 'CF__errors'
  options:
    loaded: ->
      ensureFacade.call @
      A.subjects.load @, 'errors'
      @methodFacade.map
        logifer: @errors.logifer
        flashifer: @errors.flashifer

# Subject
A.subjects.save
  name: 'CF__collectionFactory'
  options:
    # Takes collection names as arguments
    loaded: (options) ->
      ensureFacade.call @
      arr = []
      privateRef = {} # Don't load db on `this`, use loaded() instance encapsulation

      # Iterate through collections, getting the full object from config (lib/config/1.collections.coffee)
      for collection in arguments
        if config? and config.collections[collection]?
          arr.push config.collections[collection]
        else
          # if console?.log?
          #   console.log config.collections
          throw new Error "Collection #{collection} isn't defined in config!"
      A.subjects.load privateRef, ['sharedCollections', arr]
      @methodFacade.map
        db: (collection) -> privateRef.sharedCollections(collection)

A.subjects.save
  name: 'CF__pubSubs'
  options:
    loaded: (options) ->
      ensureFacade.call @
      if options?
        A.subjects.load @, ['pubSubs', [options]]
        @methodFacade.map
          getSub: @pubSubs.getSub

A.subjects.save
  name: 'CF__safeReactiveProperties'
  options:
    loaded: (options) ->
      ensureFacade.call @
      if options?
        A.subjects.load @, ['safeReactiveProperties', [options]]
        @methodFacade.map
          set: @safeReactiveProperties.set
          get: @safeReactiveProperties.get
          inc: @safeReactiveProperties.inc
          dec: @safeReactiveProperties.dec
          tog: @safeReactiveProperties.toggle
          setDefault: @safeReactiveProperties.setDefault
          setAllDefaults: @safeReactiveProperties.setAllDefaults

A.subjects.save
  name: 'CF__localTemplate'
  options:
    loaded: (options) ->
      ensureFacade.call @
      if options?
        A.subjects.load @, 'localTemplate'
        for own key, val of options
          val.template = key
          @localTemplate.create val
        @methodFacade.map
          getStaticTemplate: @localTemplate.getStatic
          getReactiveTemplate: @localTemplate.getReactive
          getTemplateAlias: @localTemplate.getAlias
          loadInto: @localTemplate.loadInto
          appendInto: @localTemplate.appendInto
          prependInto: @localTemplate.prependInto
          _loadIntoArea: @localTemplate._loadIntoArea
          _appendIntoArea: @localTemplate._appendIntoArea
          _prependIntoArea: @localTemplate._prependIntoArea
# Build a component
# -----------------

observer = null # Watch for new content blocks

A.subjects.save
  name: 'repo__contentBlocks'
  options:
    subjects:
      CF__collectionFactory: ['Repositories', 'ContentBlocks']
      CF__pubSubs:
        uniqueName: 'repo__contentBlocks'
        currentRepoContentBlocks:
          publish: (options) ->
            if options?.repo?
              ContentBlocks.find
                repo: options.repo
          subscribe:
            options:
              repo: ->
                if Session.get('xCurrentRepo')
                  Session.get('xCurrentRepo')
            onReady: ->
              # console.log "repo__contentBlocks subscription ready!"

    unloaded: (options) ->
      observer.stop()

    loaded: (options) ->
      Meteor.defer => @pubSubs.startSubReactive 'currentRepoContentBlocks'

      # Observe the blocks and flash the alert bar whenever there's a new one created
      Meteor.defer =>
        observer = Deps.autorun =>
          @db('ContentBlocks').find
            repo: Session.get('xCurrentRepo')
            createdBy: $ne: Meteor.userId() # Don't flash if it's your own block
          .observeChanges
            added: (id, fields) ->
              now = new Date().getTime()
              posted = fields.createdAt.getTime()
              if (now - posted) < 10 * 1000
                if Routes.helpers?.repository?.layouts__threeColumnDynamic?
                  Routes.helpers.repository.layouts__threeColumnDynamic.triggerMiddleAlert()

      A.subjects.load @, 'CF__errors', 'CF__animations',

        ['CF__safeReactiveProperties', [

          activeRedactor:
            default: null
            schema: Match.OneOf null, String

          blockSort:
            default: 'manual'
            schema: String

        ]] # End CF__safeReactiveProperties

        ['methodFacade', [

          # Save and destroy all existing redactors (hopefully just one existing)
          # Except one (used for allowing only one redactor instance at a time)
          saveAndReleaseBlocks: (exceptId) ->
            for item in ($ '.active-redactor')
              if item.id isnt exceptId
                content = ($ item).redactor('get')
                if typeof content isnt 'string' then return undefined # Fail silently
                @db('ContentBlocks').update
                  _id: item.id
                ,
                  $set:
                    content: content
                    locked: false
                ($ item).redactor('destroy')
                ($ '.active-redactor').remove() # For when pressing escape during fs

          saveBlock: (id) ->
            content = ($ "##{id}").redactor('get')

            # Rarely, `content` is assigned a jQuery object. Check if it's a string and
            # fail silently if it isn't. Will be saved again with a debounce or release.
            if typeof content isnt 'string' then return undefined

            @db('ContentBlocks').update
              _id: id
            ,
              $set: content: content
            , (err) =>
              unless err?
                @RMS__animations.flash "#saved-#{id}"

        ]] # End methodFacade

        ['CF__localTemplate', [

          repo__contentBlocks:
            rendered: ->
              for active in @findAll('.active-redactor')
                ($ active).redactor
                  focus: true
                  autoresize: true
                  plugins: ['fullscreen', 'fontfamily']

              if filepicker?
                if !($ '.image-change-button:visible').length
                  filepicker.constructWidget document.getElementById('repo__contentBlocks__uploadFile')

            events:
              'change #repo__contentBlocks__uploadFile': (e) ->
                @db('ContentBlocks').insert
                  type: 'file'
                  repo: Session.get('xCurrentRepo')
                  content: e.fpfiles
                  locked: false
                  createdAt: new Date()
                @saveAndReleaseBlocks()
                Deps.flush()

              'click .repo__contentBlocks__sort': (e) ->
                e.preventDefault()
                e.stopImmediatePropagation()
                @set 'blockSort', ($ e.target).data('type')

              'click .forfeit-block': (e) ->
                e.preventDefault()
                @saveAndReleaseBlocks()
                @db('ContentBlocks').update
                  _id: @_id
                ,
                  $set: locked: false
                Deps.flush()

              'click .delete-block': (e) ->
                e.preventDefault()
                confMessage = if @type is 'file' then "Delete this file set?" else "Delete this content block?"
                if confirm confMessage
                  @db('ContentBlocks').remove _id: @_id

              'click .move-block-up': (e, t) ->
                e.preventDefault()
                e.stopImmediatePropagation()
                x = @position.x
                @db('ContentBlocks').update @_id, $inc: 'position.x': 1
                Deps.flush()

              'click .move-block-down': (e, t) ->
                e.preventDefault()
                e.stopImmediatePropagation()
                x = @position.x
                @db('ContentBlocks').update @_id, $inc: 'position.x': -1
                Deps.flush()

              'click .repo__contentBlocks__createBtn': (e) ->
                e.preventDefault()
                type = ($ e.target).data('type')
                @db('ContentBlocks').insert
                  type: type
                  repo: Session.get('xCurrentRepo')
                  content: "Add some text..."
                  locked: true
                  createdAt: new Date()
                  createdBy: Meteor.userId()
                  position:
                    x: @db('ContentBlocks').find(repo: Session.get('xCurrentRepo')).count() + 1
                @saveAndReleaseBlocks()
                Deps.flush()

              'keyup .click-redactor': _.debounce (e) ->

                 # Autosave
                 if e.type is 'keyup' and e.which != 27
                   @saveBlock @_id

              , 3000

              'click .click-redactor': (e) ->
                if @type is 'file' then return

                # Don't let anyone edit a locked block
                if @locked is true then return false

                # Only allow editing one block at a time
                if !($ e.currentTarget).find('.active-redactor').length
                  e.preventDefault()
                  @saveAndReleaseBlocks @_id
                  @db('ContentBlocks').update
                    _id: @_id
                  ,
                    # Updating to locked makes it ours, because we have the lastUpdatedBy
                    # See lib/handlebars
                    $set:
                      locked: true
                      lastUpdatedBy: Meteor.userId()
                  Deps.flush()

            helpers:
              contentBlocks: ->
                sort = {}
                if @get('blockSort') is 'manual'
                  sort = {'position.x': -1}
                else if @get('blockSort') is 'dateCreated'
                  sort = {createdAt: -1}

                @db('ContentBlocks').find
                  repo: Session.get('xCurrentRepo')
                ,
                  sort: sort
              manualSelected: ->
                if @get('blockSort') is 'manual'
                  return 'selected'
              dateCreatedSelected: ->
                if @get('blockSort') is 'dateCreated'
                  return 'selected'

        ]] # End CF__localTemplate

About

Amethyst components for Meteor (experimental and outdated)


Languages

Language:JavaScript 93.6%Language:CoffeeScript 6.4%