<commit_before>
var IFRAME_NS = 'iframe',
	_emptyPage = '//about:blank',

	_fixIframeBugs = function(isShowing) {
		if(mfp.currTemplate[IFRAME_NS]) {
			var el = mfp.currTemplate[IFRAME_NS].find('iframe');
			if(el.length) {
				// reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
				if(!isShowing) {
					el[0].src = _emptyPage;
				}

				// IE8 black screen bug fix
				if(mfp.isIE8) {
					el.css('display', isShowing ? 'block' : 'none');
				}
			}
		}
	};

$.magnificPopup.registerModule(IFRAME_NS, {

	options: {
		markup: '
'+
					'

'+
					''+
				'
',

		srcAction: 'iframe_src',

		// we don't care and support only one default type of URL by default
		patterns: {
			youtube: {
				index: 'youtube.com',
				id: 'v=',
				src: '//www.youtube.com/embed/%id%?autoplay=1'
			},
			vimeo: {
				index: 'vimeo.com/',
				id: '/',
				src: '//player.vimeo.com/video/%id%?autoplay=1'
			},
			gmaps: {
				index: '//maps.google.',
				src: '%id%&output=embed'
			}
		}
	},

	proto: {
		initIframe: function() {
			mfp.types.push(IFRAME_NS);

			_mfpOn('BeforeChange', function(e, prevType, newType) {
				if(prevType !== newType) {
					if(prevType === IFRAME_NS) {
						_fixIframeBugs(); // iframe if removed
					} else if(newType === IFRAME_NS) {
						_fixIframeBugs(true); // iframe is showing
					}
				}// else {
					// iframe source is switched, don't do anything
				//}
			});

			_mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
				_fixIframeBugs();
			});
		},

		getIframe: function(item, template) {
			var embedSrc = item.src;
			var iframeSt = mfp.st.iframe;

			$.each(iframeSt.patterns, function() {
				if(embedSrc.indexOf( this.index ) > -1) {
					if(this.id) {
						if(typeof this.id === 'string') {
							embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
						} else {
							embedSrc = this.id.call( this, embedSrc );
						}
					}
					embedSrc = this.src.replace('%id%', embedSrc );
					return false; // break;
				}
			});

			var dataObj = {};
			if(iframeSt.srcAction) {
				dataObj[iframeSt.srcAction] = embedSrc;
			}
			mfp._parseMarkup(template, dataObj, item);

			mfp.updateStatus('ready');

			return template;
		}
	}
});

<commit_msg>Add support for youtu.be links and Youtube playlists<commit_after>
var IFRAME_NS = 'iframe',
	_emptyPage = '//about:blank',

	_fixIframeBugs = function(isShowing) {
		if(mfp.currTemplate[IFRAME_NS]) {
			var el = mfp.currTemplate[IFRAME_NS].find('iframe');
			if(el.length) {
				// reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
				if(!isShowing) {
					el[0].src = _emptyPage;
				}

				// IE8 black screen bug fix
				if(mfp.isIE8) {
					el.css('display', isShowing ? 'block' : 'none');
				}
			}
		}
	};

$.magnificPopup.registerModule(IFRAME_NS, {

	options: {
		markup: '
'+
					'

'+
					''+
				'
',

		srcAction: 'iframe_src',

		patterns: {
			// Youtube video
			youtube: {
				index: 'youtube.com/watch',
				id: 'v=',
				src: '//www.youtube.com/embed/%id%?autoplay=1'
			},
			// Youtube short url. Note that the ?list param will not be retained due to autoplay flag. Either remove autoplay flag, or link to playlist instead (see next)
			youtu_be: {
				index: 'youtu.be',
				id: '/',
				src: '//www.youtube.com/embed/%id%?autoplay=1'
			},
			// Youtube playlist
			youtube_playlist: {
				index: 'youtube.com/playlist',
				id: 'list=',
				src: '//www.youtube.com/embed/videoseries?list=%id%&autoplay=1'
			}
			vimeo: {
				index: 'vimeo.com/',
				id: '/',
				src: '//player.vimeo.com/video/%id%?autoplay=1'
			},
			gmaps: {
				index: '//maps.google.',
				src: '%id%&output=embed'
			}
		}
	},

	proto: {
		initIframe: function() {
			mfp.types.push(IFRAME_NS);

			_mfpOn('BeforeChange', function(e, prevType, newType) {
				if(prevType !== newType) {
					if(prevType === IFRAME_NS) {
						_fixIframeBugs(); // iframe if removed
					} else if(newType === IFRAME_NS) {
						_fixIframeBugs(true); // iframe is showing
					}
				}// else {
					// iframe source is switched, don't do anything
				//}
			});

			_mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
				_fixIframeBugs();
			});
		},

		getIframe: function(item, template) {
			var embedSrc = item.src;
			var iframeSt = mfp.st.iframe;

			$.each(iframeSt.patterns, function() {
				if(embedSrc.indexOf( this.index ) > -1) {
					if(this.id) {
						if(typeof this.id === 'string') {
							embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
						} else {
							embedSrc = this.id.call( this, embedSrc );
						}
					}
					embedSrc = this.src.replace('%id%', embedSrc );
					return false; // break;
				}
			});

			var dataObj = {};
			if(iframeSt.srcAction) {
				dataObj[iframeSt.srcAction] = embedSrc;
			}
			mfp._parseMarkup(template, dataObj, item);

			mfp.updateStatus('ready');

			return template;
		}
	}
});

<|endoftext|>


<commit_before>(function () {
  var iframe = document.createElement("iframe");
  var body = document.getElementsByTagName("body")[0];

  iframe.style.display = "none";

  body.insertBefore(iframe, body.firstChild);

  var iDocument = iframe.contentWindow.document;
  var iHead = iDocument.getElementsByTagName("head")[0];

  var script = document.createElement("script");
  script.src = FactlinkConfig.lib + "/dist/factlink.js";

  var configScript = document.createElement("script");
  configScript.type = "text/javascript";
  configScript.innerHTML = "window.FactlinkConfig = " + JSON.stringify(FactlinkConfig) + ";";

  iHead.insertBefore(configScript, iHead.firstChild);
  iHead.insertBefore(script, iHead.firstChild);
}());
<commit_msg>Restructured loader script<commit_after>(function () {
  function createIframe() {
    var body = document.getElementsByTagName("body")[0];
    var iframe = document.createElement("iframe");
    var div = document.createElement("div");

    iframe.style.display = "none";
    iframe.id = "factlink-iframe";
    div.id = "fl";

    body.insertBefore(div, body.firstChild);
    div.insertBefore(iframe, div.firstChild);

    return iframe;
  }

  var iframe = createIframe();

  var iDocument = iframe.contentWindow.document;
  var iHead = iDocument.getElementsByTagName("head")[0];
  var head = document.getElementsByTagName("head")[0];

  var flScript = document.createElement("script");
  flScript.src = FactlinkConfig.lib + "/dist/factlink.js";

  var configScript = document.createElement("script");
  configScript.type = "text/javascript";
  configScript.innerHTML = "window.FactlinkConfig = " + JSON.stringify(FactlinkConfig) + ";";

  iHead.insertBefore(configScript, iHead.firstChild);
  iHead.insertBefore(flScript, iHead.firstChild);
}());
<|endoftext|>


<commit_before>'use strict';

var convert = require('html-formulae')
  , stripHtml = require('strip-html')
  , concat = require('concat-stream');

var Backbone = require('backbone')
  , _ = require('underscore');

/**
 * Converter holds a single input/output pair:
 * - input: string, input value;
 * - output(*): string, unwrapped HTML output.
 *
 * (*) - computed property.
 */
exports.Converter = Backbone.Model.extend({
  defaults: {
    input: ''
  },

  initialize: function () {
    this.on('change:input', this.setOutput, this);
  },

  setOutput: function () {
    var input = this.get('input');

    var htmlStripper = stripHtml();
    htmlStripper.pipe(concat({ encoding: 'string' }, function (output) {
      this.set('output', output);
    }.bind(this)));
    htmlStripper.end(this.convert(input));
  },

  convert: function (input) {
    // Proxy to Convert module.
    return convert(input);
  }
});

/**
 * Theme descriptor:
 *  - name: string, unique theme identifier;
 *  - src: theme .css path;
 *  - icon: theme icon color.
 */
exports.Theme = Backbone.Model;

exports.Themes = Backbone.Collection.extend({
  model: exports.Theme
});

/**
 * Currently set theme.
 * Persistently stored in LocalStorage.
 */
exports.CurrentTheme = exports.Theme.extend({
  defaults: {
    // Fixed ID between sessions.
    id: 0
  },

  localStorage: new Backbone.LocalStorage('current-theme'),

  initialize: function () {
    this.fetch();
  }
});

/**
 * History of formulas.
 * Persistently stored in LocalStorage.
 */
exports.History = Backbone.Collection.extend({
  model: exports.Converter,

  localStorage: new Backbone.LocalStorage('history'),

  // While individual converters can be stored out of order,
  //   the entire collection grows only on one of its ends.
  // Thus, if one element is added after another, then it is
  //   guaranteed that it is located above in the history stack.
  // This insertion order is mirrored by this variable.
  // Its domain is negative to avoid collisions with existing IDs.
  nextId: -1,

  initialize: function () {
    // These lines rely on the synchrony of LocalStorage.
    this.once('sync', this.renumerate, this);
    this.fetch();
  },

  // Item IDs will constantly increase over time,
  //   so it is necessary to renumerate them on sync.
  // But the most important reason to do it is to normalize IDs
  //   to keep them non-negative for further insertions.
  renumerate: function () {
    this.reset(_.chain(this.models)
                .sortBy('id')
                .each(function (model) {
                  model.sync('delete', model);
                })
                .value());
    this.each(function (model, index) {
      model.save('id', index);
    });
  },

  pushItem: function (model) {
    this.create(model.clone().set({
      id: this.nextId--
    }), {at: 0});
  }
});
<commit_msg>Remove the convert proxy<commit_after>'use strict';

