<commit_before>import Vue from 'vue'

import QBtn from '../btn/QBtn.js'

import DarkMixin from '../../mixins/dark.js'
import { PanelParentMixin } from '../../mixins/panel.js'
import FullscreenMixin from '../../mixins/fullscreen.js'

import { isNumber } from '../../utils/is.js'
import { mergeSlot } from '../../utils/slot.js'
import { cache } from '../../utils/vm.js'

export default Vue.extend({
  name: 'QCarousel',

  mixins: [ DarkMixin, PanelParentMixin, FullscreenMixin ],

  props: {
    height: String,
    padding: Boolean,

    transitionPrev: {
      default: 'fade'
    },
    transitionNext: {
      default: 'fade'
    },

    controlColor: String,
    autoplay: [Number, Boolean],

    arrows: Boolean,
    arrowsVertical: Boolean,
    prevIcon: String,
    nextIcon: String,

    navigation: Boolean,
    navigationPosition: {
      type: String,
      default: 'bottom',
      validator: v => ['top', 'right', 'bottom', 'left'].includes(v)
    },
    navigationIcon: String,

    thumbnails: Boolean
  },

  computed: {
    style () {
      if (this.inFullscreen !== true && this.height !== void 0) {
        return {
          height: this.height
        }
      }
    },

    classes () {
      return {
        fullscreen: this.inFullscreen,
        [`q-carousel--arrows${this.arrowsVertical === true ? '--vertical' : ''}`]: this.padding === true && this.arrows === true,
        [`q-carousel--navigation--${this.navigationPosition}`]: this.padding === true && this.navigation === true,
        'q-carousel--dark q-dark': this.isDark
      }
    },

    arrowIcons () {
      const ico = [
        this.prevIcon || (this.arrowsVertical === true ? this.$q.iconSet.carousel.up : this.$q.iconSet.carousel.left),
        this.nextIcon || (this.arrowsVertical === true ? this.$q.iconSet.carousel.down : this.$q.iconSet.carousel.right)
      ]

      return this.$q.lang.rtl === true
        ? ico.reverse()
        : ico
    },

    navIcon () {
      return this.navigationIcon || this.$q.iconSet.carousel.navigationIcon
    }
  },

  watch: {
    value () {
      if (this.autoplay) {
        clearInterval(this.timer)
        this.__startTimer()
      }
    },

    autoplay (val) {
      if (val) {
        this.__startTimer()
      }
      else {
        clearInterval(this.timer)
      }
    }
  },

  methods: {
    __startTimer () {
      this.timer = setTimeout(
        this.next,
        isNumber(this.autoplay) ? this.autoplay : 5000
      )
    },

    __getNavigationContainer (h, type, mapping) {
      return h('div', {
        staticClass: 'q-carousel__control q-carousel__navigation no-wrap absolute flex scroll-x q-carousel__navigation--' + type +
          ' q-carousel__navigation--' + this.navigationPosition,
        class: this.controlColor ? `text-${this.controlColor}` : null
      }, [
        h('div', {
          staticClass: 'q-carousel__navigation-inner flex no-wrap justify-center'
        }, this.__getAvailablePanels().map(mapping))
      ])
    },

    __getContent (h) {
      const node = []

      this.arrows === true && node.push(
        h(QBtn, {
          staticClass: `q-carousel__control q-carousel__prev-arrow${this.arrowsVertical === true ? '--vertical' : ''} absolute`,
          props: { size: 'lg', color: this.controlColor, icon: this.arrowIcons[0], round: true, flat: true, dense: true },
          on: cache(this, 'prev', { click: this.previous })
        }),
        h(QBtn, {
          staticClass: `q-carousel__control q-carousel__next-arrow${this.arrowsVertical === true ? '--vertical' : ''} absolute`,
          props: { size: 'lg', color: this.controlColor, icon: this.arrowIcons[1], round: true, flat: true, dense: true },
          on: cache(this, 'next', { click: this.next })
        })
      )

      if (this.navigation === true) {
        node.push(this.__getNavigationContainer(h, 'buttons', panel => {
          const name = panel.componentOptions.propsData.name

          return h(QBtn, {
            key: name,
            staticClass: 'q-carousel__navigation-icon',
            class: { 'q-carousel__navigation-icon--active': name === this.value },
            props: {
              icon: this.navIcon,
              round: true,
              flat: true,
              size: 'sm'
            },
            on: cache(this, 'nav#' + name, { click: () => { this.goTo(name) } })
          })
        }))
      }
      else if (this.thumbnails === true) {
        node.push(this.__getNavigationContainer(h, 'thumbnails', panel => {
          const slide = panel.componentOptions.propsData

          return h('img', {
            class: { 'q-carousel__thumbnail--active': slide.name === this.value },
            attrs: {
              src: slide.imgSrc
            },
            key: 'tmb#' + slide.name,
            on: cache(this, 'tmb#' + slide.name, { click: () => { this.goTo(slide.name) } })
          })
        }))
      }

      return mergeSlot(node, this, 'control')
    },

    __renderPanels (h) {
      return h('div', {
        staticClass: 'q-carousel q-panel-parent',
        style: this.style,
        class: this.classes
      }, [
        h('div', {
          staticClass: 'q-carousel__slides-container',
          directives: this.panelDirectives
        }, this.__getPanelContent(h))
      ].concat(this.__getContent(h)))
    }
  },

  mounted () {
    this.autoplay && this.__startTimer()
  },

  beforeDestroy () {
    clearInterval(this.timer)
  }
})
<commit_msg>Small tweaks to QCarousel<commit_after>import Vue from 'vue'

import QBtn from '../btn/QBtn.js'

import DarkMixin from '../../mixins/dark.js'
import { PanelParentMixin } from '../../mixins/panel.js'
import FullscreenMixin from '../../mixins/fullscreen.js'

import { isNumber } from '../../utils/is.js'
import { mergeSlot } from '../../utils/slot.js'
import { cache } from '../../utils/vm.js'

export default Vue.extend({
  name: 'QCarousel',

  mixins: [ DarkMixin, PanelParentMixin, FullscreenMixin ],

  props: {
    height: String,
    padding: Boolean,

    transitionPrev: {
      default: 'fade'
    },
    transitionNext: {
      default: 'fade'
    },

    controlColor: String,
    autoplay: [Number, Boolean],

    arrows: Boolean,
    arrowsVertical: Boolean,
    prevIcon: String,
    nextIcon: String,

    navigation: Boolean,
    navigationPosition: {
      type: String,
      default: 'bottom',
      validator: v => ['top', 'right', 'bottom', 'left'].includes(v)
    },
    navigationIcon: String,

    thumbnails: Boolean
  },

  computed: {
    style () {
      if (this.inFullscreen !== true && this.height !== void 0) {
        return {
          height: this.height
        }
      }
    },

    classes () {
      return {
        fullscreen: this.inFullscreen,
        [`q-carousel--arrows${this.arrowsVertical === true ? '--vertical' : ''}`]: this.padding === true && this.arrows === true,
        [`q-carousel--navigation--${this.navigationPosition}`]: this.padding === true && this.navigation === true,
        'q-carousel--dark q-dark': this.isDark
      }
    },

    arrowIcons () {
      const ico = [
        this.prevIcon || this.$q.iconSet.carousel[this.arrowsVertical === true ? 'up' : 'left'],
        this.nextIcon || this.$q.iconSet.carousel[this.arrowsVertical === true ? 'down' : 'right']
      ]

      return this.$q.lang.rtl === true
        ? ico.reverse()
        : ico
    },

    navIcon () {
      return this.navigationIcon || this.$q.iconSet.carousel.navigationIcon
    }
  },

  watch: {
    value () {
      if (this.autoplay) {
        clearInterval(this.timer)
        this.__startTimer()
      }
    },

    autoplay (val) {
      if (val) {
        this.__startTimer()
      }
      else {
        clearInterval(this.timer)
      }
    }
  },

  methods: {
    __startTimer () {
      this.timer = setTimeout(
        this.next,
        isNumber(this.autoplay) ? this.autoplay : 5000
      )
    },

    __getNavigationContainer (h, type, mapping) {
      return h('div', {
        staticClass: 'q-carousel__control q-carousel__navigation no-wrap absolute flex scroll-x q-carousel__navigation--' + type +
          ' q-carousel__navigation--' + this.navigationPosition,
        class: this.controlColor ? `text-${this.controlColor}` : null
      }, [
        h('div', {
          staticClass: 'q-carousel__navigation-inner flex no-wrap justify-center'
        }, this.__getAvailablePanels().map(mapping))
      ])
    },

    __getContent (h) {
      const node = []

      this.arrows === true && node.push(
        h(QBtn, {
          staticClass: `q-carousel__control q-carousel__prev-arrow${this.arrowsVertical === true ? '--vertical' : ''} absolute`,
          props: { size: 'lg', color: this.controlColor, icon: this.arrowIcons[0], round: true, flat: true, dense: true },
          on: cache(this, 'prev', { click: this.previous })
        }),
        h(QBtn, {
          staticClass: `q-carousel__control q-carousel__next-arrow${this.arrowsVertical === true ? '--vertical' : ''} absolute`,
          props: { size: 'lg', color: this.controlColor, icon: this.arrowIcons[1], round: true, flat: true, dense: true },
          on: cache(this, 'next', { click: this.next })
        })
      )

      if (this.navigation === true) {
        node.push(this.__getNavigationContainer(h, 'buttons', panel => {
          const name = panel.componentOptions.propsData.name

          return h(QBtn, {
            key: name,
            staticClass: 'q-carousel__navigation-icon',
            class: { 'q-carousel__navigation-icon--active': name === this.value },
            props: {
              icon: this.navIcon,
              round: true,
              flat: true,
              size: 'sm'
            },
            on: cache(this, 'nav#' + name, { click: () => { this.goTo(name) } })
          })
        }))
      }
      else if (this.thumbnails === true) {
        node.push(this.__getNavigationContainer(h, 'thumbnails', panel => {
          const slide = panel.componentOptions.propsData

          return h('img', {
            class: { 'q-carousel__thumbnail--active': slide.name === this.value },
            attrs: {
              src: slide.imgSrc
            },
            key: 'tmb#' + slide.name,
            on: cache(this, 'tmb#' + slide.name, { click: () => { this.goTo(slide.name) } })
          })
        }))
      }

      return mergeSlot(node, this, 'control')
    },

    __renderPanels (h) {
      return h('div', {
        staticClass: 'q-carousel q-panel-parent',
        style: this.style,
        class: this.classes
      }, [
        h('div', {
          staticClass: 'q-carousel__slides-container',
          directives: this.panelDirectives
        }, this.__getPanelContent(h))
      ].concat(this.__getContent(h)))
    }
  },

  mounted () {
    this.autoplay && this.__startTimer()
  },

  beforeDestroy () {
    clearInterval(this.timer)
  }
})
<|endoftext|>