var htmlFormulae = require('html-formulae')
  , stripHtml = require('strip-html')
  , concat = require('concat-stream');

var Backbone = require('backbone')
  , _ = require('underscore');

/**
 * Converter holds a single input/output pair:
 * - input: string, input value;
 * - output(*): string, unwrapped HTML output.
 *
 * (*) - computed property.
 */
exports.Converter = Backbone.Model.extend({
  defaults: {
    input: ''
  },

  initialize: function () {
    this.on('change:input', this.setOutput, this);
  },

  setOutput: function () {
    var input = this.get('input');

    var htmlStripper = stripHtml();
    htmlStripper.pipe(concat({ encoding: 'string' }, function (output) {
      this.set('output', output);
    }.bind(this)));
    htmlStripper.end(htmlFormulae(input));
  }
});

/**
 * Theme descriptor:
 *  - name: string, unique theme identifier;
 *  - src: theme .css path;
 *  - icon: theme icon color.
 */
exports.Theme = Backbone.Model;

exports.Themes = Backbone.Collection.extend({
  model: exports.Theme
});

/**
 * Currently set theme.
 * Persistently stored in LocalStorage.
 */
exports.CurrentTheme = exports.Theme.extend({
  defaults: {
    // Fixed ID between sessions.
    id: 0
  },

  localStorage: new Backbone.LocalStorage('current-theme'),

  initialize: function () {
    this.fetch();
  }
});

/**
 * History of formulas.
 * Persistently stored in LocalStorage.
 */
exports.History = Backbone.Collection.extend({
  model: exports.Converter,

  localStorage: new Backbone.LocalStorage('history'),

  // While individual converters can be stored out of order,
  //   the entire collection grows only on one of its ends.
  // Thus, if one element is added after another, then it is
  //   guaranteed that it is located above in the history stack.
  // This insertion order is mirrored by this variable.
  // Its domain is negative to avoid collisions with existing IDs.
  nextId: -1,

  initialize: function () {
    // These lines rely on the synchrony of LocalStorage.
    this.once('sync', this.renumerate, this);
    this.fetch();
  },

  // Item IDs will constantly increase over time,
  //   so it is necessary to renumerate them on sync.
  // But the most important reason to do it is to normalize IDs
  //   to keep them non-negative for further insertions.
  renumerate: function () {
    this.reset(_.chain(this.models)
                .sortBy('id')
                .each(function (model) {
                  model.sync('delete', model);
                })
                .value());
    this.each(function (model, index) {
      model.save('id', index);
    });
  },

  pushItem: function (model) {
    this.create(model.clone().set({
      id: this.nextId--
    }), {at: 0});
  }
});
<|endoftext|>


<commit_before>
// Relayed
var apiKey    = '45383722';
var sessionId = '1_MX40NTM4MzcyMn5-MTQ0NTk1ODkwMzc0NH5LT3RpMUZlcWMwOTZtaGpMOE9sZ0JMLzl-UH4';
var token     = 'T1==cGFydG5lcl9pZD00NTM4MzcyMiZzaWc9ZWM3NDU5NDYxNDQwZTVjYjYxMzcxMDcxYzg1OWVkYjM4NzVhN2YzYTpyb2xlPXB1Ymxpc2hlciZzZXNzaW9uX2lkPTFfTVg0ME5UTTRNemN5TW41LU1UUTBOVGsxT0Rrd016YzBOSDVMVDNScE1VWmxjV013T1RadGFHcE1PRTlzWjBKTUx6bC1VSDQmY3JlYXRlX3RpbWU9MTQ0NTk1ODkwNyZub25jZT0wLjEzOTY1MzgyOTQ2NTA1MjM0JmV4cGlyZV90aW1lPTE0NDg1NTA4ODgmY29ubmVjdGlvbl9kYXRhPQ==';
var extensionId = 'kdgjponegkkhkigjlknapimncipajbpi';
var session = OT.initSession(apiKey, sessionId);

// Routed
/*
var apiKey    = '45383732';
var sessionId = '1_MX40NTM4MzczMn5-MTQ0NTk2Mjc1NzgzNn52am1xdWR1UUR0RVBoZWswZ0FWMGUwenZ-fg';
var token     = 'T1==cGFydG5lcl9pZD00NTM4MzczMiZzaWc9OGY4YTUwZDNkZWQ0MjVhMzRjOGFlZjg2YjQzZTJkMmJiZGMzMDMwZjpyb2xlPXB1Ymxpc2hlciZzZXNzaW9uX2lkPTFfTVg0ME5UTTRNemN6TW41LU1UUTBOVGsyTWpjMU56Z3pObjUyYW0xeGRXUjFVVVIwUlZCb1pXc3daMEZXTUdVd2VuWi1mZyZjcmVhdGVfdGltZT0xNDQ1OTYyODI3Jm5vbmNlPTAuMzYwOTUyMzEyNTUwOTMzNjMmZXhwaXJlX3RpbWU9MTQ0ODU1NDc1MSZjb25uZWN0aW9uX2RhdGE9';
*/

function initBody() {
    initShareScreen();
}

function initShareScreen() {
    var button = document.getElementById("shareScreen");
    button.addEventListener('click', function (event) {
        screenshare();
    });
}

/*
function initFullScreen() {
    var button = document.getElementById("fullScreen");
    button.addEventListener('click', function(event) {
        var elem = document.getElementById("shareScreen");

        //show full screen
        elem.webkitRequestFullScreen();
    });
}
 */

session.connect(token, function(error) {
    //document.getElementById('shareScreen').disabled = false;
});

session.on('streamCreated', function(event) {
    if (event.stream.videoType === 'screen') {
        // This is a screen-sharing stream published by another client
        var subOptions = {
            width: event.stream.videoDimensions.width / 2,
            height: event.stream.videoDimensions.height /2
        };
        session.subscribe(event.stream, 'screen-subscriber', subOptions);
    }
});

// For Google Chrome only, register your extension by ID,
// You can find it at chrome://extensions once the extension is installed
OT.registerScreenSharingExtension('chrome', extensionId);

function screenshare() {

    OT.checkScreenSharingCapability(function(response) {
        if (!response.supported || response.extensionRegistered === false) {
            alert('This browser does not support screen sharing.');
        } else if (response.extensionInstalled === false) {
            alert('Please install the screen sharing extension and load this page over HTTPS.');
        } else {
            // Screen sharing is available. Publish the screen.
            // Create an element, but do not display it in the HTML DOM:
            // var screenContainerElement = document.createElement('div');
            var screenContainerElement = document.getElementById("shareScreen");
            var screenSharingPublisher = OT.initPublisher(screenContainerElement,
                { videoSource : 'screen', width:1280, height:720 },
                function(error) {
                    if (error) {
                        alert('Something went wrong: ' + error.message);
                    } else {
                        session.publish(screenSharingPublisher, function(error) {
                            if (error) {
                                alert('Something went wrong: ' + error.message);
                            }
                        });
                    }
                });
        }
    });
}

<commit_msg>screen controller<commit_after>
// Relayed
var apiKey    = '45383722';
var sessionId = '1_MX40NTM4MzcyMn5-MTQ0NTk1ODkwMzc0NH5LT3RpMUZlcWMwOTZtaGpMOE9sZ0JMLzl-UH4';
var token     = 'T1==cGFydG5lcl9pZD00NTM4MzcyMiZzaWc9ZWM3NDU5NDYxNDQwZTVjYjYxMzcxMDcxYzg1OWVkYjM4NzVhN2YzYTpyb2xlPXB1Ymxpc2hlciZzZXNzaW9uX2lkPTFfTVg0ME5UTTRNemN5TW41LU1UUTBOVGsxT0Rrd016YzBOSDVMVDNScE1VWmxjV013T1RadGFHcE1PRTlzWjBKTUx6bC1VSDQmY3JlYXRlX3RpbWU9MTQ0NTk1ODkwNyZub25jZT0wLjEzOTY1MzgyOTQ2NTA1MjM0JmV4cGlyZV90aW1lPTE0NDg1NTA4ODgmY29ubmVjdGlvbl9kYXRhPQ==';

// Routed
//var apiKey    = '45383732';
//var sessionId = '1_MX40NTM4MzczMn5-MTQ0NTk2Mjc1NzgzNn52am1xdWR1UUR0RVBoZWswZ0FWMGUwenZ-fg';
//var token     = 'T1==cGFydG5lcl9pZD00NTM4MzczMiZzaWc9OGY4YTUwZDNkZWQ0MjVhMzRjOGFlZjg2YjQzZTJkMmJiZGMzMDMwZjpyb2xlPXB1Ymxpc2hlciZzZXNzaW9uX2lkPTFfTVg0ME5UTTRNemN6TW41LU1UUTBOVGsyTWpjMU56Z3pObjUyYW0xeGRXUjFVVVIwUlZCb1pXc3daMEZXTUdVd2VuWi1mZyZjcmVhdGVfdGltZT0xNDQ1OTYyODI3Jm5vbmNlPTAuMzYwOTUyMzEyNTUwOTMzNjMmZXhwaXJlX3RpbWU9MTQ0ODU1NDc1MSZjb25uZWN0aW9uX2RhdGE9';

var extensionId = 'kdgjponegkkhkigjlknapimncipajbpi';
var session = OT.initSession(apiKey, sessionId);

function initBody() {
    initShareScreen();
    initFullScreen();
}

//function initShareScreen() {
//    $("#shareScreen").click(function (event) {
//        alert(apiKey);
//        screenshare();
//    });
//}

//function initFullScreen() {
//    $("fullScreen").click(function(event) {
//        var elem = document.getElementById("shareScreen");
//        //show full screen
//        elem.webkitRequestFullScreen();
//    });
//}

session.connect(token, function(error) {
    screenshare();
    var elem = document.getElementById("shareScreen");

    //elem.setAttribute('autoplay', true);
    //elem.setAttribute('controls', true);

    //elem.webkitRequestFullScreen();
});

session.on('streamCreated', function(event) {
    if (event.stream.videoType === 'screen') {
        // This is a screen-sharing stream published by another client
        var subOptions = {
            //width: event.stream.videoDimensions.width / 2,
            //height: event.stream.videoDimensions.height / 2
            width: screen.width,
            height: screen.height
        };
        session.subscribe(event.stream, 'screen-subscriber', subOptions);
    }
});

// For Google Chrome only, register your extension by ID,
// You can find it at chrome://extensions once the extension is installed
OT.registerScreenSharingExtension('chrome', extensionId);

function screenshare() {
    OT.checkScreenSharingCapability(function(response) {
        if (!response.supported || response.extensionRegistered === false) {
            alert('This browser does not support screen sharing.');
        }
        else if (response.extensionInstalled === false) {
            alert('Please install the screen sharing extension and load this page over HTTPS.');
        }
        else {
            var screenContainerElement = document.getElementById("shareScreen");
            var screenSharingPublisher = OT.initPublisher(screenContainerElement,
                { videoSource : 'screen', width:screen.width, height:screen.height },
                function(error) {
                    if (error) {
                        alert('Something went wrong: ' + error.message);
                    } else {
                        session.publish(screenSharingPublisher, function(error) {
                            if (error) {
                                alert('Something went wrong: ' + error.message);
                            }
                        });
                    }
                });
        }
    });
}
<|endoftext|>