<commit_before>$(document).ready(function() {
  $('#request_btn').click(function() {
    $('#myModal').modal('toggle');
    $('<input>').attr('type','hidden').attr('name','_request').attr('value','_request').appendTo('#vmForm');
    console.log(($('#vmForm').html()));
    $('#vmForm').submit();
  });
});
<commit_msg>Remove log<commit_after>$(document).ready(function() {
  $('#request_btn').click(function() {
    $('#myModal').modal('toggle');
    $('<input>').attr('type','hidden').attr('name','_request').attr('value','_request').appendTo('#vmForm');
    $('#vmForm').submit();
  });
});
<|endoftext|>


<commit_before><commit_msg>Update Question 1 Solution.js<commit_after><|endoftext|>


<commit_before>'use strict';

var path = require('path'),
  mongoose = require('mongoose'),
  Poll = mongoose.model('Poll'),
  Opt = mongoose.model('Opt'),
  Cmt = mongoose.model('Cmt'),
  Vote = mongoose.model('Vote'),
  Voteopt = mongoose.model('Voteopt'),
  Polltag = mongoose.model('Polltag'),
  Polluser = mongoose.model('Polluser'),
  Notif = mongoose.model('Notif'),
  Like = mongoose.model('Like'),
  errorHandler = require(path.resolve(
    './modules/core/server/controllers/errors.server.controller'
  )),
  _ = require('underscore');

// Create the chat configuration
module.exports = function (io, socket) {
  // On subscribe
  socket.on('subscribe_poll', req => {
    socket.join(req.pollId);
  });
  socket.on('subscribe_public', req => {
    socket.join('public');
  });
  // On unsubscribe
  socket.on('unsubscribe_poll', req => {
    socket.leave(req.pollId);
  });
  // On unsubscribe
  socket.on('unsubscribe_public', req => {
    socket.leave('public');
  });

  // On like poll
  socket.on('poll_like', req => {
    io.sockets.in(req.pollId).emit('poll_like', req.report);
    if (req.type === 0) {
      return;
    }
    // Create notifis
    var action = (req.type === 1) ? 'liked' : 'disliked';
    var notif = new Notif({
      from: req.from,
      to: req.to,
      content: 'has ' + action + ' your poll ',
      poll: req.pollId
    });
    notif.save().then(notif => {
      var socketIds = _.where(global.socketUsers, { user: req.to });
      socketIds.forEach(item => {
        io.sockets.connected[item.socket].emit('notifs', notif._id);
      });
    });
  });
  // On vote poll
  socket.on('poll_vote', req => {
    io.sockets.in(req.pollId).emit('poll_vote');
  });
  // On delete poll
  socket.on('poll_delete', req => {
    io.sockets.in(req.pollId).emit('poll_delete');
  });
  // On delete poll
  socket.on('poll_update', req => {
    io.sockets.in(req.pollId).emit('poll_update');
  });
  // On delete poll
  socket.on('poll_create', req => {
    io.sockets.in('public').emit('poll_create');
  });

  // On comment added
  socket.on('cmt_add', req => {
    io.sockets.in(req.pollId).emit('cmt_add', req.cmtId);
    if (req.to) {
      var notif = new Notif({
        from: req.from,
        to: req.to,
        content: 'has replied your comment on',
        poll: req.pollId
      });
      notif.save().then(notif => {
        var socketIds = _.where(global.socketUsers, { user: req.to });
        socketIds.forEach(item => {
          io.sockets.connected[item.socket].emit('notifs', notif._id);
        });
      });
    } else {
      // Tìm toàn bộ các member đang theo dõi poll
      Polluser.find({ poll: req.pollId, following: true }).then(
        pollusers => {
          var notif;
          // Tạo notif cho toàn bộ các member đang theo dõi
          pollusers.forEach((polluser, index) => {
            if (polluser.user.toString() !== req.from.toString()) {
              notif = new Notif({
                from: req.from,
                to: polluser.user,
                content: 'has posted a comment on',
                poll: req.pollId
              });
              notif.save().then(
                _notif => {
                  var socketIds = _.where(global.socketUsers, {
                    user: polluser.user.toString()
                  });
                  socketIds.forEach(item => {
                    io.sockets.connected[item.socket].emit(
                      'notifs',
                      _notif._id
                    );
                  });
                },
                err => {
                  console.log('Has error when save notif comment');
                }
              );
            }
          });
        },
        err => {
          console.log('Has error when get user in poll for comment');
        }
      );
    }
  });
  // On comment deleted
  socket.on('cmt_del', req => {
    io.sockets.in(req.pollId).emit('cmt_del', req.cmtId);
  });
  // On like poll
  socket.on('cmt_like', req => {
    io.sockets
      .in(req.pollId)
      .emit('cmt_like', { cmtId: req.cmtId, likeCnt: req.likeCnt });
    if (req.type === 0) {
      return;
    }
    var action = (req.type === 1) ? 'liked' : 'disliked';
    var notif = new Notif({
      from: req.from,
      to: req.to,
      content: 'has ' + action + ' your comment on',
      poll: req.pollId
    });
    notif.save().then(notif => {
      var socketIds = _.where(global.socketUsers, { user: req.to });
      socketIds.forEach(item => {
        io.sockets.connected[item.socket].emit('notifs', notif._id);
      });
    });
  });

  // On delete poll
  socket.on('opts_update', req => {
    io.sockets.in(req.pollId).emit('opts_update');
  });
  // On delete poll
  socket.on('opts_request', req => {
    console.log('Has option request: ', req);
    io.sockets.in(req.pollId).emit('opts_request');
  });

  // io.sockets.connected[socket.id].emit('comment_result', { success: true });
};
<commit_msg>Commited from lenh at Thu, Jul 13, 2017 11:34:26 AM<commit_after>'use strict';

var path = require('path'),
  mongoose = require('mongoose'),
  Poll = mongoose.model('Poll'),
  Opt = mongoose.model('Opt'),
  Cmt = mongoose.model('Cmt'),
  Vote = mongoose.model('Vote'),
  Voteopt = mongoose.model('Voteopt'),
  Polltag = mongoose.model('Polltag'),
  Polluser = mongoose.model('Polluser'),
  Notif = mongoose.model('Notif'),
  Like = mongoose.model('Like'),
  errorHandler = require(path.resolve(
    './modules/core/server/controllers/errors.server.controller'
  )),
  _ = require('underscore');

// Create the chat configuration
module.exports = function (io, socket) {
  // On subscribe
  socket.on('subscribe_poll', req => {
    console.log('Has user subcribe poll');
    socket.join(req.pollId);
  });
  socket.on('subscribe_public', req => {
    socket.join('public');
  });
  // On unsubscribe
  socket.on('unsubscribe_poll', req => {
    socket.leave(req.pollId);
  });
  // On unsubscribe
  socket.on('unsubscribe_public', req => {
    socket.leave('public');
  });

  // On like poll
  socket.on('poll_like', req => {
    io.sockets.in(req.pollId).emit('poll_like', req.report);
    if (req.type === 0) {
      return;
    }
    // Create notifis
    var action = (req.type === 1) ? 'liked' : 'disliked';
    var notif = new Notif({
      from: req.from,
      to: req.to,
      content: 'has ' + action + ' your poll ',
      poll: req.pollId
    });
    notif.save().then(notif => {
      var socketIds = _.where(global.socketUsers, { user: req.to });
      socketIds.forEach(item => {
        io.sockets.connected[item.socket].emit('notifs', notif._id);
      });
    });
  });
  // On vote poll
  socket.on('poll_vote', req => {
    io.sockets.in(req.pollId).emit('poll_vote');
  });
  // On delete poll
  socket.on('poll_delete', req => {
    io.sockets.in(req.pollId).emit('poll_delete');
  });
  // On delete poll
  socket.on('poll_update', req => {
    io.sockets.in(req.pollId).emit('poll_update');
  });
  // On delete poll
  socket.on('poll_create', req => {
    io.sockets.in('public').emit('poll_create');
  });

  // On comment added
  socket.on('cmt_add', req => {
    io.sockets.in(req.pollId).emit('cmt_add', req.cmtId);
    if (req.to) {
      var notif = new Notif({
        from: req.from,
        to: req.to,
        content: 'has replied your comment on',
        poll: req.pollId
      });
      notif.save().then(notif => {
        var socketIds = _.where(global.socketUsers, { user: req.to });
        socketIds.forEach(item => {
          io.sockets.connected[item.socket].emit('notifs', notif._id);
        });
      });
    } else {
      // Tìm toàn bộ các member đang theo dõi poll
      Polluser.find({ poll: req.pollId, following: true }).then(
        pollusers => {
          var notif;
          // Tạo notif cho toàn bộ các member đang theo dõi
          pollusers.forEach((polluser, index) => {
            if (polluser.user.toString() !== req.from.toString()) {
              notif = new Notif({
                from: req.from,
                to: polluser.user,
                content: 'has posted a comment on',
                poll: req.pollId
              });
              notif.save().then(
                _notif => {
                  var socketIds = _.where(global.socketUsers, {
                    user: polluser.user.toString()
                  });
                  socketIds.forEach(item => {
                    io.sockets.connected[item.socket].emit(
                      'notifs',
                      _notif._id
                    );
                  });
                },
                err => {
                  console.log('Has error when save notif comment');
                }
              );
            }
          });
        },
        err => {
          console.log('Has error when get user in poll for comment');
        }
      );
    }
  });
  // On comment deleted
  socket.on('cmt_del', req => {
    io.sockets.in(req.pollId).emit('cmt_del', req.cmtId);
  });
  // On like poll
  socket.on('cmt_like', req => {
    io.sockets
      .in(req.pollId)
      .emit('cmt_like', { cmtId: req.cmtId, likeCnt: req.likeCnt });
    if (req.type === 0) {
      return;
    }
    var action = (req.type === 1) ? 'liked' : 'disliked';
    var notif = new Notif({
      from: req.from,
      to: req.to,
      content: 'has ' + action + ' your comment on',
      poll: req.pollId
    });
    notif.save().then(notif => {
      var socketIds = _.where(global.socketUsers, { user: req.to });
      socketIds.forEach(item => {
        io.sockets.connected[item.socket].emit('notifs', notif._id);
      });
    });
  });

  // On delete poll
  socket.on('opts_update', req => {
    io.sockets.in(req.pollId).emit('opts_update');
  });
  // On delete poll
  socket.on('opts_request', req => {
    console.log('Has option request: ', req);
    io.sockets.in(req.pollId).emit('opts_request');
  });

  // io.sockets.connected[socket.id].emit('comment_result', { success: true });
};
<|endoftext|>