<commit_before>$(window).load(function () {

  $(document).on('change', '.btn-file :file', function () {
    var input = $(this)
    var numFiles = input.get(0).files ? input.get(0).files.length : 1
    var label = input.val().replace(/\\/g, '/').replace(/.*\//, '')

    input.trigger('fileselect', [numFiles, label])
  })

  $(document).ready(function () {
    $('.btn-file :file').on('fileselect', function (event, numFiles, label) {
      //console.log(numFiles)
      //console.log(label)
    })
  })

  $('[data-toggle="tooltip"]').tooltip()

})

$(document).ready(function () {
  if ($('#srch-term').length > 0 && $('#srch-term').val() === '') {
    setSearchFormState()
    doTrigger()
  }

  // Open links in-app instead of new window //
  $('.open-in-app a').click(function (event) {
    event.preventDefault()
    if ($(this).attr('href') !== undefined) {
      window.location = $(this).attr('href')
    }
  })

  // Menu toggle //
  $('.toggle-dropdown').on('click', function () {
    var parent = $(this).parent() // Select parent of clicked element
    if (parent.hasClass('active')) {
      parent.removeClass('active')
    } else {
      $('li.active').removeClass('active') // Reset active class
      parent.addClass('active') // Set class 'active' to parent's child
    }
  })

  // Searchfilter toggle //
  $('.toggleFilters').on('click', function () {
    $('.toggleFilters').toggleClass('active')
    $('.filters').toggleClass('active')
  })

  // Searchform //

  $('.searchForm').on('keydown', function () {
    $('#heroSearch').addClass('contracted')
    $('html, body').animate({ scrollTop: 0 }, 'fast')
  })

  $('.searchForm').keyup(setSearchFormState).blur(function () {
    if (this.value === '') {
      $('#heroSearch')
        .removeClass('contracted')
        .addClass('transition')
    }
  })

  function setSearchFormState() {
    if ($('.searchForm').val() === '') {
      $('#searchForm-btn-default').html(
        $('', {
          class: 'glyphicon glyphicon-search'
        })
      )
      $('#results').hide()
    } else {
      $('#searchForm-btn-default').html(
        $('', {
          alt: 'Laddar...',
          src: '/assets/images/loading.svg',
          class: 'loading'
        })
      )
    }
  }

  var typingTimer
  $('.searchForm').on('keyup', function () {
    clearTimeout(typingTimer)
    typingTimer = setTimeout(doTrigger, 150)
  })

  $('.searchForm').on('keydown', function () {
    clearTimeout(typingTimer)
  })

  setTimeout(function () {
    var searchParam = window.location.search
    if (searchParam.length > 0) { //Search query is entered in URL
      setSearchFormState()
      doTrigger()
    }
  }, 0)

  // Search results //
  function doTrigger() {
    if ($('.searchForm').val().length > 2) {

      var searchTerm = $('.searchForm').val()
      var container = $('#searchResult')

      $.getJSON('/ajax/search/?s=' + searchTerm, function (data) {
        if (data.length > 0 && data[0] !== undefined) {
          if ($('#searchEngine-noResults').css('display') === 'block') {
            $('#searchEngine-noResults').show()
          }

          $('#searchFor')
          .html(
            $('
', {
              id: 'searchFor'
            })
            .append(
              $('').html('SökresultatResultat för '),
              $('').html(searchTerm)
            )
          )

          $('#searchFilter').show()
          $('#results').show()

          var entryImage = function (entry) {
            var cover = entry.post.cover.filename
            var image = cover !== null && cover.length > 0 ? '/uploads/' + cover + '_thumb.jpg'
              : '/assets/images/placeholder-' + entry.type + '.svg'
            var imageSrc = 'background-image: url(' + image + ')'

            var entryImage = $('', {
              href: entry.url
            })
            .append(
              $('
', {
                class: 'image'
              }).attr('style', imageSrc)
            )

            return entryImage
          }

          var entryTitle = function (entry) {
            return $('', {
              href: '/' + entry.url
            })
            .append(
              $('
').text(entry.title)
            )
          }

          var entryDescription = function (entry) {
            var description = $('
')
            if (entry.type === '4') {
              var veg_type = entry.post.veg_type

              //TODO this info needs to be updated
              var veg_types = {
                vegan: function () {
                  return $('', {
                    class: 'text-success'
                  })
                  .append(
                    $('', {
                      class: 'fa fa-check-circle'
                    }),
                    $('').html('Veganskt ')
                  )
                },
                lacto_ovo: function () {
                  return $('', {
                    class: 'text-warning'
                  })
                  .append(
                    $('').html('Lakto-Ovo ')
                  )
                },
                animal: function () {
                  return $('', {
                    class: 'text-danger'
                  })
                  .append(
                    $('').html('Animaliskt ')
                  )
                }
              }

              if (veg_type in veg_types) {
                $(description).append(
                  veg_types[veg_type]()
                )
              }
            }

            $(description).append(
              $('')
              .html(entry.post.content.substring(0, 115) + '...')
            )

            return description
          }

          var entryRating = function (entry) {
            var rating = (entry.hasOwnProperty('rating') ? (entry.rating.hasOwnProperty('votes_sum') ? entry.rating.votes_sum : false) : false)
            return $('
', {
              class: 'stars'
            })
            .attr({
              'data-id': entry._id
            })
            .append(
              $.map(new Array(5), function (item, index) {
                return $('
', {
                  class: (rating !== false && index <= rating) ? 'active star' : 'star'
                })
                .append(
                  $('', {
                    class: 'glyphicon glyphicon-star'
                  })
                )
              }),
              $('', {
                class: 'votes'
              })
              .text((rating) ? entry.rating.votes : 0)
            )
          }

          var entryLikes = function (entry) {
            var likes = (entry.hasOwnProperty('rating')) ? (entry.rating.hasOwnProperty('likes') ? entry.rating.likes : false) : false

            if (likes) {
              return $('
', {
                id: 'like',
                class: 'like-container xs'
              })
              .append(
                $('
', {
                  class: 'hint'
                })
                .append(
                  $('', {
                    href: '/logga-in'
                  })
                  .text('Logga in'),
                  $('')
                  .html(' på Vegosvar för att gilla')
                ),
                $('', {
                  id: entry._id,
                  class: 'like add-like'
                })
                .append(
                  $('', {
                    id: 'heart-glyphicon',
                    class: 'glyphicon glyphicon-heart'
                  }),
                  $('', {
                    class: 'count'
                  })
                  .html(' ' + likes)
                )
              )
            }
          }

          var createEntry = function (entry) {
            return $('
', {
              class: 'col-sm-6 col-md-4 col-lg-3',
              id: 'searchResult-' + entry._id
            })
            .append(
              $('
', {
                class: 'result'
              })
              .append(
                entryImage(entry),
                entryLikes(entry),
                $('
', {
                  class: 'content'
                })
                .append(
                  $('
', {
                    class: 'text-overflow'
                  })
                  .append(
                    entryTitle(entry),
                    entryDescription(entry),
                    entryRating(entry),
                    $('
', {
                      class: 'more'
                    })
                    .append(
                      $('', {
                        href: '/' + entry.url,
                        class: 'btn btn-primary'
                      })
                      .html('Läs mer')
                    )
                  )
                )
              )
            )
          }

          var resultContainer = $('
', {
            id: 'searchResultsContainer'
          })

          $.each(data, function (i, entry) {
            $(resultContainer).append(
              createEntry(entry)
            )
          })

          $(container).html(resultContainer)

          $('#searchEngine-noResults').hide()
        } else { // No results
          $('#searchFor').html(
            $('
').text('Inga resultat kunde hittas')
          )

          $('#searchFilter').hide()
          $('#results').show()
          $('#searchResultsContainer').html('')
        }

        $('#searchForm-btn-default').html(
          $('', {
            class: 'glyphicon glyphicon-search'
          })
        )
      })
    }
  }
})<commit_msg>Fix missing class in likes<commit_after>$(window).load(function () {

  $(document).on('change', '.btn-file :file', function () {
    var input = $(this)
    var numFiles = input.get(0).files ? input.get(0).files.length : 1
    var label = input.val().replace(/\\/g, '/').replace(/.*\//, '')

    input.trigger('fileselect', [numFiles, label])
  })

  $(document).ready(function () {
    $('.btn-file :file').on('fileselect', function (event, numFiles, label) {
      //console.log(numFiles)
      //console.log(label)
    })
  })

  $('[data-toggle="tooltip"]').tooltip()

})

$(document).ready(function () {
  if ($('#srch-term').length > 0 && $('#srch-term').val() === '') {
    setSearchFormState()
    doTrigger()
  }

  // Open links in-app instead of new window //
  $('.open-in-app a').click(function (event) {
    event.preventDefault()
    if ($(this).attr('href') !== undefined) {
      window.location = $(this).attr('href')
    }
  })

  // Menu toggle //
  $('.toggle-dropdown').on('click', function () {
    var parent = $(this).parent() // Select parent of clicked element
    if (parent.hasClass('active')) {
      parent.removeClass('active')
    } else {
      $('li.active').removeClass('active') // Reset active class
      parent.addClass('active') // Set class 'active' to parent's child
    }
  })

  // Searchfilter toggle //
  $('.toggleFilters').on('click', function () {
    $('.toggleFilters').toggleClass('active')
    $('.filters').toggleClass('active')
  })

  // Searchform //

  $('.searchForm').on('keydown', function () {
    $('#heroSearch').addClass('contracted')
    $('html, body').animate({ scrollTop: 0 }, 'fast')
  })

  $('.searchForm').keyup(setSearchFormState).blur(function () {
    if (this.value === '') {
      $('#heroSearch')
        .removeClass('contracted')
        .addClass('transition')
    }
  })

  function setSearchFormState() {
    if ($('.searchForm').val() === '') {
      $('#searchForm-btn-default').html(
        $('', {
          class: 'glyphicon glyphicon-search'
        })
      )
      $('#results').hide()
    } else {
      $('#searchForm-btn-default').html(
        $('', {
          alt: 'Laddar...',
          src: '/assets/images/loading.svg',
          class: 'loading'
        })
      )
    }
  }

  var typingTimer
  $('.searchForm').on('keyup', function () {
    clearTimeout(typingTimer)
    typingTimer = setTimeout(doTrigger, 150)
  })

  $('.searchForm').on('keydown', function () {
    clearTimeout(typingTimer)
  })

  setTimeout(function () {
    var searchParam = window.location.search
    if (searchParam.length > 0) { //Search query is entered in URL
      setSearchFormState()
      doTrigger()
    }
  }, 0)

  // Search results //
  function doTrigger() {
    if ($('.searchForm').val().length > 2) {

      var searchTerm = $('.searchForm').val()
      var container = $('#searchResult')

      $.getJSON('/ajax/search/?s=' + searchTerm, function (data) {
        if (data.length > 0 && data[0] !== undefined) {
          if ($('#searchEngine-noResults').css('display') === 'block') {
            $('#searchEngine-noResults').show()
          }

          $('#searchFor')
          .html(
            $('
', {
              id: 'searchFor'
            })
            .append(
              $('').html('SökresultatResultat för '),
              $('').html(searchTerm)
            )
          )

          $('#searchFilter').show()
          $('#results').show()

          var entryImage = function (entry) {
            var cover = entry.post.cover.filename
            var image = cover !== null && cover.length > 0 ? '/uploads/' + cover + '_thumb.jpg'
              : '/assets/images/placeholder-' + entry.type + '.svg'
            var imageSrc = 'background-image: url(' + image + ')'

            var entryImage = $('', {
              href: entry.url
            })
            .append(
              $('
', {
                class: 'image'
              }).attr('style', imageSrc)
            )

            return entryImage
          }

          var entryTitle = function (entry) {
            return $('', {
              href: '/' + entry.url
            })
            .append(
              $('
').text(entry.title)
            )
          }

          var entryDescription = function (entry) {
            var description = $('
')
            if (entry.type === '4') {
              var veg_type = entry.post.veg_type

              //TODO this info needs to be updated
              var veg_types = {
                vegan: function () {
                  return $('', {
                    class: 'text-success'
                  })
                  .append(
                    $('', {
                      class: 'fa fa-check-circle'
                    }),
                    $('').html('Veganskt ')
                  )
                },
                lacto_ovo: function () {
                  return $('', {
                    class: 'text-warning'
                  })
                  .append(
                    $('').html('Lakto-Ovo ')
                  )
                },
                animal: function () {
                  return $('', {
                    class: 'text-danger'
                  })
                  .append(
                    $('').html('Animaliskt ')
                  )
                }
              }

              if (veg_type in veg_types) {
                $(description).append(
                  veg_types[veg_type]()
                )
              }
            }

            $(description).append(
              $('')
              .html(entry.post.content.substring(0, 115) + '...')
            )

            return description
          }

          var entryRating = function (entry) {
            var rating = (entry.hasOwnProperty('rating') ? (entry.rating.hasOwnProperty('votes_sum') ? entry.rating.votes_sum : false) : false)
            return $('
', {
              class: 'stars'
            })
            .attr({
              'data-id': entry._id
            })
            .append(
              $.map(new Array(5), function (item, index) {
                return $('
', {
                  class: (rating !== false && index <= rating) ? 'active star' : 'star'
                })
                .append(
                  $('', {
                    class: 'glyphicon glyphicon-star'
                  })
                )
              }),
              $('', {
                class: 'votes'
              })
              .text((rating) ? entry.rating.votes : 0)
            )
          }

          var entryLikes = function (entry) {
            var likes = (entry.hasOwnProperty('rating')) ? (entry.rating.hasOwnProperty('likes') ? entry.rating.likes : false) : false

            if (likes) {
              return $('
', {
                class: 'likes xs'
              })
              .append(
                $('
', {
                  class: 'hint'
                })
                .append(
                  $('', {
                    href: '/logga-in'
                  })
                  .text('Logga in'),
                  $('')
                  .html(' på Vegosvar för att gilla')
                ),
                $('', {
                  id: entry._id,
                  class: 'like add-like'
                })
                .append(
                  $('', {
                    id: 'heart-glyphicon',
                    class: 'glyphicon glyphicon-heart'
                  }),
                  $('', {
                    class: 'count'
                  })
                  .html(' ' + likes)
                )
              )
            }
          }

          var createEntry = function (entry) {
            return $('
', {
              class: 'col-sm-6 col-md-4 col-lg-3',
              id: 'searchResult-' + entry._id
            })
            .append(
              $('
', {
                class: 'result'
              })
              .append(
                entryImage(entry),
                entryLikes(entry),
                $('
', {
                  class: 'content'
                })
                .append(
                  $('
', {
                    class: 'text-overflow'
                  })
                  .append(
                    entryTitle(entry),
                    entryDescription(entry),
                    entryRating(entry),
                    $('
', {
                      class: 'more'
                    })
                    .append(
                      $('', {
                        href: '/' + entry.url,
                        class: 'btn btn-primary'
                      })
                      .html('Läs mer')
                    )
                  )
                )
              )
            )
          }

          var resultContainer = $('
', {
            id: 'searchResultsContainer'
          })

          $.each(data, function (i, entry) {
            $(resultContainer).append(
              createEntry(entry)
            )
          })

          $(container).html(resultContainer)

          $('#searchEngine-noResults').hide()
        } else { // No results
          $('#searchFor').html(
            $('
').text('Inga resultat kunde hittas')
          )

          $('#searchFilter').hide()
          $('#results').show()
          $('#searchResultsContainer').html('')
        }

        $('#searchForm-btn-default').html(
          $('', {
            class: 'glyphicon glyphicon-search'
          })
        )
      })
    }
  }
})<|endoftext|>


<commit_before>var warnings = (function () {

    return {

        expectedFields: {
            inproceedings: ['author', 'booktitle', 'pages', 'publisher', 'title', 'year'],
            article: ['author', 'journal', 'number', 'pages', 'title', 'volume', 'year'],
            techreport: ['author', 'institution', 'title', 'year'],
            incollection: ['author', 'booktitle', 'pages', 'publisher', 'title', 'year'],
            book: ['author', 'publisher', 'title', 'year'],
            inbook: ['author', 'booktitle', 'pages', 'publisher', 'title', 'year'],
            proceedings: ['editor', 'publisher', 'title', 'year'],
            phdthesis: ['author', 'school', 'title', 'year'],
            mastersthesis: ['author', 'school', 'title', 'year'],
            electronic: ['author', 'title', 'url', 'year'],
            misc: ['author', 'howpublished', 'title', 'year']
        },

        computeAllWarnings: function (entries) {
            var that = this;
            var warnings = {};
            $.each(entries, function (id, entry) {
                warnings[id] = that.computeWarnings(entry);
            });
            return warnings;
        },

        computeWarnings: function (entry) {
            var warningsList = [];
            if (editable) {
                warningsList = warningsList.concat(warnings.computeMissingFieldWarning(entry));
                warningsList = warningsList.concat(warnings.computeTitleCapitalizationWarning(entry));
                warningsList = warningsList.concat(warnings.computeProtectedIdentifierCapitalizationWarning(entry));
                $.each(entry, function (field, value) {
                    computeEmptyFieldWarning(warningsList, field, value);
                    computeFirstNameUnknown(warningsList, field, value);
                    computeWholeFieldCapitalizationProtected(warningsList, field, value);
                });
            }
            return warningsList;
        },

        computeMissingFieldWarning: function (entry) {
            var warningsList = [];
            if (entry) {
                var expected = warnings.expectedFields[entry['type']];
                if (expected) {
                    $.each(expected, function (i, field) {
                        if (!entry[field] && entry[field] != '') {
                            warningsList.push({
                                type: 'missing field "' + field + '"',
                                fix: {
                                    description: 'add field', 'function': function () {
                                        entry[field] = '';
                                        return entry;
                                    }
                                }
                            });
                        }
                    });
                }
            }
            return warningsList;
        },

        computeTitleCapitalizationWarning: function (entry) {
            if (!entry) {
                return [];
            }
            var warningsList = [];
            $.each(['booktitle', 'journal'], function (i, field) {
                if (entry[field]) {
                    var value = entry[field];
                    var capitalizationCorrect = true;
                    var correctedValue = '';
                    $.each(value.split(' '), function (i, word) {
                        var capitalizedWord = word;
                        if (!word.match(/\d.*/)) {
                            if ((word.length >= 5 || i == 0) && word.toLowerCase() == word) {
                                capitalizationCorrect = false;
                                capitalizedWord = word.charAt(0).toUpperCase() + word.substring(1);
                            }
                        }
                        correctedValue += (correctedValue ? ' ' : '') + capitalizedWord;
                    });
                    if (!capitalizationCorrect) {
                        warningsList.push({
                            type: 'capitalization in field "' + field + '"',
                            fix: {
                                description: 'capitalize longer words', 'function': function () {
                                    entry[field] = correctedValue;
                                    return entry;
                                }
                            }
                        });
                    }
                }
            });
            return warningsList;
        },

        computeProtectedIdentifierCapitalizationWarning: function (entry) {
            if (!entry) {
                return [];
            }
            var warningsList = [];
            $.each(['title'], function (i, field) {
                if (entry[field]) {
                    var value = entry[field];
                    var capitalizationCorrect = true;
                    var correctedValue = value;
                    if (value.indexOf('{') < 0) {
                        $.each(value.split(/[\s,:\-()\/]+/), function (i, word) {
                            if (!word.startsWith('{')) {
                                var subword = word.substring(1);
                                if (subword.length > 0 && subword.toLowerCase() != subword) {
                                    capitalizationCorrect = false;
                                    var re = new RegExp('\{?'+word+'\}?','g');
                                    correctedValue = correctedValue.replace(re, '{'+word+'}');
                                }
                            }
                        });
                        if (!capitalizationCorrect) {
                            // warningsList.push('non-protected capitalization of identifier in field "' + field + '"');
                            warningsList.push({
                                type: 'non-protected capitalization of identifier in field "' + field + '"',
                                fix: {
                                    description: 'protect identifiers', 'function': function () {
                                        entry[field] = correctedValue;
                                        return entry;
                                    }
                                }
                            });
                        }
                    }
                }
            });
            return warningsList;
        }

    };

    function computeEmptyFieldWarning(warningsList, field, value) {
        if (!value) {
            warningsList.push('empty field "' + field + '"');
        }
    }

    function computeFirstNameUnknown(warningsList, field, value) {
        if (field === 'author' || field === 'editor') {
            var firstNameKnown = true;
            $.each(value.split(' and '), function (i, name) {
                var parsedName = name.trim().split(',');
                if (parsedName.length > 1) {
                    var firstName = parsedName[1].trim().split(' ')[0].trim();
                    if (firstName.indexOf('.') > 0 || firstName.length < 2) {
                        firstNameKnown = false;
                    }
                } else {
                    firstNameKnown = false;
                }
            });
            if (!firstNameKnown) {
                warningsList.push('unknown or abbreviated first name in field "' + field + '"');
            }
        }
    }

    function computeWholeFieldCapitalizationProtected(warningsList, field, value) {
        if (value.indexOf('{') == 0 && value.lastIndexOf('}') == value.length - 1 && value.length > 10) {
            warningsList.push('whole field "' + field + '" with protected capitalization');
        }
    }

})
();<commit_msg>expected fields warning: added Bachelor's thesis<commit_after>var warnings = (function () {

    return {

        expectedFields: {
            inproceedings: ['author', 'booktitle', 'pages', 'publisher', 'title', 'year'],
            article: ['author', 'journal', 'number', 'pages', 'title', 'volume', 'year'],
            techreport: ['author', 'institution', 'title', 'year'],
            incollection: ['author', 'booktitle', 'pages', 'publisher', 'title', 'year'],
            book: ['author', 'publisher', 'title', 'year'],
            inbook: ['author', 'booktitle', 'pages', 'publisher', 'title', 'year'],
            proceedings: ['editor', 'publisher', 'title', 'year'],
            phdthesis: ['author', 'school', 'title', 'year'],
            mastersthesis: ['author', 'school', 'title', 'year'],
            bachelorsthesis: ['author', 'school', 'title', 'year'],
            electronic: ['author', 'title', 'url', 'year'],
            misc: ['author', 'howpublished', 'title', 'year']
        },

        computeAllWarnings: function (entries) {
            var that = this;
            var warnings = {};
            $.each(entries, function (id, entry) {
                warnings[id] = that.computeWarnings(entry);
            });
            return warnings;
        },

        computeWarnings: function (entry) {
            var warningsList = [];
            if (editable) {
                warningsList = warningsList.concat(warnings.computeMissingFieldWarning(entry));
                warningsList = warningsList.concat(warnings.computeTitleCapitalizationWarning(entry));
                warningsList = warningsList.concat(warnings.computeProtectedIdentifierCapitalizationWarning(entry));
                $.each(entry, function (field, value) {
                    computeEmptyFieldWarning(warningsList, field, value);
                    computeFirstNameUnknown(warningsList, field, value);
                    computeWholeFieldCapitalizationProtected(warningsList, field, value);
                });
            }
            return warningsList;
        },

        computeMissingFieldWarning: function (entry) {
            var warningsList = [];
            if (entry) {
                var expected = warnings.expectedFields[entry['type']];
                if (expected) {
                    $.each(expected, function (i, field) {
                        if (!entry[field] && entry[field] != '') {
                            warningsList.push({
                                type: 'missing field "' + field + '"',
                                fix: {
                                    description: 'add field', 'function': function () {
                                        entry[field] = '';
                                        return entry;
                                    }
                                }
                            });
                        }
                    });
                }
            }
            return warningsList;
        },

        computeTitleCapitalizationWarning: function (entry) {
            if (!entry) {
                return [];
            }
            var warningsList = [];
            $.each(['booktitle', 'journal'], function (i, field) {
                if (entry[field]) {
                    var value = entry[field];
                    var capitalizationCorrect = true;
                    var correctedValue = '';
                    $.each(value.split(' '), function (i, word) {
                        var capitalizedWord = word;
                        if (!word.match(/\d.*/)) {
                            if ((word.length >= 5 || i == 0) && word.toLowerCase() == word) {
                                capitalizationCorrect = false;
                                capitalizedWord = word.charAt(0).toUpperCase() + word.substring(1);
                            }
                        }
                        correctedValue += (correctedValue ? ' ' : '') + capitalizedWord;
                    });
                    if (!capitalizationCorrect) {
                        warningsList.push({
                            type: 'capitalization in field "' + field + '"',
                            fix: {
                                description: 'capitalize longer words', 'function': function () {
                                    entry[field] = correctedValue;
                                    return entry;
                                }
                            }
                        });
                    }
                }
            });
            return warningsList;
        },

        computeProtectedIdentifierCapitalizationWarning: function (entry) {
            if (!entry) {
                return [];
            }
            var warningsList = [];
            $.each(['title'], function (i, field) {
                if (entry[field]) {
                    var value = entry[field];
                    var capitalizationCorrect = true;
                    var correctedValue = value;
                    if (value.indexOf('{') < 0) {
                        $.each(value.split(/[\s,:\-()\/]+/), function (i, word) {
                            if (!word.startsWith('{')) {
                                var subword = word.substring(1);
                                if (subword.length > 0 && subword.toLowerCase() != subword) {
                                    capitalizationCorrect = false;
                                    var re = new RegExp('\{?'+word+'\}?','g');
                                    correctedValue = correctedValue.replace(re, '{'+word+'}');
                                }
                            }
                        });
                        if (!capitalizationCorrect) {
                            // warningsList.push('non-protected capitalization of identifier in field "' + field + '"');
                            warningsList.push({
                                type: 'non-protected capitalization of identifier in field "' + field + '"',
                                fix: {
                                    description: 'protect identifiers', 'function': function () {
                                        entry[field] = correctedValue;
                                        return entry;
                                    }
                                }
                            });
                        }
                    }
                }
            });
            return warningsList;
        }

    };

    function computeEmptyFieldWarning(warningsList, field, value) {
        if (!value) {
            warningsList.push('empty field "' + field + '"');
        }
    }

    function computeFirstNameUnknown(warningsList, field, value) {
        if (field === 'author' || field === 'editor') {
            var firstNameKnown = true;
            $.each(value.split(' and '), function (i, name) {
                var parsedName = name.trim().split(',');
                if (parsedName.length > 1) {
                    var firstName = parsedName[1].trim().split(' ')[0].trim();
                    if (firstName.indexOf('.') > 0 || firstName.length < 2) {
                        firstNameKnown = false;
                    }
                } else {
                    firstNameKnown = false;
                }
            });
            if (!firstNameKnown) {
                warningsList.push('unknown or abbreviated first name in field "' + field + '"');
            }
        }
    }

    function computeWholeFieldCapitalizationProtected(warningsList, field, value) {
        if (value.indexOf('{') == 0 && value.lastIndexOf('}') == value.length - 1 && value.length > 10) {
            warningsList.push('whole field "' + field + '" with protected capitalization');
        }
    }

})
();<|endoftext|>