<commit_before>/*
 * This file is part of the YNLOFramework package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

YnloFramework.Debugger = {
    lastAjaxRequest: null,
    lastDebugTokenLink: null,
    init: function () {
        if (!YnloFramework.debug) {
            return;
        }
        $(document).on('ajaxStart', function (event, xhr) {
            if ($('.ynlo-debugger-error').length) {
                $('.ynlo-debugger-error').remove();
            }
        });

        $(document).on('ajaxError pjax:error', function (event, xhr) {
            YnloFramework.Debugger.showAjaxError(xhr);
        });
    },
    showAjaxError: function (xhr) {
        if (xhr.statusText == 'abort' || xhr.statusText == 'canceled' || xhr.status == 403) {
            return;
        }

        if ($('.ynlo-debugger-error').length) {
            $('.ynlo-debugger-error').remove();
        }

        var audio = new Audio('/bundles/ynloframework/media/error.mp3');
        audio.play();

        var element = $('

');
        $('body').append(element);
        element.html('(' + xhr.status + ') ' + xhr.statusText);
        element.show();
        element.append('[RESPONSE]');

        YnloFramework.error('Error Code: ' + xhr.status + ', Error: ' + xhr.statusText);

        YnloFramework.Debugger.lastAjaxRequest = xhr;
        if (xhr.getResponseHeader('X-Debug-Token-Link')) {
            YnloFramework.Debugger.lastDebugTokenLink = xhr.getResponseHeader('X-Debug-Token-Link');
            element.append('[PROFILE]');
        }
    },
    showLastRequest: function (profile) {
        if ($('.ynlo-debugger-error-preview').length) {
            $('.ynlo-debugger-error-preview').remove();
        }
        var element = $('
[ CLOSE ]
');
        $('body').append(element);
        var iframe = element.find('iframe');
        if (profile) {
            iframe.prop('src', YnloFramework.Debugger.lastDebugTokenLink + '?panel=exception');
        } else {
            iframe.prop('srcdoc', YnloFramework.Debugger.lastAjaxRequest.responseText);
        }
        element.show();
    }
};<commit_msg>clear debugger on pjax start<commit_after>/*
 * This file is part of the YNLOFramework package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

YnloFramework.Debugger = {
    lastAjaxRequest: null,
    lastDebugTokenLink: null,
    init: function () {
        if (!YnloFramework.debug) {
            return;
        }
        $(document).on('ajaxStart pjax:start', function (event, xhr) {
            if ($('.ynlo-debugger-error').length) {
                $('.ynlo-debugger-error').remove();
            }
        });

        $(document).on('ajaxError pjax:error', function (event, xhr) {
            YnloFramework.Debugger.showAjaxError(xhr);
        });
    },
    showAjaxError: function (xhr) {
        if (xhr.statusText == 'abort' || xhr.statusText == 'canceled' || xhr.status == 403) {
            return;
        }

        if ($('.ynlo-debugger-error').length) {
            $('.ynlo-debugger-error').remove();
        }

        var audio = new Audio('/bundles/ynloframework/media/error.mp3');
        audio.play();

        var element = $('

');
        $('body').append(element);
        element.html('(' + xhr.status + ') ' + xhr.statusText);
        element.show();
        element.append('[RESPONSE]');

        YnloFramework.error('Error Code: ' + xhr.status + ', Error: ' + xhr.statusText);

        YnloFramework.Debugger.lastAjaxRequest = xhr;
        if (xhr.getResponseHeader('X-Debug-Token-Link')) {
            YnloFramework.Debugger.lastDebugTokenLink = xhr.getResponseHeader('X-Debug-Token-Link');
            element.append('[PROFILE]');
        }
    },
    showLastRequest: function (profile) {
        if ($('.ynlo-debugger-error-preview').length) {
            $('.ynlo-debugger-error-preview').remove();
        }
        var element = $('
[ CLOSE ]
');
        $('body').append(element);
        var iframe = element.find('iframe');
        if (profile) {
            iframe.prop('src', YnloFramework.Debugger.lastDebugTokenLink + '?panel=exception');
        } else {
            iframe.prop('srcdoc', YnloFramework.Debugger.lastAjaxRequest.responseText);
        }
        element.show();
    }
};<|endoftext|>


<commit_before>/**
 * # Like Button
 *
 * Allow users to `like` an object. Likes are not connected to facebook or any other network
 * You can use this as "favorite", "starred", "want"... or of course "like".
 *
 * ## Examples
 *
 *

 *

 *

 *
 * ## Options
 *
 * - `provider`: Optional, One or more providers to log users in.
 *   If none specified, will show all configured providers for the app.
 *
 * ## Template
 *
 * - `login_button`: Show login buttons if the user isn't logged, logout button if he is.
 *
 */

 define({
  type: "Hull",

  templates: ["like_button"],

  working: false,

  initialize: function() {
    if (this.options.liked) {
      this.isLiked = (this.options.liked == true);
    }
  },

  datasources: {
    liked: "me/liked",
  },

  beforeRender: function(data) {
    var likedIds = _.map(data.liked,function(l){return l.liked.id});

    // var likedIds = _.pluck(data.liked, 'id');
    if (!data.me || !data.me.id) {
      this.isLiked = undefined;
    } else if (typeof this.isLiked !== 'boolean') {
      var target=this.id;
      switch (target){
        case 'app' :
          target = data.app.id;
          break;
        case 'me' :
          target = data.me.id;
          break;
        case 'org' :
          target = data.org.id;
          break;
      }
      this.isLiked = _.include(likedIds, target);
    }
    data.likesCount = data.likesCount || this.options.likesCount;
    data.isLiked = this.isLiked;
    return data;
  },

  act: function(verb) {
    if (this.working) {
      return;
    }
    this.working = true;
    var method = verb === 'unlike' ? 'delete' : 'post';
    this.api('hull/' + this.id + '/likes', method, function(count) {
      this.working    = false;
      this.isLiked    = !this.isLiked;
      this.likesCount = count
      this.render('like_button', { isLiked: this.isLiked, likesCount: this.likesCount });
    }.bind(this));
  },

  actions: {
    like: function() {
      this.act('like');
    },
    unlike: function() {
      this.act('unlike');
    }
  }

});
<commit_msg>Better but still not working<commit_after>/**
 * # Like Button
 *
 * Allow users to `like` an object. Likes are not connected to facebook or any other network
 * You can use this as "favorite", "starred", "want"... or of course "like".
 *
 * ## Examples
 *
 *

 *

 *

 *
 * ## Options
 *
 * - `provider`: Optional, One or more providers to log users in.
 *   If none specified, will show all configured providers for the app.
 *
 * ## Template
 *
 * - `login_button`: Show login buttons if the user isn't logged, logout button if he is.
 *
 */

 define({
  type: "Hull",

  templates: ["like_button"],

  working: false,

  initialize: function() {
    if (this.options.liked) {
      this.isLiked = (this.options.liked == true);
    }
  },

  datasources: {
    liked: "me/liked",
  },

  beforeRender: function(data) {
    var likedIds = _.map(data.liked,function(l){return l.liked.id});

    // var likedIds = _.pluck(data.liked, 'id');
    if (!data.me || !data.me.id) {
      this.isLiked = undefined;
    } else if (typeof this.isLiked !== 'boolean') {
      var target=this.id;
      switch (target){
        case 'app' :
          this.id = data.app.id;
          break;
        case 'me' :
          this.id = data.me.id;
          break;
        case 'org' :
          this.id = data.org.id;
          break;
      }
      this.isLiked = _.include(likedIds, this.id);
    }
    data.likesCount = this.likesCount || this.options.likesCount;
    data.isLiked = this.isLiked;
    return data;
  },

  act: function(verb) {
    if (this.working) {
      return;
    }
    this.working = true;
    var method = verb === 'unlike' ? 'delete' : 'post';
    this.isLiked    = !this.isLiked;
    this.api('hull/' + this.id + '/likes', method, function(count) {
      this.working    = false;
      this.likesCount = count
      this.render('like_button', { isLiked: this.isLiked, likesCount: this.likesCount });
    }.bind(this)).fail(function(){
      this.isLiked = !this.isLiked;
    });
  },

  actions: {
    like: function() {
      this.act('like');
    },
    unlike: function() {
      this.act('unlike');
    }
  }

});
<|endoftext|>


<commit_before>import React, { Component } from 'react'; // eslint-disable-line
import PropTypes from 'prop-types';
import {
  StyleSheet,
  Image,
  Animated,
  Dimensions,
  TouchableOpacity,
  LayoutAnimation,
  Platform
} from 'react-native';

import FloatingActionItem from './FloatingActionItem';

import { getTouchableComponent, getRippleProps } from './utils/touchable';

const DEVICE_WIDTH = Dimensions.get('window').width;
const ACTION_BUTTON_SIZE = 56;

class FloatingAction extends Component {
  constructor(props) {
    super(props);

    this.state = {
      active: false,
      visible: props.visible
    };

    this.animation = new Animated.Value(0);
    this.actionsAnimation = new Animated.Value(0);
    this.visibleAnimation = new Animated.Value(props.visible ? 0 : 1);
    /*
     * this animation will fix an error on ReactNative (Android) where
     * interpolations with 0 and 1 don't work as expected.
     */
    this.fadeAnimation = new Animated.Value(props.visible ? 1 : 0);
  }

  componentDidMount() {
    const { openOnMount } = this.props;

    if (openOnMount) {
      this.animateButton();
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.visible !== this.props.visible) {
      if (nextProps.visible) {
        Animated.parallel([
          Animated.spring(this.visibleAnimation, { toValue: 0 }),
          Animated.spring(this.fadeAnimation, { toValue: 1 })
        ]).start();
      } if (!nextProps.visible) {
        Animated.parallel([
          Animated.spring(this.visibleAnimation, { toValue: 1 }),
          Animated.spring(this.fadeAnimation, { toValue: 0 })
        ]).start();
      }
    }
  }

  getIcon = () => {
    const { actions, floatingIcon, overrideWithAction } = this.props;

    if (overrideWithAction) {
      const { icon } = actions[0];

      if (React.isValidElement(icon)) {
        return icon;
      }

      return <Image style={styles.buttonIcon} source={icon} />;
    }

    if (floatingIcon) {
      if (React.isValidElement(floatingIcon)) {
        return floatingIcon;
      }

      return <Image style={styles.buttonIcon} source={floatingIcon} />;
    }

    return <Image style={styles.buttonIcon} source={require('../images/add.png')} />;
  };

  handlePressItem = (itemName) => {
    const { onPressItem } = this.props;

    if (onPressItem) {
      onPressItem(itemName);
    }

    this.reset();
  };

  reset = () => {
    Animated.spring(this.animation, { toValue: 0 }).start();
    Animated.spring(this.actionsAnimation, { toValue: 0 }).start();

    this.setState({
      active: false
    });
  };

  animateButton = () => {
    const {
      overrideWithAction,
      actions,
      floatingIcon,
      onPressMain
    } = this.props;
    const { active } = this.state;

    if (overrideWithAction) {
      this.handlePressItem(actions[0].name);

      return;
    }

    if (onPressMain) {
      onPressMain(!active);
    }

    if (!active) {
      if (!floatingIcon) {
        Animated.spring(this.animation, { toValue: 1 }).start();
      }

      Animated.spring(this.actionsAnimation, { toValue: 1 }).start();

      // only execute it for the background to prevent extra calls
      LayoutAnimation.configureNext({
        duration: 180,
        create: {
          type: LayoutAnimation.Types.easeInEaseOut,
          property: LayoutAnimation.Properties.opacity
        }
      });

      this.setState({
        active: true
      });
    } else {
      this.reset();
    }
  };