<commit_before>import debounce from 'lodash.debounce';
import { bypassCSPForImages } from './github';

// brfs doesn't work with ES6 import syntax
// https://github.com/substack/brfs/issues/39
const fs = require('fs');
const widgetTemplate = fs.readFileSync('src/giphy-widget.html', 'utf8');
const hiddenClass = 'giphy-widget-hidden';

export default {
    create(...args) {
        return Object.create(this).init(...args);
    },

    init({ onSelection, onDispose }) {
        const $widget = this.$widget = $(widgetTemplate);
        this.$input = $widget.find('input');
        this.$imgList = $widget.find('.js-gif-list');
        this.onSelection = onSelection;
        this.onDispose = onDispose;
        return this.setupListeners();
    },

    appendToDOM(selector = 'body') {
        $(selector).append(this.$widget);
        return this;
    },

    setupListeners() {
        this.$input.on('keydown', debounce(e => {
            this.$imgList.empty();
            this.toggleLoading(true);
            window.postMessage({
                giphySearch: true,
                query: e.currentTarget.value
            }, '*');
        }, 1000));

        this.$widget.on('click', 'img', e => this.imageSelected(e.currentTarget));

        window.addEventListener('message', ({ data }) => {
            if (data && data.giphyResponse) this.onImageData(data);
        });

        return this;
    },

    onImageData(data) {
        if (this.disposed) return;

        this.toggleLoading(false);
        const images = data.res.data.map(image => ({
            uri: image.images.original.url,
            name: image.slug
        }));

        bypassCSPForImages(images)
            .then(imgList => this.updateImageList(imgList))
            .catch(err => console.error(err));
    },

    imageSelected(img) {
        this.onSelection({
            uri: img.src,
            name: img.title
        });
        this.dispose();
    },

    showAt(top = 0, left = 0) {
        this.$widget.removeClass(hiddenClass).css({ top, left });
        return this;
    },

    dispose() {
        this.$widget.remove();
        this.$widget = null;
        this.$input = null;
        this.$imgList = null;
        this.disposed = true;
        this.onDispose();
    },

    toggleLoading(show) {
        const action = show ? 'removeClass' : 'addClass';
        this.$widget.find('.js-giphy-loading')[action](hiddenClass);
    },

    updateImageList(images = []) {
        const imageDOM = images.map(image => {
            return `<li><img src="${image.uri}" title="${image.name}"</li>`;
        }).join('');

        this.$imgList.html(imageDOM);
        return this;
    }
};
<commit_msg>Close when focus is lost<commit_after>import debounce from 'lodash.debounce';
import { bypassCSPForImages } from './github';

// brfs doesn't work with ES6 import syntax
// https://github.com/substack/brfs/issues/39
const fs = require('fs');
const widgetTemplate = fs.readFileSync('src/giphy-widget.html', 'utf8');
const hiddenClass = 'giphy-widget-hidden';

export default {
    create(...args) {
        return Object.create(this).init(...args);
    },

    init({ onSelection, onDispose }) {
        const $widget = this.$widget = $(widgetTemplate);
        this.$input = $widget.find('input');
        this.$imgList = $widget.find('.js-gif-list');
        this.onSelection = onSelection;
        this.onDispose = onDispose;
        return this.setupListeners();
    },

    appendToDOM(selector = 'body') {
        $(selector).append(this.$widget);
        return this;
    },

    setupListeners() {
        this.$input.on('keydown', debounce(e => {
            this.$imgList.empty();
            this.toggleLoading(true);
            window.postMessage({
                giphySearch: true,
                query: e.currentTarget.value
            }, '*');
        }, 1000));

        this.$widget.on('click', 'img', e => this.imageSelected(e.currentTarget));

        window.addEventListener('message', ({ data }) => {
            if (data && data.giphyResponse) this.onImageData(data);
        });

        $(document).on('click.giphy', e => {
            if (this.$widget.get(0).contains(e.target)) return;
            this.dispose();
        });

        return this;
    },

    onImageData(data) {
        if (this.disposed) return;

        this.toggleLoading(false);
        const images = data.res.data.map(image => ({
            uri: image.images.original.url,
            name: image.slug
        }));

        bypassCSPForImages(images)
            .then(imgList => this.updateImageList(imgList))
            .catch(err => console.error(err));
    },

    imageSelected(img) {
        this.onSelection({
            uri: img.src,
            name: img.title
        });
        this.dispose();
    },

    showAt(top = 0, left = 0) {
        this.$widget.removeClass(hiddenClass).css({ top, left });
        return this;
    },

    dispose() {
        $(document).off('click.giphy');
        this.$widget.remove();
        this.disposed = true;
        this.onDispose();
    },

    toggleLoading(show) {
        const action = show ? 'removeClass' : 'addClass';
        this.$widget.find('.js-giphy-loading')[action](hiddenClass);
    },

    updateImageList(images = []) {
        const imageDOM = images.map(image => {
            return `<li><img src="${image.uri}" title="${image.name}"</li>`;
        }).join('');

        this.$imgList.html(imageDOM);
        return this;
    }
};
<|endoftext|>


<commit_before>// run test when changing related file using
// $ TESTING=1 node_modules/jasmine/bin/jasmine.js spec/ParseGlobalConfig.spec.js

var auth = require('../Auth');
var cache = require('../cache');
var Config = require('../Config');
var DatabaseAdapter = require('../DatabaseAdapter');
var Parse = require('parse/node').Parse;
var rest = require('../rest');

var config = new Config('test');
var database = DatabaseAdapter.getDatabaseConnection('test');

describe('GlobalConfig', () => {
  beforeEach(function() {
    database.create('_GlobalConfig', { objectId: 1, params: { mostValuableCompany: 'Apple' } }, {});
  });

  it('find existing values', (done) => {
    rest.find(config, auth.nobody(config), '_GlobalConfig', 1)
    .then(() => {
      return database.mongoFind('_GlobalConfig', {}, {});
    }).then((results) => {
      expect(results.length).toEqual(1);
      var obj = results[0];
      expect(obj.params.mostValuableCompany).toEqual('Apple');
      done();
    }).catch((error) => { console.log(error); });
  });

  it('update with a new value', (done) => {
    var input = {
      params: {
        mostValuableCompany: 'Alphabet'
      }
    };
    rest.update(config, auth.nobody(config), '_GlobalConfig', 1, input)
    .then(() => {
      return database.mongoFind('_GlobalConfig', {}, {});
    }).then((results) => {
      expect(results.length).toEqual(1);
      var obj = results[0];
      expect(obj.params.mostValuableCompany).toEqual('Alphabet');
      done();
    }).catch((error) => { console.log(error); });
  });

});
<commit_msg>Remove unnecessary comment about testing<commit_after>
var auth = require('../Auth');
var cache = require('../cache');
var Config = require('../Config');
var DatabaseAdapter = require('../DatabaseAdapter');
var Parse = require('parse/node').Parse;
var rest = require('../rest');

var config = new Config('test');
var database = DatabaseAdapter.getDatabaseConnection('test');

describe('GlobalConfig', () => {
  beforeEach(function() {
    database.create('_GlobalConfig', { objectId: 1, params: { mostValuableCompany: 'Apple' } }, {});
  });

  it('find existing values', (done) => {
    rest.find(config, auth.nobody(config), '_GlobalConfig', 1)
    .then(() => {
      return database.mongoFind('_GlobalConfig', {}, {});
    }).then((results) => {
      expect(results.length).toEqual(1);
      var obj = results[0];
      expect(obj.params.mostValuableCompany).toEqual('Apple');
      done();
    }).catch((error) => { console.log(error); });
  });

  it('update with a new value', (done) => {
    var input = {
      params: {
        mostValuableCompany: 'Alphabet'
      }
    };
    rest.update(config, auth.nobody(config), '_GlobalConfig', 1, input)
    .then(() => {
      return database.mongoFind('_GlobalConfig', {}, {});
    }).then((results) => {
      expect(results.length).toEqual(1);
      var obj = results[0];
      expect(obj.params.mostValuableCompany).toEqual('Alphabet');
      done();
    }).catch((error) => { console.log(error); });
  });

});
<|endoftext|>


<commit_before>// Fullscreen canvas
function fc(fn, autorun, dimensions) {
  document.body.style.margin = "0px";
  document.body.style.padding = "0px";

  var canvas = document.createElement('canvas');
  document.body.appendChild(canvas);
  canvas.style.position = 'absolute';
  canvas.style.left = '0px';
  canvas.style.top = '0px';

  var ctx;
  dimensions = dimensions || 2;

  if (dimensions === 2) {
    ctx = canvas.getContext('2d');
  } else if (dimensions === 3) {
    ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  }

  if (!ctx) {
    return;
  }

  var last = 0, dirty = false, request;

  function tick(time) {
    time = time || 0;
    var delta = time-last;
    last = time;

    ctx.reset();

    dimensions === 2 && ctx.save();
    fn && fn(delta);
    dimensions === 2 && ctx.restore();
    if (autorun !== false) {
      requestAnimationFrame(tick);
    }
    dirty = false;
  }

  if (dimensions === 2) {
    ctx.reset = function() {
      canvas.width = 0;
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    };

    ctx.clear = function(color) {
      var orig = ctx.fillStyle;
      ctx.fillStyle = color || "#223";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.fillStyle = orig;
    };
  } else {
    ctx.reset = function() {
      if (canvas.width !== window.innerWidth) {
        canvas.width = window.innerWidth;
      }

      if (canvas.height !== window.innerHeight) {
        canvas.height = window.innerHeight;
      }
    }
  }

  setTimeout(tick, 0);

  ctx.dirty = function() {
    if (!dirty) {
      request = requestAnimationFrame(tick);
      dirty = true;
    }
  };

  ctx.stop = function() {
    autorun = false;
    dirty = false;
    request && cancelAnimcationFrame(request);
  };

  ctx.start = function() {
    autorun = true;
    requestAnimationFrame(tick);
  };

  (window.attachEvent || window.addEventListener)('resize', ctx.dirty);

  ctx.canvas = canvas;
  return ctx;
};

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
  module.exports = fc;
}

if (typeof window !== 'undefined') {
  window.fc = window.fc || fc;
}
<commit_msg>fix typo<commit_after>// Fullscreen canvas
function fc(fn, autorun, dimensions) {
  document.body.style.margin = "0px";
  document.body.style.padding = "0px";

  var canvas = document.createElement('canvas');
  document.body.appendChild(canvas);
  canvas.style.position = 'absolute';
  canvas.style.left = '0px';
  canvas.style.top = '0px';

  var ctx;
  dimensions = dimensions || 2;

  if (dimensions === 2) {
    ctx = canvas.getContext('2d');
  } else if (dimensions === 3) {
    ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  }

  if (!ctx) {
    return;
  }

  var last = 0, dirty = false, request;

  function tick(time) {
    time = time || 0;
    var delta = time-last;
    last = time;

    ctx.reset();

    dimensions === 2 && ctx.save();
    fn && fn(delta);
    dimensions === 2 && ctx.restore();
    if (autorun !== false) {
      requestAnimationFrame(tick);
    }
    dirty = false;
  }

  if (dimensions === 2) {
    ctx.reset = function() {
      canvas.width = 0;
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    };

    ctx.clear = function(color) {
      var orig = ctx.fillStyle;
      ctx.fillStyle = color || "#223";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.fillStyle = orig;
    };
  } else {
    ctx.reset = function() {
      if (canvas.width !== window.innerWidth) {
        canvas.width = window.innerWidth;
      }

      if (canvas.height !== window.innerHeight) {
        canvas.height = window.innerHeight;
      }
    }
  }

  setTimeout(tick, 0);

  ctx.dirty = function() {
    if (!dirty) {
      request = requestAnimationFrame(tick);
      dirty = true;
    }
  };

  ctx.stop = function() {
    autorun = false;
    dirty = false;
    request && cancelAnimationFrame(request);
  };

  ctx.start = function() {
    autorun = true;
    requestAnimationFrame(tick);
  };

  (window.attachEvent || window.addEventListener)('resize', ctx.dirty);

  ctx.canvas = canvas;
  return ctx;
};

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
  module.exports = fc;
}

if (typeof window !== 'undefined') {
  window.fc = window.fc || fc;
}
<|endoftext|>


<commit_before>describe("Configured gadget", function() {
  var gadget_window, getString;

  beforeEach(function() {
    loadFixtures('gadget.html');

    window.google = {};

    var contentmatch = {getContentMatches: function(){} };
    spyOn(contentmatch,'getContentMatches').andReturn( [ {subject: "An email subject"} ] );
    window.google.contentmatch = contentmatch;

    getString  = jasmine.createSpy().andReturn("dupa");
    var Prefs =  function() {
      this.getString = getString;
    };

    gadget_window = {
      adjustHeight: jasmine.createSpy('window')
    };

    window.gadgets = {
      Prefs: Prefs,
      'window': gadget_window,
      io: {
	makeRequest: jasmine.createSpy('makeRequest'),
	ContentType: {
	  DOM: 'DOM'
	},
	MethodType: {
	  POST: 'POST',
	  PUT: 'PUT'
	},
	RequestParameters: {
	  METHOD: 'METHOD',
	  HEADERS: 'HEADERS',
	  CONTENT_TYPE: 'CONTENT_TYPE',
	  POST_DATA: 'POST_DATA'
	}
      }
    };

    window.initializeGeepivoGadget();
  });

  it("should read settings", function() {
    expect(getString).toHaveBeenCalled();
  });

  it("should adjust height to 32", function() {
    expect(getString).toHaveBeenCalled();
  });

  it("should post XML story to Tracker", function() {
    $('button.create_story_button').click();

    expect(window.gadgets.io.makeRequest.callCount).toEqual(1);

    var args = window.gadgets.io.makeRequest.mostRecentCall.args;
    expect(args.shift()).toEqual('https://www.pivotaltracker.com/services/v3/projects/dupa/stories');

    var callback = args.shift();
    expect(typeof callback).toEqual('function');

    expect( args.shift() ).toEqual({
      METHOD: 'POST',
      HEADERS: { 'X-TrackerToken' : 'dupa', 'Content-type' : 'application/xml' },
      CONTENT_TYPE: 'DOM',
      POST_DATA: "<story>\n  <project_id>dupa</project_id>\n  <story_type>dupa</story_type>\n  <name>An email subject</name>\n  <integration_id>dupa</integration_id>\n  <requested_by>dupa</requested_by>\n  <owned_by>dupa</owned_by>\n</story>"
    });
  });

  it("should display story link when callback called with success message", function() {
    $('button.create_story_button').click();

    expect(window.gadgets.io.makeRequest.callCount).toEqual(1);
    var callback = window.gadgets.io.makeRequest.mostRecentCall.args[1];

    story_data = "<story><url>http://tracker/story/555</url><id>555</id></story>";
    response_data = {
      rc: 201,
      text: story_data
    };

    callback(response_data);

    expect( $(".notification_area").html() ).toEqual('http://tracker/story/555');

  });

  it("should show error message callback called with error message", function() {
    $('button.create_story_button').click();

    expect(window.gadgets.io.makeRequest.callCount).toEqual(1);
    var callback = window.gadgets.io.makeRequest.mostRecentCall.args[1];

    response_data = { rc: 500, text: '' };
    callback(response_data);

    expect( $(".notification_area").html() ).toEqual('Error creating story');
  });

});
<commit_msg>Differentiate setting values<commit_after>describe("Configured gadget", function() {
  var gadget_window, getString;

  beforeEach(function() {
    loadFixtures('gadget.html');

    window.google = {};

    var contentmatch = {getContentMatches: function(){} };
    spyOn(contentmatch,'getContentMatches').andReturn( [ {subject: "An email subject"} ] );
    window.google.contentmatch = contentmatch;

    var Prefs =  function() {
      this.getString = function(key) {
	return key + '_value';
      };
    };

    gadget_window = {
      adjustHeight: jasmine.createSpy('window')
    };

    window.gadgets = {
      Prefs: Prefs,
      'window': gadget_window,
      io: {
	makeRequest: jasmine.createSpy('makeRequest'),
	ContentType: {
	  DOM: 'DOM'
	},
	MethodType: {
	  POST: 'POST',
	  PUT: 'PUT'
	},
	RequestParameters: {
	  METHOD: 'METHOD',
	  HEADERS: 'HEADERS',
	  CONTENT_TYPE: 'CONTENT_TYPE',
	  POST_DATA: 'POST_DATA'
	}
      }
    };

    window.initializeGeepivoGadget();
  });

  xit("should adjust height to 32", function() {
    expect(getString).toHaveBeenCalled();
  });

  it("should post XML story to Tracker", function() {
    $('button.create_story_button').click();

    expect(window.gadgets.io.makeRequest.callCount).toEqual(1);

    var args = window.gadgets.io.makeRequest.mostRecentCall.args;
    expect(args.shift()).toEqual('https://www.pivotaltracker.com/services/v3/projects/project_id_value/stories');

    var callback = args.shift();
    expect(typeof callback).toEqual('function');

    expect( args.shift() ).toEqual({
      METHOD: 'POST',
      HEADERS: { 'X-TrackerToken' : 'pivotal_api_token_value', 'Content-type' : 'application/xml' },
      CONTENT_TYPE: 'DOM',
      POST_DATA: "<story>\n  <project_id>project_id_value</project_id>\n  <story_type>story_type_value</story_type>\n  <name>An email subject</name>\n  <integration_id>integration_id_value</integration_id>\n  <requested_by>requested_by_value</requested_by>\n  <owned_by>owned_by_value</owned_by>\n</story>"
    });
  });

  it("should display story link when callback called with success message", function() {
    $('button.create_story_button').click();

    expect(window.gadgets.io.makeRequest.callCount).toEqual(1);
    var callback = window.gadgets.io.makeRequest.mostRecentCall.args[1];

    story_data = "<story><url>http://tracker/story/555</url><id>555</id></story>";
    response_data = {
      rc: 201,
      text: story_data
    };

    callback(response_data);

    expect( $(".notification_area").html() ).toEqual('http://tracker/story/555');

  });

  it("should show error message callback called with error message", function() {
    $('button.create_story_button').click();

    expect(window.gadgets.io.makeRequest.callCount).toEqual(1);
    var callback = window.gadgets.io.makeRequest.mostRecentCall.args[1];

    response_data = { rc: 500, text: '' };
    callback(response_data);

    expect( $(".notification_area").html() ).toEqual('Error creating story');
  });

});
<|endoftext|>