  renderMainButton() {
    const {
      // @deprecated in favor of "color"
      buttonColor, // eslint-disable-line
      color,
      position,
      overrideWithAction,
      distanceToEdge
    } = this.props;

    if (buttonColor) {
      console.warn('FloatingAction: "buttonColor" property was deprecated. Please use "color"');
    }

    const mainButtonColor = buttonColor || color;

    const animatedVisibleView = {
      opacity: this.fadeAnimation,
      transform: [{
        rotate: this.visibleAnimation.interpolate({
          inputRange: [0, 1],
          outputRange: ['0deg', '90deg']
        })
      }, {
        scale: this.visibleAnimation.interpolate({
          inputRange: [0, 1],
          outputRange: [1, 0]
        })
      }]
    };

    let animatedViewStyle = {
      transform: [{
        rotate: this.animation.interpolate({
          inputRange: [0, 1],
          outputRange: ['0deg', '45deg']
        })
      }]
    };

    if (overrideWithAction) {
      animatedViewStyle = {};
    }

    const Touchable = getTouchableComponent();
    const propStyles = { backgroundColor: mainButtonColor, bottom: distanceToEdge };
    if (['left', 'right'].indexOf(position) > -1) {
      propStyles[position] = distanceToEdge;
    }

    return (
      <Animated.View
        style={[
          styles.buttonContainer,
          styles[`${position}Button`],
          propStyles,
          animatedVisibleView
        ]}
      >
        <Touchable
          {...getRippleProps(mainButtonColor)}
          style={styles.button}
          activeOpacity={0.85}
          onPress={this.animateButton}
        >
          <Animated.View style={[styles.buttonTextContainer, animatedViewStyle]}>
            {this.getIcon()}
          </Animated.View>
        </Touchable>
      </Animated.View>
    );
  }

  renderActions() {
    const {
      actions,
      position,
      overrideWithAction,
      distanceToEdge,
      actionsPaddingTopBottom
    } = this.props;
    const { active } = this.state;

    if (overrideWithAction) {
      return null;
    }

    const animatedActionsStyle = {
      opacity: this.actionsAnimation.interpolate({
        inputRange: [0, 1],
        outputRange: [0, 1]
      })
    };

    const actionsStyles = [styles.actions, styles[`${position}Actions`], animatedActionsStyle, {
      bottom: ACTION_BUTTON_SIZE + distanceToEdge + actionsPaddingTopBottom
    }];

    if (active) {
      actionsStyles.push(styles[`${position}ActionsVisible`]);
    }

    const sortedActions = actions.sort((a, b) => a.position - b.position);

    return (
      <Animated.View style={actionsStyles} pointerEvents="box-none">
        {
          sortedActions.map((action) => {
            const textColor = action.textColor || action.actionsTextColor;
            const textBackground = action.textBackground || action.actionsTextBackground;

            return (
              <FloatingActionItem
                paddingTopBottom={actionsPaddingTopBottom}
                distanceToEdge={distanceToEdge}
                key={action.name}
                textColor={textColor}
                textBackground={textBackground}
                {...action}
                position={position}
                active={active}
                onPress={this.handlePressItem}
              />
            );
          })
        }
      </Animated.View>
    );
  }

  renderTappableBackground() {
    const { overlayColor } = this.props;

    // TouchableOpacity don't require a child
    return (
      <TouchableOpacity
        activeOpacity={1}
        style={[styles.overlay, { backgroundColor: overlayColor }]}
        onPress={this.reset}
      />
    );
  }

  render() {
    const { active } = this.state;
    const { showBackground } = this.props;

    return (
      <Animated.View
        pointerEvents="box-none"
        style={[styles.overlay, { backgroundColor: 'transparent' }]}
      >
        {
          (active && showBackground) &&
            this.renderTappableBackground()
        }
        {
          this.renderActions()
        }
        {
          this.renderMainButton()
        }
      </Animated.View>
    );
  }
}

FloatingAction.propTypes = {
  actions: PropTypes.arrayOf(PropTypes.shape({
    color: PropTypes.string,
    icon: PropTypes.any.isRequired,
    name: PropTypes.string.isRequired,
    text: PropTypes.string,
    textBackground: PropTypes.string,
    textColor: PropTypes.string
  })),
  color: PropTypes.string,
  distanceToEdge: PropTypes.number,
  visible: PropTypes.bool,
  overlayColor: PropTypes.string,
  position: PropTypes.oneOf(['right', 'left', 'center']),
  overrideWithAction: PropTypes.bool, // replace mainAction with first action from actions
  floatingIcon: PropTypes.any,
  showBackground: PropTypes.bool,
  openOnMount: PropTypes.bool,
  actionsPaddingTopBottom: PropTypes.number,
  onPressItem: PropTypes.func,
  onPressMain: PropTypes.func
};

FloatingAction.defaultProps = {
  actionsPaddingTopBottom: 8,
  overrideWithAction: false,
  visible: true,
  color: '#1253bc',
  overlayColor: 'rgba(68, 68, 68, 0.6)',
  position: 'right',
  distanceToEdge: 30,
  openOnMount: false,
  showBackground: true
};

const styles = StyleSheet.create({
  actions: {
    position: 'absolute',
    bottom: 85,
    zIndex: 10
  },
  rightActions: {
    alignItems: 'flex-end',
    right: -1000 // this magic number will make always disspear the text from screen
  },
  leftActions: {
    alignItems: 'flex-start',
    left: -1000 // this magic number will make always disspear the text from screen
  },
  centerActions: {
    left: -1000
  },
  rightActionsVisible: {
    right: 0
  },
  leftActionsVisible: {
    left: 0
  },
  centerActionsVisible: {
    left: (DEVICE_WIDTH / 2) - 30
  },
  overlay: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
    top: 0,
    elevation: 0,
    zIndex: 0
  },
  buttonContainer: {
    overflow: Platform.OS === 'ios' ? 'visible' : 'hidden',
    zIndex: 2,
    width: ACTION_BUTTON_SIZE,
    height: ACTION_BUTTON_SIZE,
    borderRadius: 28,
    alignItems: 'center',
    justifyContent: 'center',
    shadowOpacity: 0.35,
    shadowOffset: {
      width: 0,
      height: 5
    },
    shadowColor: '#000000',
    shadowRadius: 3,
    elevation: 5,
    position: 'absolute'
  },
  button: {
    zIndex: 3,
    width: ACTION_BUTTON_SIZE,
    height: ACTION_BUTTON_SIZE,
    borderRadius: 28,
    alignItems: 'center',
    justifyContent: 'center'
  },
  rightButton: {},
  leftButton: {},
  centerButton: {
    left: (DEVICE_WIDTH / 2) - 28
  },
  buttonTextContainer: {
    borderRadius: 28,
    width: ACTION_BUTTON_SIZE,
    height: ACTION_BUTTON_SIZE,
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  buttonIcon: {
    resizeMode: 'contain'
  }
});

export default FloatingAction;
<commit_msg>Fix floatingIcon not show when using Network image<commit_after>import React, { Component } from 'react'; // eslint-disable-line
import PropTypes from 'prop-types';
import {
  StyleSheet,
  Image,
  Animated,
  Dimensions,
  TouchableOpacity,
  LayoutAnimation,
  Platform
} from 'react-native';

import FloatingActionItem from './FloatingActionItem';

import { getTouchableComponent, getRippleProps } from './utils/touchable';

const DEVICE_WIDTH = Dimensions.get('window').width;
const ACTION_BUTTON_SIZE = 56;

class FloatingAction extends Component {
  constructor(props) {
    super(props);

    this.state = {
      active: false,
      visible: props.visible
    };

    this.animation = new Animated.Value(0);
    this.actionsAnimation = new Animated.Value(0);
    this.visibleAnimation = new Animated.Value(props.visible ? 0 : 1);
    /*
     * this animation will fix an error on ReactNative (Android) where
     * interpolations with 0 and 1 don't work as expected.
     */
    this.fadeAnimation = new Animated.Value(props.visible ? 1 : 0);
  }

  componentDidMount() {
    const { openOnMount } = this.props;

    if (openOnMount) {
      this.animateButton();
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.visible !== this.props.visible) {
      if (nextProps.visible) {
        Animated.parallel([
          Animated.spring(this.visibleAnimation, { toValue: 0 }),
          Animated.spring(this.fadeAnimation, { toValue: 1 })
        ]).start();
      } if (!nextProps.visible) {
        Animated.parallel([
          Animated.spring(this.visibleAnimation, { toValue: 1 }),
          Animated.spring(this.fadeAnimation, { toValue: 0 })
        ]).start();
      }
    }
  }

  getIcon = () => {
    const { actions, floatingIcon, overrideWithAction , iconWidth , iconHeight } = this.props;

    if (overrideWithAction) {
      const { icon } = actions[0];

      if (React.isValidElement(icon)) {
        return icon;
      }
      return <Image style={{width:iconWidth,height:iconHeight}} source={icon} />;
    }

    if (floatingIcon) {
      if (React.isValidElement(floatingIcon)) {
        return floatingIcon;
      }

      return <Image style={{width:iconWidth,height:iconHeight}} source={floatingIcon} />;
    }

    return <Image style={{width:iconWidth,height:iconHeight}} source={require('../images/add.png')} />;
  };

  handlePressItem = (itemName) => {
    const { onPressItem } = this.props;

    if (onPressItem) {
      onPressItem(itemName);
    }

    this.reset();
  };

  reset = () => {
    Animated.spring(this.animation, { toValue: 0 }).start();
    Animated.spring(this.actionsAnimation, { toValue: 0 }).start();

    this.setState({
      active: false
    });
  };

  animateButton = () => {
    const {
      overrideWithAction,
      actions,
      floatingIcon,
      onPressMain
    } = this.props;
    const { active } = this.state;

    if (overrideWithAction) {
      this.handlePressItem(actions[0].name);

      return;
    }

    if (onPressMain) {
      onPressMain(!active);
    }

    if (!active) {
      if (!floatingIcon) {
        Animated.spring(this.animation, { toValue: 1 }).start();
      }

      Animated.spring(this.actionsAnimation, { toValue: 1 }).start();

      // only execute it for the background to prevent extra calls
      LayoutAnimation.configureNext({
        duration: 180,
        create: {
          type: LayoutAnimation.Types.easeInEaseOut,
          property: LayoutAnimation.Properties.opacity
        }
      });

      this.setState({
        active: true
      });
    } else {
      this.reset();
    }
  };

  renderMainButton() {
    const {
      // @deprecated in favor of "color"
      buttonColor, // eslint-disable-line
      color,
      position,
      overrideWithAction,
      distanceToEdge
    } = this.props;

    if (buttonColor) {
      console.warn('FloatingAction: "buttonColor" property was deprecated. Please use "color"');
    }

    const mainButtonColor = buttonColor || color;

    const animatedVisibleView = {
      opacity: this.fadeAnimation,
      transform: [{
        rotate: this.visibleAnimation.interpolate({
          inputRange: [0, 1],
          outputRange: ['0deg', '90deg']
        })
      }, {
        scale: this.visibleAnimation.interpolate({
          inputRange: [0, 1],
          outputRange: [1, 0]
        })
      }]
    };

    let animatedViewStyle = {
      transform: [{
        rotate: this.animation.interpolate({
          inputRange: [0, 1],
          outputRange: ['0deg', '45deg']
        })
      }]
    };

    if (overrideWithAction) {
      animatedViewStyle = {};
    }

    const Touchable = getTouchableComponent();
    const propStyles = { backgroundColor: mainButtonColor, bottom: distanceToEdge };
    if (['left', 'right'].indexOf(position) > -1) {
      propStyles[position] = distanceToEdge;
    }

    return (
      <Animated.View
        style={[
          styles.buttonContainer,
          styles[`${position}Button`],
          propStyles,
          animatedVisibleView
        ]}
      >
        <Touchable
          {...getRippleProps(mainButtonColor)}
          style={styles.button}
          activeOpacity={0.85}
          onPress={this.animateButton}
        >
          <Animated.View style={[styles.buttonTextContainer, animatedViewStyle]}>
            {this.getIcon()}
          </Animated.View>
        </Touchable>
      </Animated.View>
    );
  }