<commit_before>function response (link, err, result, callback) {

    if (err) {
        return callback ? callback(err) : link.send(err.statusCode || 500, err.toString());
    }

    if(!callback) {
        link.res.headers['content-type'] = 'application/json; charset=utf-8';
    }

    if (result.constructor.name === 'Cursor') {

        if (callback) {
            return callback(null, result);
        }

        // stream result
        var stream = result.stream();
        link.stream.start(200);

        stream.on('end', function() {
            link.stream.end();
        });

        stream.on('error', function(err) {
            link.stream.error(500, err.toString());
        });

        stream.on('data', function(data) {
            link.stream.data(data);
        });

    } else {
        callback ? callback(err, result) : link.send(200, result);
    }
}

function jointResponse (link, dbReq, cursor, callback) {

    cursor.toArray(function (err, result) {

        if (err) {
            return callback ? callback(err) : link.send(err.statusCode || 500, err.toString());
        }

        // don't merge if no doucments are found
        if (result.length === 0) {
            return callback ? callback(err, result) : link.send(200, result);
        }

        var current = 0;
        for (var joint in dbReq.joints) {

            // set limit to length of result
            dbReq.joints[joint].options.limit = result.length;

            // get ids from linked fields
            var uniqueId = {};
            dbReq.joints[joint].query = {_id: {$in: []}};
            for (var i = 0, l = result.length; i < l; ++i) {
                for (var mergeField in dbReq.joints[joint].merge) {
                    if (!uniqueId[result[i][mergeField]] && result[i][mergeField]) {
                        uniqueId[result[i][mergeField]] = 1;
                        dbReq.joints[joint].query._id.$in.push(result[i][mergeField]);
                    }
                }
            }

            // get linked data
            (function (jointDbReq) {
                jointDbReq.template.collection.find(jointDbReq.query, jointDbReq.options, function (err, cursor) {

                    if (err) {
                        return ++crrent;
                    }

                    cursor.toArray(function (err, jointResult) {

                        if (err) {
                            return ++current;
                        }

                        // merge linkd data
                        for (var i = 0, l = result.length; i < l; ++i) {
                            for (var field in jointDbReq.merge) {
                                if (result[i][field]) {

                                    // set and emtpy object if no jointResults are found
                                    if (jointResult.length === 0) {
                                        result[i][field] = {};
                                        continue;
                                    }

                                    for (var ii = 0, ll = jointResult.length; i < l; ++i) {
                                        // find id in joint results
                                        if (jointResult[ii]._id.toString() === result[i][field].toString()) {
                                            // merge linked data in result field
                                            result[i][field] = jointResult[ii];
                                        }
                                    }
                                }
                            }
                        }

                        if (++current === dbReq.jointsLength) {
                            callback ? callback(err, result) : link.send(200, result);
                        }
                    });
                });
            })(dbReq.joints[joint]);
        }
    });
}

function hasAccess (link, req, access) {
    req.template = req.template || { "roles": {} };

    if (!link) {
        return true;
    }

    if (!link.session || !link.session.crudRole) {
        return false;
    }

    if (req.template.roles && req.template.roles[link.session.crudRole] < access) {
        return false;
    }

    return true;
}

// read
exports.find = function (link, dbReq, callback) {

    if (!hasAccess(link, dbReq, 1)) { return link.send(403, "Access denied."); }

    dbReq.template.collection.find(dbReq.query, dbReq.options, function (err, cursor) {

        var countOptions = JSON.parse(JSON.stringify(dbReq.options));

        delete countOptions.limit;

        dbReq.template.collection.count(dbReq.query, countOptions, function (countErr, count) {

            if (link && !countErr) {
                link.res.headers['X-Mono-CRUD-Count'] = count.toString();
            }

                // merge linked data in result data
            if (!err && dbReq.joints) {
                return jointResponse(link, dbReq, cursor, callback);
            }

            response(link, err, cursor, callback);
        });
    });
};

// write
exports.update = function (link, dbReq, callback) {
    if (!hasAccess(link, dbReq, 2)) { return link.send(403, "Access denied."); }

    dbReq.template.collection.update(dbReq.query, dbReq.data, dbReq.options, function (err, updItem) {
        response(link, err, updItem, callback);
    });
};

exports.insert = function (link, dbReq, callback) {
    if (!hasAccess(link, dbReq, 2)) { return link.send(403, "Access denied."); }

    dbReq.template.collection.insert(dbReq.data, dbReq.options, function (err, newItem) {
        response(link, err, newItem, callback);
    });
};

exports.remove = function (link, dbReq, callback) {
    if (!hasAccess(link, dbReq, 3)) { return link.send(403, "Access denied."); }

    dbReq.template.collection.remove(dbReq.query, dbReq.options, function (err, numOfRmDocs) {
        response(link, err, numOfRmDocs, callback);
    });
};
<commit_msg>do not send options for count operation<commit_after>function response (link, err, result, callback) {

    if (err) {
        return callback ? callback(err) : link.send(err.statusCode || 500, err.toString());
    }

    if(!callback) {
        link.res.headers['content-type'] = 'application/json; charset=utf-8';
    }

    if (result.constructor.name === 'Cursor') {

        if (callback) {
            return callback(null, result);
        }

        // stream result
        var stream = result.stream();
        link.stream.start(200);

        stream.on('end', function() {
            link.stream.end();
        });

        stream.on('error', function(err) {
            link.stream.error(500, err.toString());
        });

        stream.on('data', function(data) {
            link.stream.data(data);
        });

    } else {
        callback ? callback(err, result) : link.send(200, result);
    }
}

function jointResponse (link, dbReq, cursor, callback) {

    cursor.toArray(function (err, result) {

        if (err) {
            return callback ? callback(err) : link.send(err.statusCode || 500, err.toString());
        }

        // don't merge if no doucments are found
        if (result.length === 0) {
            return callback ? callback(err, result) : link.send(200, result);
        }

        var current = 0;
        for (var joint in dbReq.joints) {

            // set limit to length of result
            dbReq.joints[joint].options.limit = result.length;

            // get ids from linked fields
            var uniqueId = {};
            dbReq.joints[joint].query = {_id: {$in: []}};
            for (var i = 0, l = result.length; i < l; ++i) {
                for (var mergeField in dbReq.joints[joint].merge) {
                    if (!uniqueId[result[i][mergeField]] && result[i][mergeField]) {
                        uniqueId[result[i][mergeField]] = 1;
                        dbReq.joints[joint].query._id.$in.push(result[i][mergeField]);
                    }
                }
            }

            // get linked data
            (function (jointDbReq) {
                jointDbReq.template.collection.find(jointDbReq.query, jointDbReq.options, function (err, cursor) {

                    if (err) {
                        return ++crrent;
                    }

                    cursor.toArray(function (err, jointResult) {

                        if (err) {
                            return ++current;
                        }

                        // merge linkd data
                        for (var i = 0, l = result.length; i < l; ++i) {
                            for (var field in jointDbReq.merge) {
                                if (result[i][field]) {

                                    // set and emtpy object if no jointResults are found
                                    if (jointResult.length === 0) {
                                        result[i][field] = {};
                                        continue;
                                    }

                                    for (var ii = 0, ll = jointResult.length; i < l; ++i) {
                                        // find id in joint results
                                        if (jointResult[ii]._id.toString() === result[i][field].toString()) {
                                            // merge linked data in result field
                                            result[i][field] = jointResult[ii];
                                        }
                                    }
                                }
                            }
                        }

                        if (++current === dbReq.jointsLength) {
                            callback ? callback(err, result) : link.send(200, result);
                        }
                    });
                });
            })(dbReq.joints[joint]);
        }
    });
}

function hasAccess (link, req, access) {
    req.template = req.template || { "roles": {} };

    if (!link) {
        return true;
    }

    if (!link.session || !link.session.crudRole) {
        return false;
    }

    if (req.template.roles && req.template.roles[link.session.crudRole] < access) {
        return false;
    }

    return true;
}

// read
exports.find = function (link, dbReq, callback) {

    if (!hasAccess(link, dbReq, 1)) { return link.send(403, "Access denied."); }

    dbReq.template.collection.find(dbReq.query, dbReq.options, function (err, cursor) {

        // why do we need options for count?
        //var countOptions = JSON.parse(JSON.stringify(dbReq.options));
        //delete countOptions.limit;

        dbReq.template.collection.count(dbReq.query, function (countErr, count) {

            if (link && !countErr) {
                link.res.headers['X-Mono-CRUD-Count'] = count.toString();
            }

                // merge linked data in result data
            if (!err && dbReq.joints) {
                return jointResponse(link, dbReq, cursor, callback);
            }

            response(link, err, cursor, callback);
        });
    });
};

// write
exports.update = function (link, dbReq, callback) {
    if (!hasAccess(link, dbReq, 2)) { return link.send(403, "Access denied."); }

    dbReq.template.collection.update(dbReq.query, dbReq.data, dbReq.options, function (err, updItem) {
        response(link, err, updItem, callback);
    });
};

exports.insert = function (link, dbReq, callback) {
    if (!hasAccess(link, dbReq, 2)) { return link.send(403, "Access denied."); }

    dbReq.template.collection.insert(dbReq.data, dbReq.options, function (err, newItem) {
        response(link, err, newItem, callback);
    });
};

exports.remove = function (link, dbReq, callback) {
    if (!hasAccess(link, dbReq, 3)) { return link.send(403, "Access denied."); }

    dbReq.template.collection.remove(dbReq.query, dbReq.options, function (err, numOfRmDocs) {
        response(link, err, numOfRmDocs, callback);
    });
};
<|endoftext|>