  renderActions() {
    const {
      actions,
      position,
      overrideWithAction,
      distanceToEdge,
      actionsPaddingTopBottom
    } = this.props;
    const { active } = this.state;

    if (overrideWithAction) {
      return null;
    }

    const animatedActionsStyle = {
      opacity: this.actionsAnimation.interpolate({
        inputRange: [0, 1],
        outputRange: [0, 1]
      })
    };

    const actionsStyles = [styles.actions, styles[`${position}Actions`], animatedActionsStyle, {
      bottom: ACTION_BUTTON_SIZE + distanceToEdge + actionsPaddingTopBottom
    }];

    if (active) {
      actionsStyles.push(styles[`${position}ActionsVisible`]);
    }

    const sortedActions = actions.sort((a, b) => a.position - b.position);

    return (
      <Animated.View style={actionsStyles} pointerEvents="box-none">
        {
          sortedActions.map((action) => {
            const textColor = action.textColor || action.actionsTextColor;
            const textBackground = action.textBackground || action.actionsTextBackground;

            return (
              <FloatingActionItem
                paddingTopBottom={actionsPaddingTopBottom}
                distanceToEdge={distanceToEdge}
                key={action.name}
                textColor={textColor}
                textBackground={textBackground}
                {...action}
                position={position}
                active={active}
                onPress={this.handlePressItem}
              />
            );
          })
        }
      </Animated.View>
    );
  }

  renderTappableBackground() {
    const { overlayColor } = this.props;

    // TouchableOpacity don't require a child
    return (
      <TouchableOpacity
        activeOpacity={1}
        style={[styles.overlay, { backgroundColor: overlayColor }]}
        onPress={this.reset}
      />
    );
  }

  render() {
    const { active } = this.state;
    const { showBackground } = this.props;

    return (
      <Animated.View
        pointerEvents="box-none"
        style={[styles.overlay, { backgroundColor: 'transparent' }]}
      >
        {
          (active && showBackground) &&
            this.renderTappableBackground()
        }
        {
          this.renderActions()
        }
        {
          this.renderMainButton()
        }
      </Animated.View>
    );
  }
}

FloatingAction.propTypes = {
  actions: PropTypes.arrayOf(PropTypes.shape({
    color: PropTypes.string,
    icon: PropTypes.any.isRequired,
    name: PropTypes.string.isRequired,
    text: PropTypes.string,
    textBackground: PropTypes.string,
    textColor: PropTypes.string
  })),
  color: PropTypes.string,
  distanceToEdge: PropTypes.number,
  visible: PropTypes.bool,
  overlayColor: PropTypes.string,
  position: PropTypes.oneOf(['right', 'left', 'center']),
  overrideWithAction: PropTypes.bool, // replace mainAction with first action from actions
  floatingIcon: PropTypes.any,
  showBackground: PropTypes.bool,
  openOnMount: PropTypes.bool,
  actionsPaddingTopBottom: PropTypes.number,
  onPressItem: PropTypes.func,
  onPressMain: PropTypes.func,
  iconHeight : PropTypes.number,
  iconWidth : PropTypes.number
};

FloatingAction.defaultProps = {
  actionsPaddingTopBottom: 8,
  overrideWithAction: false,
  visible: true,
  color: '#1253bc',
  overlayColor: 'rgba(68, 68, 68, 0.6)',
  position: 'right',
  distanceToEdge: 30,
  openOnMount: false,
  showBackground: true,
  iconHeight : 15,
  iconWidth : 15
};

const styles = StyleSheet.create({
  actions: {
    position: 'absolute',
    bottom: 85,
    zIndex: 10
  },
  rightActions: {
    alignItems: 'flex-end',
    right: -1000 // this magic number will make always disspear the text from screen
  },
  leftActions: {
    alignItems: 'flex-start',
    left: -1000 // this magic number will make always disspear the text from screen
  },
  centerActions: {
    left: -1000
  },
  rightActionsVisible: {
    right: 0
  },
  leftActionsVisible: {
    left: 0
  },
  centerActionsVisible: {
    left: (DEVICE_WIDTH / 2) - 30
  },
  overlay: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
    top: 0,
    elevation: 0,
    zIndex: 0
  },
  buttonContainer: {
    overflow: Platform.OS === 'ios' ? 'visible' : 'hidden',
    zIndex: 2,
    width: ACTION_BUTTON_SIZE,
    height: ACTION_BUTTON_SIZE,
    borderRadius: 28,
    alignItems: 'center',
    justifyContent: 'center',
    shadowOpacity: 0.35,
    shadowOffset: {
      width: 0,
      height: 5
    },
    shadowColor: '#000000',
    shadowRadius: 3,
    elevation: 5,
    position: 'absolute'
  },
  button: {
    zIndex: 3,
    width: ACTION_BUTTON_SIZE,
    height: ACTION_BUTTON_SIZE,
    borderRadius: 28,
    alignItems: 'center',
    justifyContent: 'center'
  },
  rightButton: {},
  leftButton: {},
  centerButton: {
    left: (DEVICE_WIDTH / 2) - 28
  },
  buttonTextContainer: {
    borderRadius: 28,
    width: ACTION_BUTTON_SIZE,
    height: ACTION_BUTTON_SIZE,
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  }
});

export default FloatingAction;
<|endoftext|>


<commit_before>define([
    'uijet_dir/uijet',
    'api',
    'resources'
], function (uijet, api, resources) {

    /**
     * Utility lambdas for formatting template
     */
    var getUserAvatar = function () {
            return function (text, render) {
                return render(text).replace(/s=\d+/, 's=25');
            };
        },
        multiline = function (text) {
            return text.replace(/(\r?\n)/g, '
');
        },
        linesToBRs = function () {
            return function (text, render) {
                return multiline(render(text));
            };
        },
        formatDate = function (date) {
            return date &&
                    [date.getDate(), date.getMonth() + 1, date.getFullYear()].join('.');
        },
        parseCreatedOn = function () {
            return function (text, render) {
                var value = render(text),
                    date = value ? new Date(value) : value;
                return formatDate(date);
            };
        },
        new_comment_data = {
            discussion  : {
                id              : '',
                comment         : '',
                created_on      : '',
                user            : window.LOGGEDIN_USER,
                get_user_avatar : getUserAvatar,
                parse_date      : parseCreatedOn,
                lines_to_brs    : linesToBRs
            }
        },
        rescrollToBottom = function () {
            this.scroll().scrollTo(this.$element.children().last());
        };

    uijet.Resource('NewComment', uijet.Model(), {
        user: window.LOGGEDIN_USER.uuid
    });

    return [{
        type    : 'Button',
        config  : {
            element     : '#items_comments_close',
            dont_wake   : true,
            signals     : {
                pre_click   : function () {
                    uijet.Resource('ItemsListState').set('comments_item', null);
                    this.sleep();
                }
            },
            app_events  : {
                open_comments   : 'wake'
            }
        }
    }, {
        type    : 'Pane',
        config  : {
            element         : '#items_comments_container',
            mixins          : ['Scrolled'],
            adapters        : ['jqWheelScroll'],
            resource        : 'NewComment',
            dont_wake       : true,
            jqscroll_options: {
                exclude_padding : true
            },
            signals         : {
                post_init   : function () {
                    this.$description = this.$element.find('#item_description');
                }
            },
            data_events     : {
                'change:comment': function (model, comment) {
                    api.itemComments(this.resource.get('item_pk'), {
                        type    : 'POST',
                        data    : {
                            comment : resources._.escape(comment.trim()),
                            user    : model.get('user')
                        },
                        success : function (response) {
                            uijet.publish('comment_created', response);
                        },
                        error   : function (response) {
                            uijet.publish('comment_failed', response);
                        }
                    });
                }
            },
            app_events      : {
                open_comments                   : function ($selected) {
                    var item_id = $selected.attr('data-item'),
                        item = item_id ? uijet.Resource('LatestSheet').get(item_id) : null,
                        //TODO: for now there's no SheetComment model, needs to be implemented server-side
                        discussion = item && item.get('discussion'),
                        description = item ?
                                      // found an item
                                      item.get('description') :
                                      // if no item it's the sheet's description we need
                                      uijet.Resource('AllSheets').get(
                                          uijet.Resource('ItemsListState').get('sheet')
                                      ).get('description');

                    //TODO: delete this shit
                    this.$element[0].style.setProperty('padding-top', (uijet.utils.getOffsetOf($selected[0], uijet.$element[0]).y + 15) + 'px');
                    if ( description ) {
                        this.$element.removeClass('no_description');
                        this.$description.text(description);
                    }
                    else {
                        this.$element.addClass('no_description');
                    }

                    this.resource.set('item_pk', item_id);

                    this.wake({
                        discussion      : discussion,
                        get_user_avatar : getUserAvatar,
                        parse_date      : parseCreatedOn,
                        lines_to_brs    : linesToBRs
                    });
                },
                close_comments                  : 'sleep',
                'new_comment.line_added'        : rescrollToBottom,
                'new_comment.awake'             : rescrollToBottom,
                'new_comment.asleep'            : rescrollToBottom,
                'item_comments_list.rendered'   : 'scroll'
            }
        }
    }, {
        type    : 'List',
        config  : {
            element         : '#item_comments_list',
            mixins          : ['Templated', 'Translated'],
            adapters        : ['Spin'],
            dont_fetch      : true,
            spinner_options : {
                element     : function () {
                    return this.$new_comment.find('.item_comment_date');
                },
                lines       : 8,
                length      : 5,
                width       : 3,
                radius      : 3
            },
            signals         : {
                post_render : 'rendered'
            },
            app_events      : {
                'add_comment.clicked'       : function () {
                    this.$new_comment = this.$element.append(this.template(new_comment_data))
                        .children().last();
                    uijet._translate(this.$new_comment[0]);
                },
                'new_comment_cancel.clicked': function () {
                    if ( this.$new_comment ) {
                        this.$new_comment.remove();
                        delete this.$new_comment;
                    }
                },
                'new_comment_ok.clicked'    : 'spin',
                comment_created             : function (comment) {
                    if ( this.$new_comment ) {
                        this.$new_comment.find('.item_comment_text').html(multiline(comment.comment));
                        this.$new_comment.find('.item_comment_date').text(formatDate(new Date(comment.created_on)));
                        this.$new_comment.attr('data-id', comment.id);
                        this.$new_comment.removeClass('new_comment');
                        delete this.$new_comment;
                    }
                }
            }
        }
    }, {
        type    : 'Button',
        config  : {
            element     : '#add_comment',
            signals     : {
                pre_click   : function  () {
                    if ( ! uijet.Resource('NewComment').has('user') ) {
                        uijet.publish('login');
                        return false
                    }
                    else {
                        this.sleep();
                    }
                }
            },
            app_events  : {
                'new_comment_ok.clicked'    : 'wake',
                'new_comment_cancel.clicked': 'wake'
            }
        }
    }, {
        type    : 'Pane',
        config  : {
            element     : '#new_comment',
            resource    : 'NewComment',
            dont_wake   : true,
            signals     : {
                post_init       : function () {
                    var that = this;
                    this.$textarea = this.$element.find('textarea');
                    this.$textarea.on('keyup', function (e) {
                        if ( this.scrollHeight > this.clientHeight ) {
                            this.style.height = this.scrollHeight + 'px';
                            that.publish('line_added');
                        }
                    });
                },
                pre_wake        : function () {
                    this.$element.removeClass('hide');
                },
                post_appear     : function () {
                    this.$textarea.focus();
                    this.publish('awake');
                },
                post_disappear  : function () {
                    this.publish('asleep');
                },
                pre_sleep       : function () {
                    var textarea = this.$textarea[0];
                    textarea.value = '';
                    textarea.style.removeProperty('height');
                    this.$element.addClass('hide');
                }
            },
            data_events : {},
            app_events  : {
                'add_comment.clicked'       : 'wake',
                'new_comment_ok.clicked'    : function () {
                    this.resource.set('comment', this.$textarea.val());
                },
                comment_created             : function () {
                    this.resource.set('comment', '', { silent : true });
                    this.sleep();
                },
                'new_comment_cancel.clicked': 'sleep',
                open_comments               : 'sleep',
                close_comments              : 'sleep'
            }
        }
    }, {
        type    : 'Button',
        config  : {
            element     : '#new_comment_ok',
            signals     : {
                pre_click   : 'sleep'
            },
            app_events  : {
                'new_comment_cancel.clicked': 'sleep'
            }
        }
    }, {
        type    : 'Button',
        config  : {
            element     : '#new_comment_cancel',
            signals     : {
                pre_click   : 'sleep'
            },
            app_events  : {
                'new_comment_ok.clicked': 'sleep'
            }
        }
    }];
});
<commit_msg>Fixed comments' text serialization<commit_after>define([
    'uijet_dir/uijet',
    'api',
    'resources'
], function (uijet, api, resources) {

    /**
     * Utility lambdas for formatting template
     */
    var getUserAvatar = function () {
            return function (text, render) {
                return render(text).replace(/s=\d+/, 's=25');
            };
        },
        multiline = function (text) {
            return text.replace(/(\r?\n)/g, '
');
        },
        linesToBRs = function () {
            return function (text, render) {
                return multiline(render(text));
            };
        },
        formatDate = function (date) {
            return date &&
                    [date.getDate(), date.getMonth() + 1, date.getFullYear()].join('.');
        },
        parseCreatedOn = function () {
            return function (text, render) {
                var value = render(text),
                    date = value ? new Date(value) : value;
                return formatDate(date);
            };
        },
        new_comment_data = {
            discussion  : {
                id              : '',
                comment         : '',
                created_on      : '',
                user            : window.LOGGEDIN_USER,
                get_user_avatar : getUserAvatar,
                parse_date      : parseCreatedOn,
                lines_to_brs    : linesToBRs
            }
        },
        rescrollToBottom = function () {
            this.scroll().scrollTo(this.$element.children().last());
        };

    uijet.Resource('NewComment', uijet.Model(), {
        user: window.LOGGEDIN_USER.uuid
    });

    return [{
        type    : 'Button',
        config  : {
            element     : '#items_comments_close',
            dont_wake   : true,
            signals     : {
                pre_click   : function () {
                    uijet.Resource('ItemsListState').set('comments_item', null);
                    this.sleep();
                }
            },
            app_events  : {
                open_comments   : 'wake'
            }
        }
    }, {
        type    : 'Pane',
        config  : {
            element         : '#items_comments_container',
            mixins          : ['Scrolled'],
            adapters        : ['jqWheelScroll'],
            resource        : 'NewComment',
            dont_wake       : true,
            jqscroll_options: {
                exclude_padding : true
            },
            signals         : {
                post_init   : function () {
                    this.$description = this.$element.find('#item_description');
                }
            },
            data_events     : {
                'change:comment': function (model, comment) {
                    api.itemComments(this.resource.get('item_pk'), {
                        type    : 'POST',
                        data    : {
                            comment : encodeURIComponent(resources._.escape(comment.trim())),
                            user    : model.get('user')
                        },
                        success : function (response) {
                            uijet.publish('comment_created', response);
                        },
                        error   : function (response) {
                            uijet.publish('comment_failed', response);
                        }
                    });
                }
            },
            app_events      : {
                open_comments                   : function ($selected) {
                    var item_id = $selected.attr('data-item'),
                        item = item_id ? uijet.Resource('LatestSheet').get(item_id) : null,
                        //TODO: for now there's no SheetComment model, needs to be implemented server-side
                        discussion = item && item.get('discussion'),
                        description = item ?
                                      // found an item
                                      item.get('description') :
                                      // if no item it's the sheet's description we need
                                      uijet.Resource('AllSheets').get(
                                          uijet.Resource('ItemsListState').get('sheet')
                                      ).get('description');

                    //TODO: delete this shit
                    this.$element[0].style.setProperty('padding-top', (uijet.utils.getOffsetOf($selected[0], uijet.$element[0]).y + 15) + 'px');
                    if ( description ) {
                        this.$element.removeClass('no_description');
                        this.$description.text(description);
                    }
                    else {
                        this.$element.addClass('no_description');
                    }

                    this.resource.set('item_pk', item_id);

                    this.wake({
                        discussion      : discussion,
                        get_user_avatar : getUserAvatar,
                        parse_date      : parseCreatedOn,
                        lines_to_brs    : linesToBRs
                    });
                },
                close_comments                  : 'sleep',
                'new_comment.line_added'        : rescrollToBottom,
                'new_comment.awake'             : rescrollToBottom,
                'new_comment.asleep'            : rescrollToBottom,
                'item_comments_list.rendered'   : 'scroll'
            }
        }
    }, {
        type    : 'List',
        config  : {
            element         : '#item_comments_list',
            mixins          : ['Templated', 'Translated'],
            adapters        : ['Spin'],
            dont_fetch      : true,
            spinner_options : {
                element     : function () {
                    return this.$new_comment.find('.item_comment_date');
                },
                lines       : 8,
                length      : 5,
                width       : 3,
                radius      : 3
            },
            signals         : {
                post_render : 'rendered'
            },
            app_events      : {
                'add_comment.clicked'       : function () {
                    this.$new_comment = this.$element.append(this.template(new_comment_data))
                        .children().last();
                    uijet._translate(this.$new_comment[0]);
                },
                'new_comment_cancel.clicked': function () {
                    if ( this.$new_comment ) {
                        this.$new_comment.remove();
                        delete this.$new_comment;
                    }
                },
                'new_comment_ok.clicked'    : 'spin',
                comment_created             : function (comment) {
                    if ( this.$new_comment ) {
                        this.$new_comment.find('.item_comment_text').html(multiline(comment.comment));
                        this.$new_comment.find('.item_comment_date').text(formatDate(new Date(comment.created_on)));
                        this.$new_comment.attr('data-id', comment.id);
                        this.$new_comment.removeClass('new_comment');
                        delete this.$new_comment;
                    }
                }
            }
        }
    }, {
        type    : 'Button',
        config  : {
            element     : '#add_comment',
            signals     : {
                pre_click   : function  () {
                    if ( ! uijet.Resource('NewComment').has('user') ) {
                        uijet.publish('login');
                        return false
                    }
                    else {
                        this.sleep();
                    }
                }
            },
            app_events  : {
                'new_comment_ok.clicked'    : 'wake',
                'new_comment_cancel.clicked': 'wake'
            }
        }
    }, {
        type    : 'Pane',
        config  : {
            element     : '#new_comment',
            resource    : 'NewComment',
            dont_wake   : true,
            signals     : {
                post_init       : function () {
                    var that = this;
                    this.$textarea = this.$element.find('textarea');
                    this.$textarea.on('keyup', function (e) {
                        if ( this.scrollHeight > this.clientHeight ) {
                            this.style.height = this.scrollHeight + 'px';
                            that.publish('line_added');
                        }
                    });
                },
                pre_wake        : function () {
                    this.$element.removeClass('hide');
                },
                post_appear     : function () {
                    this.$textarea.focus();
                    this.publish('awake');
                },
                post_disappear  : function () {
                    this.publish('asleep');
                },
                pre_sleep       : function () {
                    var textarea = this.$textarea[0];
                    textarea.value = '';
                    textarea.style.removeProperty('height');
                    this.$element.addClass('hide');
                }
            },
            data_events : {},
            app_events  : {
                'add_comment.clicked'       : 'wake',
                'new_comment_ok.clicked'    : function () {
                    this.resource.set('comment', this.$textarea.val());
                },
                comment_created             : function () {
                    this.resource.set('comment', '', { silent : true });
                    this.sleep();
                },
                'new_comment_cancel.clicked': 'sleep',
                open_comments               : 'sleep',
                close_comments              : 'sleep'
            }
        }
    }, {
        type    : 'Button',
        config  : {
            element     : '#new_comment_ok',
            signals     : {
                pre_click   : 'sleep'
            },
            app_events  : {
                'new_comment_cancel.clicked': 'sleep'
            }
        }
    }, {
        type    : 'Button',
        config  : {
            element     : '#new_comment_cancel',
            signals     : {
                pre_click   : 'sleep'
            },
            app_events  : {
                'new_comment_ok.clicked': 'sleep'
            }
        }
    }];
});
<|endoftext|>


<commit_before>/**
 * Created by ryan on 17/05/16.
 */

var Logger = require('polyball/shared/Logger');
var _ = require('lodash');
var ArrayHelper = require('polyball/shared/utilities/ArrayHelper');
var IdGenerator = require('polyball/shared/utilities/IdGenerator');
var Player = require('polyball/shared/model/Player');
var Util = require('polyball/shared/utilities/Util');

/**
 * Initializes the PlayerContainer
 * @property {Physics.world} config.world
 * @constructor
 */
var PlayerContainer = function (config) {
    var IdGen = new IdGenerator();
    var world = config.world;

    /**
     * @type {Player[]}
     */
    var players = [];

    /**
     * Adds a player to the model.
     * @param {Object} config - A Player config.  See constructor.
     * @property {Number} [config.id] - Optional.  Should not be passed on the server, should always be passed on the client.
     * @return {Player} The new Player.
     */
    this.addPlayer = function (config) {
        var playerConfig = {
            id: config.id ? config.id : IdGen.nextID()
        };

        _.assign(playerConfig, config);

        var player = new Player(playerConfig);
        players.push(player);

        if (player.paddle != null) {
            world.add(player.paddle.body);
        }

        return player;
    };

    /**
     * @param {Number|Predicate} id - Either the ID of the Player, or a boolean returning callback that takes a Player.
     * @return {Player} The player from the model (undefined if not found).
     */
    this.getPlayer = function (id) {
        return ArrayHelper.findSingle(players, id);
    };

    /**
     * Get all players satisfying the predicate callback.
     * @param {Predicate} [predicate]  Callback to evaluate for each player.  (matches all if null.)
     * @returns {Player[]} All players matching the predicate. (may be empty.)
     */
    this.getPlayers = function (predicate) {
        return ArrayHelper.findAll(players, predicate);
    };

    /**
     * @param {Number|Predicate} id - Either the ID of the Player, or a boolean returning callback that takes a Player.
     * @returns {boolean} True iff the model has the player identified by id.
     */
    this.hasPlayer = function (id) {
        return this.getPlayer(id) != null;
    };

    /**
     * @returns {Number} The number of players in the model.
     */
    this.playerCount = function () {
        return players.length;
    };

    /**
     * Delete the identified player from the model.
     *
     * @param {Number} id
     */
    this.deletePlayer = function (id) {
        var player = ArrayHelper.removeByID(players, id);
        if (player != null && player.paddle != null){
            var paddle = player.paddle;
            world.remove(paddle.body);
        }
    };

    /**
     * This adds a paddle to the player given by id
     * SRS Requirement - 3.2.2.6 Paddle Setup
     * @param {Object} config
     * @property {number} config.playerID
     * @property {Object} config.paddleConfig
     * @returns {Paddle} The paddle added to the player.
     */
    this.addPaddleToPlayer = function (config){
        var player = this.getPlayer(config.playerID);

        if (player == null) {
            Logger.warn('Cannot find player id in model - cannot add paddle to player.');
            return null;
        }

        if (player.paddle != null) {
            Logger.warn('Cannot add paddle to player that already has a paddle.');
            return null;
        }

        var paddle = player.addPaddle(config.paddleConfig);
        world.add(paddle.body);

        return paddle;
    };

    /**
     * Returns a paddle that belongs to the player given by id
     * @param {Number} playerID
     * @returns {Paddle} - The player's paddle.  Undefined if the player doesn't exist or if the player doesn't have a paddle yet.
     */
    this.getPaddle = function (playerID) {
        var player = this.getPlayer(playerID);

        if (player == null) {
            return undefined;
        }

        return player.paddle;
    };

    /**
     * Gets the config object for the enclosed players collection
     * @returns {Object}
     */
    this.playersConfig = function () {
        if (players.length > 0){
            return Util.arrayToConfig(players);
        }
    };

};

module.exports = PlayerContainer;<commit_msg>Added some paddle deletion convenience methods<commit_after>/**
 * Created by ryan on 17/05/16.
 */

var Logger = require('polyball/shared/Logger');
var _ = require('lodash');
var ArrayHelper = require('polyball/shared/utilities/ArrayHelper');
var IdGenerator = require('polyball/shared/utilities/IdGenerator');
var Player = require('polyball/shared/model/Player');
var Util = require('polyball/shared/utilities/Util');

/**
 * Initializes the PlayerContainer
 * @property {Physics.world} config.world
 * @constructor
 */
var PlayerContainer = function (config) {
    var IdGen = new IdGenerator();
    var world = config.world;

    /**
     * @type {Player[]}
     */
    var players = [];

    /**
     * Adds a player to the model.
     * @param {Object} config - A Player config.  See constructor.
     * @property {Number} [config.id] - Optional.  Should not be passed on the server, should always be passed on the client.
     * @return {Player} The new Player.
     */
    this.addPlayer = function (config) {
        var playerConfig = {
            id: config.id ? config.id : IdGen.nextID()
        };

        _.assign(playerConfig, config);

        var player = new Player(playerConfig);
        players.push(player);

        if (player.paddle != null) {
            world.add(player.paddle.body);
        }

        return player;
    };

    /**
     * @param {Number|Predicate} id - Either the ID of the Player, or a boolean returning callback that takes a Player.
     * @return {Player} The player from the model (undefined if not found).
     */
    this.getPlayer = function (id) {
        return ArrayHelper.findSingle(players, id);
    };

    /**
     * Get all players satisfying the predicate callback.
     * @param {Predicate} [predicate]  Callback to evaluate for each player.  (matches all if null.)
     * @returns {Player[]} All players matching the predicate. (may be empty.)
     */
    this.getPlayers = function (predicate) {
        return ArrayHelper.findAll(players, predicate);
    };

    /**
     * @param {Number|Predicate} id - Either the ID of the Player, or a boolean returning callback that takes a Player.
     * @returns {boolean} True iff the model has the player identified by id.
     */
    this.hasPlayer = function (id) {
        return this.getPlayer(id) != null;
    };

    /**
     * @returns {Number} The number of players in the model.
     */
    this.playerCount = function () {
        return players.length;
    };

    /**
     * Delete the identified player from the model.
     *
     * @param {Number} id
     */
    this.deletePlayer = function (id) {
        var player = ArrayHelper.removeByID(players, id);
        if (player != null && player.paddle != null){
            var paddle = player.paddle;
            world.remove(paddle.body);
            player.paddle = null;
        }
    };

    /**
     * Delete the identified player from the model.
     * @param {Number} id
     */
    this.deletePaddle = function (playerID) {
        var player = ArrayHelper.findByID(players, playerID);
        if (player != null && player.paddle != null){
            var paddle = player.paddle;
            world.remove(paddle.body);
        }
    };

    /**
     * This adds a paddle to the player given by id
     * SRS Requirement - 3.2.2.6 Paddle Setup
     * @param {Object} config
     * @property {number} config.playerID
     * @property {Object} config.paddleConfig
     * @returns {Paddle} The paddle added to the player.
     */
    this.addPaddleToPlayer = function (config){
        var player = this.getPlayer(config.playerID);

        if (player == null) {
            Logger.warn('Cannot find player id in model - cannot add paddle to player.');
            return null;
        }

        if (player.paddle != null) {
            Logger.warn('Cannot add paddle to player that already has a paddle.');
            return null;
        }

        var paddle = player.addPaddle(config.paddleConfig);
        world.add(paddle.body);

        return paddle;
    };

    /**
     * Returns a paddle that belongs to the player given by id
     * @param {Number} playerID
     * @returns {Paddle} - The player's paddle.  Undefined if the player doesn't exist or if the player doesn't have a paddle yet.
     */
    this.getPaddle = function (playerID) {
        var player = this.getPlayer(playerID);

        if (player == null) {
            return undefined;
        }

        return player.paddle;
    };

    /**
     * A convenience method for resetting all player paddles
     */
    this.clearPaddles = function () {
        var playerIDs = _.map(players, function (player) { return player.id; });

        var me = this;
        playerIDs.forEach(function (id) {
            me.deletePaddle(id);
        });
    };

    /**
     * Gets the config object for the enclosed players collection
     * @returns {Object}
     */
    this.playersConfig = function () {
        if (players.length > 0){
            return Util.arrayToConfig(players);
        }
    };

};

module.exports = PlayerContainer;<|endoftext|>


<commit_before>function NWTLayoutManager() {
}

/**
 * Magically called when any link is found inside of
 * a div with a class of "nwt_event_sink"
 */
NWTLayoutManager.prototype.trapEvent = function(el) {

	var resource = el.get('href');

	nwt.socket.send(resource,{
		success: function(response) {
			el.ancestor('.nwt_layout').one('.main .inner').setContent(response.content);
		}
	});
};

nwt.layoutManager = new NWTLayoutManager();
<commit_msg>Implement class change.<commit_after>function NWTLayoutManager() {
}

/**
 * Magically called when any link is found inside of
 * a div with a class of "nwt_event_sink"
 */
NWTLayoutManager.prototype.trapEvent = function(el) {

	var resource = el.get('href'),
		layoutWrapper = el.ancestor('.nwt_layout');

	layoutWrapper.addClass('layout_' + resource.replace('/', '_'));

	nwt.socket.send(resource,{
		success: function(response) {
			layoutWrapper.one('.main .inner').setContent(response.content);
		}
	});
};

nwt.layoutManager = new NWTLayoutManager();
<|endoftext|>


<commit_before>var loaderUtils = require('loader-utils')
var assign = require('object-assign')
var parse = require('./parser')
var path = require('path')
var normalize = require('./normalize')
var genId = require('./gen-id')

// internal lib loaders
var selectorPath = normalize.lib('selector')
var templateLoaderPath = normalize.lib('template-loader')
var templateCompilerPath = normalize.lib('template-compiler')
var styleRewriterPath = normalize.lib('style-rewriter')

// dep loaders
var styleLoaderPath = normalize.dep('vue-style-loader')
var hotReloadAPIPath = normalize.dep('vue-hot-reload-api')

var hasBabel = true
try {
  require('babel-loader')
} catch (e) {
  hasBabel = false
}

var rewriterInjectRE = /\b(css(?:-loader)?(?:\?[^!]+)?)(?:!|$)/

var defaultLang = {
  template: 'html',
  styles: 'css',
  script: 'js'
}

module.exports = function (content) {
  this.cacheable()
  var isServer = this.options.target === 'node'
  var loaderContext = this
  var options = this.options.vue || {}
  var query = loaderUtils.parseQuery(this.query)
  var filePath = this.resourcePath
  var fileName = path.basename(filePath)
  var moduleId = 'data-v-' + genId(filePath)
  var styleRewriter = styleRewriterPath + '?id=' + moduleId

  var needCssSourceMap =
    this.sourceMap &&
    !this.minimize &&
    process.env.NODE_ENV !== 'production' &&
    options.cssSourceMap !== false

  var defaultLoaders = {
    html: templateCompilerPath + '?id=' + moduleId,
    css: styleLoaderPath + '!css-loader' + (needCssSourceMap ? '?sourceMap' : ''),
    js: hasBabel ? 'babel-loader' : ''
  }

  // check if there are custom loaders specified via
  // webpack config, otherwise use defaults
  var loaders = assign({}, defaultLoaders, options.loaders)

  function getRequire (type, part, index, scoped) {
    return 'require(' +
      getRequireString(type, part, index, scoped) +
    ')\n'
  }

  function getRequireString (type, part, index, scoped) {
    return loaderUtils.stringifyRequest(loaderContext,
      // disable all configuration loaders
      '!!' +
      // get loader string for pre-processors
      getLoaderString(type, part, scoped) +
      // select the corresponding part from the vue file
      getSelectorString(type, index || 0) +
      // the url to the actual vuefile
      filePath
    )
  }

  function getRequireForImport (type, impt, scoped) {
    return 'require(' +
      getRequireForImportString(type, impt, scoped) +
    ')\n'
  }

  function getRequireForImportString (type, impt, scoped) {
    return loaderUtils.stringifyRequest(loaderContext,
      '!!' +
      getLoaderString(type, impt, scoped) +
      impt.src
    )
  }

  function getLoaderString (type, part, scoped) {
    var lang = part.lang || defaultLang[type]
    var loader = loaders[lang]
    var rewriter = type === 'styles' ? styleRewriter + (scoped ? '&scoped=true!' : '!') : ''
    var injectString = (type === 'script' && query.inject) ? 'inject!' : ''
    if (loader !== undefined) {
      // inject rewriter before css/html loader for
      // extractTextPlugin use cases
      if (rewriterInjectRE.test(loader)) {
        loader = loader.replace(rewriterInjectRE, function (m, $1) {
          return ensureBang($1) + rewriter
        })
      } else {
        loader = ensureBang(loader) + rewriter
      }
      return injectString + ensureBang(loader)
    } else {
      // unknown lang, infer the loader to be used
      switch (type) {
        case 'template':
          return defaultLoaders.html + '!' + templateLoaderPath + '?raw&engine=' + lang + '!'
        case 'styles':
          return defaultLoaders.css + '!' + rewriter + lang + '!'
        case 'script':
          return injectString + lang + '!'
      }
    }
  }

  function getSelectorString (type, index) {
    return selectorPath +
      '?type=' + type +
      '&index=' + index + '!'
  }

  function ensureBang (loader) {
    if (loader.charAt(loader.length - 1) !== '!') {
      return loader + '!'
    } else {
      return loader
    }
  }

  var parts = parse(content, fileName, this.sourceMap)
  var hasScoped = parts.styles.some(function (s) { return s.scoped })
  var output = 'var __vue_script__\n'

  // add requires for styles
  if (!isServer) {
    parts.styles.forEach(function (style, i) {
      output += style.src
        ? getRequireForImport('styles', style, style.scoped)
        : getRequire('styles', style, i, style.scoped)
    })
  }

  // add require for script
  var script = parts.script
  if (script) {
    output +=
      '__vue_script__ = ' + (
        script.src
          ? getRequireForImport('script', script)
          : getRequire('script', script)
      )
    // check and warn named exports
    if (!this.minimize) {
      output +=
        'if (__vue_script__ &&\n' +
        '    __vue_script__.__esModule &&\n' +
        '    Object.keys(__vue_script__).length > 1) {\n' +
        '  console.warn(' + JSON.stringify(
            '[vue-loader] ' + path.relative(process.cwd(), filePath) +
            ': named exports in *.vue files are ignored.'
          ) + ')' +
        '}\n'
    }
  }

  // plain require() compatibility
  var exports = 'if (__exports__.__esModule) __exports__ = __exports__.default\n'

  // add require for template
  var template = parts.template
  if (template) {
    output += 'var __vue_template__ = ' + (
      template.src
        ? getRequireForImport('template', template)
        : getRequire('template', template)
    )
    // attach render functions to exported options
    exports +=
      'var __vue_options__ = (typeof __exports__ === "function" ' +
        '? (__exports__.options || (__exports__.options = {})) ' +
        ': __exports__)\n' +
      '__vue_options__.render = __vue_template__.render\n' +
      '__vue_options__.staticRenderFns = __vue_template__.staticRenderFns\n'
    // attach scoped id
    if (hasScoped) {
      exports += '__vue_options__._scopeId = "' + moduleId + '"\n'
    }
  }

  if (!query.inject) {
    output +=
      'var __exports__ = __vue_script__ || {}\n' +
      exports +
      'module.exports = __exports__'
    // hot reload
    if (
      !this.minimize &&
      process.env.NODE_ENV !== 'production' &&
      (parts.script || parts.template)
    ) {
      output +=
        '\nif (module.hot) {(function () {' +
        '  var hotAPI = require("' + hotReloadAPIPath + '")\n' +
        '  hotAPI.install(require("vue"), false)\n' +
        '  if (!hotAPI.compatible) return\n' +
        '  module.hot.accept()\n' +
        '  if (!module.hot.data) {\n' +
        // initial insert
        '    hotAPI.createRecord("' + moduleId + '", __exports__)\n' +
        '  } else {\n' +
        // update
        '    hotAPI.reload("' + moduleId + '", __exports__)\n' +
        '  }\n' +
        '})()}'
    }
  } else {
    output +=
      'module.exports = function (injections) {\n' +
      '  var __exports__ = __vue_script__\n' +
      '    ? __vue_script__(injections)\n' +
      '    : {}\n' + exports +
      '  return __exports__\n' +
      '}'
  }

  // done
  return output
}
<commit_msg>do not include hot-reload for server<commit_after>var loaderUtils = require('loader-utils')
var assign = require('object-assign')
var parse = require('./parser')
var path = require('path')
var normalize = require('./normalize')
var genId = require('./gen-id')

// internal lib loaders
var selectorPath = normalize.lib('selector')
var templateLoaderPath = normalize.lib('template-loader')
var templateCompilerPath = normalize.lib('template-compiler')
var styleRewriterPath = normalize.lib('style-rewriter')

// dep loaders
var styleLoaderPath = normalize.dep('vue-style-loader')
var hotReloadAPIPath = normalize.dep('vue-hot-reload-api')

var hasBabel = true
try {
  require('babel-loader')
} catch (e) {
  hasBabel = false
}

var rewriterInjectRE = /\b(css(?:-loader)?(?:\?[^!]+)?)(?:!|$)/

var defaultLang = {
  template: 'html',
  styles: 'css',
  script: 'js'
}

module.exports = function (content) {
  this.cacheable()
  var isServer = this.options.target === 'node'
  var loaderContext = this
  var options = this.options.vue || {}
  var query = loaderUtils.parseQuery(this.query)
  var filePath = this.resourcePath
  var fileName = path.basename(filePath)
  var moduleId = 'data-v-' + genId(filePath)
  var styleRewriter = styleRewriterPath + '?id=' + moduleId

  var needCssSourceMap =
    this.sourceMap &&
    !this.minimize &&
    process.env.NODE_ENV !== 'production' &&
    options.cssSourceMap !== false

  var defaultLoaders = {
    html: templateCompilerPath + '?id=' + moduleId,
    css: styleLoaderPath + '!css-loader' + (needCssSourceMap ? '?sourceMap' : ''),
    js: hasBabel ? 'babel-loader' : ''
  }

  // check if there are custom loaders specified via
  // webpack config, otherwise use defaults
  var loaders = assign({}, defaultLoaders, options.loaders)

  function getRequire (type, part, index, scoped) {
    return 'require(' +
      getRequireString(type, part, index, scoped) +
    ')\n'
  }

  function getRequireString (type, part, index, scoped) {
    return loaderUtils.stringifyRequest(loaderContext,
      // disable all configuration loaders
      '!!' +
      // get loader string for pre-processors
      getLoaderString(type, part, scoped) +
      // select the corresponding part from the vue file
      getSelectorString(type, index || 0) +
      // the url to the actual vuefile
      filePath
    )
  }

  function getRequireForImport (type, impt, scoped) {
    return 'require(' +
      getRequireForImportString(type, impt, scoped) +
    ')\n'
  }

  function getRequireForImportString (type, impt, scoped) {
    return loaderUtils.stringifyRequest(loaderContext,
      '!!' +
      getLoaderString(type, impt, scoped) +
      impt.src
    )
  }

  function getLoaderString (type, part, scoped) {
    var lang = part.lang || defaultLang[type]
    var loader = loaders[lang]
    var rewriter = type === 'styles' ? styleRewriter + (scoped ? '&scoped=true!' : '!') : ''
    var injectString = (type === 'script' && query.inject) ? 'inject!' : ''
    if (loader !== undefined) {
      // inject rewriter before css/html loader for
      // extractTextPlugin use cases
      if (rewriterInjectRE.test(loader)) {
        loader = loader.replace(rewriterInjectRE, function (m, $1) {
          return ensureBang($1) + rewriter
        })
      } else {
        loader = ensureBang(loader) + rewriter
      }
      return injectString + ensureBang(loader)
    } else {
      // unknown lang, infer the loader to be used
      switch (type) {
        case 'template':
          return defaultLoaders.html + '!' + templateLoaderPath + '?raw&engine=' + lang + '!'
        case 'styles':
          return defaultLoaders.css + '!' + rewriter + lang + '!'
        case 'script':
          return injectString + lang + '!'
      }
    }
  }

  function getSelectorString (type, index) {
    return selectorPath +
      '?type=' + type +
      '&index=' + index + '!'
  }

  function ensureBang (loader) {
    if (loader.charAt(loader.length - 1) !== '!') {
      return loader + '!'
    } else {
      return loader
    }
  }

  var parts = parse(content, fileName, this.sourceMap)
  var hasScoped = parts.styles.some(function (s) { return s.scoped })
  var output = 'var __vue_script__\n'

  // add requires for styles
  if (!isServer) {
    parts.styles.forEach(function (style, i) {
      output += style.src
        ? getRequireForImport('styles', style, style.scoped)
        : getRequire('styles', style, i, style.scoped)
    })
  }

  // add require for script
  var script = parts.script
  if (script) {
    output +=
      '__vue_script__ = ' + (
        script.src
          ? getRequireForImport('script', script)
          : getRequire('script', script)
      )
    // check and warn named exports
    if (!this.minimize) {
      output +=
        'if (__vue_script__ &&\n' +
        '    __vue_script__.__esModule &&\n' +
        '    Object.keys(__vue_script__).length > 1) {\n' +
        '  console.warn(' + JSON.stringify(
            '[vue-loader] ' + path.relative(process.cwd(), filePath) +
            ': named exports in *.vue files are ignored.'
          ) + ')' +
        '}\n'
    }
  }

  // plain require() compatibility
  var exports = 'if (__exports__.__esModule) __exports__ = __exports__.default\n'

  // add require for template
  var template = parts.template
  if (template) {
    output += 'var __vue_template__ = ' + (
      template.src
        ? getRequireForImport('template', template)
        : getRequire('template', template)
    )
    // attach render functions to exported options
    exports +=
      'var __vue_options__ = (typeof __exports__ === "function" ' +
        '? (__exports__.options || (__exports__.options = {})) ' +
        ': __exports__)\n' +
      '__vue_options__.render = __vue_template__.render\n' +
      '__vue_options__.staticRenderFns = __vue_template__.staticRenderFns\n'
    // attach scoped id
    if (hasScoped) {
      exports += '__vue_options__._scopeId = "' + moduleId + '"\n'
    }
  }

  if (!query.inject) {
    output +=
      'var __exports__ = __vue_script__ || {}\n' +
      exports +
      'module.exports = __exports__'
    // hot reload
    if (
      !isServer &&
      !this.minimize &&
      process.env.NODE_ENV !== 'production' &&
      (parts.script || parts.template)
    ) {
      output +=
        '\nif (module.hot) {(function () {' +
        '  var hotAPI = require("' + hotReloadAPIPath + '")\n' +
        '  hotAPI.install(require("vue"), false)\n' +
        '  if (!hotAPI.compatible) return\n' +
        '  module.hot.accept()\n' +
        '  if (!module.hot.data) {\n' +
        // initial insert
        '    hotAPI.createRecord("' + moduleId + '", __exports__)\n' +
        '  } else {\n' +
        // update
        '    hotAPI.reload("' + moduleId + '", __exports__)\n' +
        '  }\n' +
        '})()}'
    }
  } else {
    output +=
      'module.exports = function (injections) {\n' +
      '  var __exports__ = __vue_script__\n' +
      '    ? __vue_script__(injections)\n' +
      '    : {}\n' + exports +
      '  return __exports__\n' +
      '}'
  }

  // done
  return output
}
<|endoftext|>