<commit_before>var calc = function () {
  Number.radix = parseInt(location.hash.slice(1)) || 10
  calc.refresh()
  document.body === calc.display.parentNode || document.body.appendChild(calc.display)
  document.body === calc.keypad .parentNode || document.body.appendChild(calc.keypad)
}

!function () {

var
set = function (a) {
  e.value = a; e.data.textContent = a.toString()
},
reset = function () {
  delete e.value; e.data.textContent = '0'
},
bs = function () {
  var _ = e.data.textContent.slice(0, -1)

  e.data.textContent = _ === '' ? '0' : _
},
fix = function () {
  e.value = e.value || new Adele(parseInt(e.data.textContent, Number.radix))
},
focus = function () {
  e.classList.remove('focus')
  e = this
  e.classList.add('focus')
},
makeCell = function () {
  var
  cell = html.tr(),
  data = html.td()

  cell.appendChild(data)
  data.textContent = '0'
  cell[touch] = cell.focus = focus
  cell.data = data

  return cell
},
refresh = function () {
  var _ = calc.display.firstChild

  while (_) {
    _.value && (_.data.textContent = _.value.toString())
    _ = _.nextSibling
  }
},
push = function () {
  e.parentNode.insertBefore(makeCell(), e.nextSibling)
  e.nextSibling.focus()
},
pop = function () {
  var _ = e.value

  if (e.previousSibling) {
    e.previousSibling.focus()
    e.parentNode.removeChild(e.nextSibling)
  }

  return _
},
numeric = function () {
  var _ = this.textContent, __

  e.value && push()
  __ = e.data
  __.textContent = (__.textContent === '0' ? '' : __.textContent) + _
},
touch = document.createElement('div').hasOwnProperty('ontouchend') ? 'ontouchend' : 'onmouseup',
html = {}, func = {}, e

10 .forEach(function (i) {
  func[i] = numeric
})
func['.'] = function() {
  e.value && push()
  e.data.textContent += '.'
}
func['↑'] = function () {
  var _ = e.value

  _ ? push() : (_ = new Adele(parseInt(e.data.textContent, Number.radix)))
  set(_)
}
func['↓'] = function () {
  e.previousSibling ? pop() : reset()
}
func['←'] = function () {
  e.value ? reset() : bs()
}
func['ˆ'] = function () {
  var _

  if (e.previousSibling) {
    fix(); _ = pop(); set(e.value ? e.value.pow(_) : _)
  }
}
func['↕'] = function () {
  fix()
  if (e.previousSibling) {
    e.parentNode.insertBefore(e, e.previousSibling)
    e.nextSibling.focus()
  }
}
func['↔'] = function () {
  Number.isLittle = ! Number.isLittle
  refresh()
}
func['/'] = function () {
  var _

  fix(); _ = e.value
  _.isZero() || set(_.inv())
}
func['−'] = function () {
  fix(); set(e.value.neg())
}
func['\\'] = function () {
  var _

  fix(); _ = e.value
  _.isUnit() || set(_.isZero() ? new Adele(_.n) : _.res())
}
func[' '] = function () {
  var _

  if (e.previousSibling) {
    fix(); _ = pop(); set(e.value ? e.value.mul(_) : _)
  }
}
func['+'] = function () {
  var _

  if (e.previousSibling) {
    fix(); _ = pop(); set(e.value ? e.value.add(_) : _)
  }
}
func[':'] = function () {
  var _, __, p

  fix(); _ = e.value

  if (_.isZero() || _.isUnit()) {
    // do nothing
  } else
  if (_.isBody()) {
    // prime factorization
    __ = _.factor(); p = __[0]; _ = __[1]
    set(p)
    if (!_.isUnity()) {
      push(); set(_)
    }
  } else
  {
    // ub factorization
    set(_.body()); push(); set(_.unit())
  }
}
func['..'] = function () {
  var _

  fix(); _ = e.value
  if (_.n === 0) {
    // do nothing
  } else
  if (!_.isZero()) {
    set(new Adele(_.r, _.s)); push()
    set(new Adele(0, 1, _.n))
  }
}

;['tr', 'td', 'table'].forEach(function (a) {
  html[a] = function () {
    return document.createElement(a)
  }
})

calc.display = html.table()
calc.keypad  = html.table()
;[
  ['↑', '↓', '←', '7', '8', '9'],
  ['ˆ', '↕', '↔', '4', '5', '6'],
  [':', ' ', '/', '1', '2', '3'],
  ['..', '+', '−', '0', '.', '\\']
].forEach(function (tds) {
  var tr = html.tr()

  tds.forEach(function (td) {
    var _ = html.td()

    _.textContent = td
    _[touch] = func[td]
    tr.appendChild(_)
  })
  calc.keypad.appendChild(tr)
})
calc.keypad.classList.add('keypad')
e = makeCell()
calc.display.appendChild(e)
calc.display.classList.add('display')
calc.refresh = refresh

}()

onload = onhashchange = calc
<commit_msg>Update adele.js<commit_after>var calc = function () {
  Number.radix = parseInt(location.hash.slice(1)) || 10
  calc.refresh()
  document.body === calc.display.parentNode || document.body.appendChild(calc.display)
  document.body === calc.keypad .parentNode || document.body.appendChild(calc.keypad)
}

!function () {

var
set = function (a) {
  e.value = a; e.data.textContent = a.toString()
},
reset = function () {
  delete e.value; e.data.textContent = '0'
},
bs = function () {
  var _ = e.data.textContent.slice(0, -1)

  e.data.textContent = _ === '' ? '0' : _
},
fix = function () {
  e.value = e.value || Number.parse(e.data.textContent)
},
focus = function () {
  e.classList.remove('focus')
  e = this
  e.classList.add('focus')
},
makeCell = function () {
  var
  cell = html.tr(),
  data = html.td()

  cell.appendChild(data)
  data.textContent = '0'
  cell[touch] = cell.focus = focus
  cell.data = data

  return cell
},
refresh = function () {
  var _ = calc.display.firstChild

  while (_) {
    _.value && (_.data.textContent = _.value.toString())
    _ = _.nextSibling
  }
},
push = function () {
  e.parentNode.insertBefore(makeCell(), e.nextSibling)
  e.nextSibling.focus()
},
pop = function () {
  var _ = e.value

  if (e.previousSibling) {
    e.previousSibling.focus()
    e.parentNode.removeChild(e.nextSibling)
  }

  return _
},
numeric = function () {
  var _ = this.textContent, __

  e.value && push()
  __ = e.data
  __.textContent = (__.textContent === '0' ? '' : __.textContent) + _
},
touch = document.createElement('div').hasOwnProperty('ontouchend') ? 'ontouchend' : 'onmouseup',
html = {}, func = {}, e

10 .forEach(function (i) {
  func[i] = numeric
})
func['.'] = function() {
  e.value && push()
  e.data.textContent += '.'
}
func['↑'] = function () {
  var _ = e.value

  _ ? push() : (_ = Number.parse(e.data.textContent))
  set(_)
}
func['↓'] = function () {
  e.previousSibling ? pop() : reset()
}
func['←'] = function () {
  e.value ? reset() : bs()
}
func['ˆ'] = function () {
  var _

  if (e.previousSibling) {
    fix(); _ = pop(); set(e.value ? e.value.pow(_) : _)
  }
}
func['↕'] = function () {
  fix()
  if (e.previousSibling) {
    e.parentNode.insertBefore(e, e.previousSibling)
    e.nextSibling.focus()
  }
}
func['↔'] = function () {
  Number.isLittle = ! Number.isLittle
  refresh()
}
func['/'] = function () {
  var _

  fix(); _ = e.value
  _.isZero() || set(_.inv())
}
func['−'] = function () {
  fix(); set(e.value.neg())
}
func['\\'] = function () {
  var _

  fix(); _ = e.value
  _.isUnit() || set(_.isZero() ? new Adele(_.n) : _.res())
}
func[' '] = function () {
  var _

  if (e.previousSibling) {
    fix(); _ = pop(); set(e.value ? e.value.mul(_) : _)
  }
}
func['+'] = function () {
  var _

  if (e.previousSibling) {
    fix(); _ = pop(); set(e.value ? e.value.add(_) : _)
  }
}
func[':'] = function () {
  var _, __, p

  fix(); _ = e.value

  if (_.isZero() || _.isUnit()) {
    // do nothing
  } else
  if (_.isBody()) {
    // prime factorization
    __ = _.factor(); p = __[0]; _ = __[1]
    set(p)
    if (!_.isUnity()) {
      push(); set(_)
    }
  } else
  {
    // ub factorization
    set(_.body()); push(); set(_.unit())
  }
}
func['..'] = function () {
  var _

  fix(); _ = e.value
  if (_.n === 0) {
    // do nothing
  } else
  if (!_.isZero()) {
    set(new Adele(_.r, _.s)); push()
    set(new Adele(0, 1, _.n))
  }
}

;['tr', 'td', 'table'].forEach(function (a) {
  html[a] = function () {
    return document.createElement(a)
  }
})

calc.display = html.table()
calc.keypad  = html.table()
;[
  ['↑', '↓', '←', '7', '8', '9'],
  ['ˆ', '↕', '↔', '4', '5', '6'],
  [':', ' ', '/', '1', '2', '3'],
  ['..', '+', '−', '0', '.', '\\']
].forEach(function (tds) {
  var tr = html.tr()

  tds.forEach(function (td) {
    var _ = html.td()

    _.textContent = td
    _[touch] = func[td]
    tr.appendChild(_)
  })
  calc.keypad.appendChild(tr)
})
calc.keypad.classList.add('keypad')
e = makeCell()
calc.display.appendChild(e)
calc.display.classList.add('display')
calc.refresh = refresh

}()

onload = onhashchange = calc
<|endoftext|>


<commit_before>$('#breed-select').change(function() {
    let events = JSON.parse(localStorage.Events);

    if($('#breed-select').val() === 'Breed') {
      $('.event').show();
    } else {
      $('.event').hide();
      for(let i = 0; i < events.length; i++) {
        let event = events[i];
        let lowercaseBreed = event.breed.toLowerCase();
        let breedSelectLower = $('#breed-select').val().toLowerCase();

        if(lowercaseBreed === breedSelectLower) {
          $('.' + event.breed).show();
        }
      }
    }
  }
);

$('#size-select').change(function() {
    let events = JSON.parse(localStorage.Events);

    if($('#size-select').val() === 'Dog Size') {
      $('.event').show();
    } else {
      $('.event').hide();
      for(let i = 0; i < events.length; i++) {
        let event = events[i];
        let lowercaseBreed = event.dogSize.toLowerCase();
        let breedSelectLower = $('#size-select').val().toLowerCase();

        if(lowercaseBreed === breedSelectLower) {
          $('.' + event.dogSize).show();
        }
      }
    }
  }
);

$('#date-select').change(function() {
    let events = JSON.parse(localStorage.Events);

    if($('#date-select').val() === 'Date') {
      $('.event').show();
    } else {
      $('.event').hide();
      for(let i = 0; i < events.length; i++) {
        let today = new Date().toDateString();
        let event = events[i];

        let eventDate = event.date;
        let dateSelect = $('#date-select').val();

        let parseEventDate = Date.parse(eventDate);
        let parseToday = Date.parse(today);

        let difference = parseEventDate - parseToday;

        switch(dateSelect) {
          case 'Today':
            if (eventDate === today) {
              $('.' + event.dateString).show();
            }
            break;
          case 'This Week':
            if (difference <= 604800000) {
              $('.' + event.dateString).show();
            }
            break;
          case 'This Month':
            if (difference <= 2419200000) {
              $('.' + event.dateString).show();
            }
            break;
          default:
            break;
        }
      }
    }
  }
);

$('#price-select').change(function() {
    let events = JSON.parse(localStorage.Events);

    if($('#price-select').val() === 'Price') {
      $('.event').show();
    } else {
      $('.event').hide();
      for(let i = 0; i < events.length; i++) {
        let event = events[i];

        let eventPrice = event.price.toLowerCase();
        let eventPriceNumber = parseInt(event.price);
        let priceSelect = $('#price-select').val();

        switch(priceSelect) {
          case 'Free':
            if(eventPrice === 'free') {
              $('.' + event.price).show();
            }
            break;
          case '$':
            if(eventPriceNumber <= 10) {
              $('.' + event.price).show();
            }
            break;
          case '$$':
            if(eventPriceNumber <= 50 && eventPriceNumber > 10) {
              $('.' + event.price).show();
            }
            break;
          case '$$$':
            if(eventPriceNumber > 50) {
              $('.' + event.price).show();
            }
            break;
          default:
            break;
        }

      }
    }
  }
);
<commit_msg>hardcoded searching<commit_after>$('#breed-select').change(function() {
    let events = JSON.parse(localStorage.Events);

    if($('#breed-select').val() === 'Breed') {
      $('.event').show();
    } else {
      $('.event').hide();
      for(let i = 0; i < events.length; i++) {
        let event = events[i];
        let lowercaseBreed = event.breed.toLowerCase();
        let breedSelectLower = $('#breed-select').val().toLowerCase();

        if(lowercaseBreed === breedSelectLower) {
          $('.' + event.breed).show();
        }
      }
    }
  }
);

$('#searchevents').change(function() {
    $('.event').hide();
    $('.corgi').show();
});

$('#size-select').change(function() {
    let events = JSON.parse(localStorage.Events);

    if($('#size-select').val() === 'Dog Size') {
      $('.event').show();
    } else {
      $('.event').hide();
      for(let i = 0; i < events.length; i++) {
        let event = events[i];
        let lowercaseBreed = event.dogSize.toLowerCase();
        let breedSelectLower = $('#size-select').val().toLowerCase();

        if(lowercaseBreed === breedSelectLower) {
          $('.' + event.dogSize).show();
        }
      }
    }
  }
);

$('#date-select').change(function() {
    let events = JSON.parse(localStorage.Events);

    if($('#date-select').val() === 'Date') {
      $('.event').show();
    } else {
      $('.event').hide();
      for(let i = 0; i < events.length; i++) {
        let today = new Date().toDateString();
        let event = events[i];

        let eventDate = event.date;
        let dateSelect = $('#date-select').val();

        let parseEventDate = Date.parse(eventDate);
        let parseToday = Date.parse(today);

        let difference = parseEventDate - parseToday;

        switch(dateSelect) {
          case 'Today':
            if (eventDate === today) {
              $('.' + event.dateString).show();
            }
            break;
          case 'This Week':
            if (difference <= 604800000) {
              $('.' + event.dateString).show();
            }
            break;
          case 'This Month':
            if (difference <= 2419200000) {
              $('.' + event.dateString).show();
            }
            break;
          default:
            break;
        }
      }
    }
  }
);

$('#price-select').change(function() {
    let events = JSON.parse(localStorage.Events);

    if($('#price-select').val() === 'Price') {
      $('.event').show();
    } else {
      $('.event').hide();
      for(let i = 0; i < events.length; i++) {
        let event = events[i];

        let eventPrice = event.price.toLowerCase();
        let eventPriceNumber = parseInt(event.price);
        let priceSelect = $('#price-select').val();

        switch(priceSelect) {
          case 'Free':
            if(eventPrice === 'free') {
              $('.' + event.price).show();
            }
            break;
          case '$':
            if(eventPriceNumber <= 10) {
              $('.' + event.price).show();
            }
            break;
          case '$$':
            if(eventPriceNumber <= 50 && eventPriceNumber > 10) {
              $('.' + event.price).show();
            }
            break;
          case '$$$':
            if(eventPriceNumber > 50) {
              $('.' + event.price).show();
            }
            break;
          default:
            break;
        }

      }
    }
  }
);
<|endoftext|>


<commit_before>/* Facebook like page*/

(function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s); js.id = id;
    js.src = "//connect.facebook.net/fr_FR/sdk.js#xfbml=1&version=v2.4&appId=1534300023482847";
    fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));

/* Google analytics */

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-67287154-1', 'auto');
ga('send', 'pageview');

/* iframe loading function*/
function IFrameScroll(link){
    window.galleryIframe.location=link;
    window.location.hash='galleryIframe';
}

/* Navigation bar */

document.getElementById("nav").innerHTML =
    '
'+
    ''+
    '
'+
    '<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">'+
    'Toggle navigation'+
    ''+
    ''+
    ''+
    '</button>'+
    ''+
    'Feed Southern Africa'+
    '
'+
    ''+
    '
'+
    '
'+
    '
HOME
'+
    '
ABOUT
'+
    '
PROGRAMS
'+
    '
JOIN
'+
    '
RATES
'+
    '
CONTACT
'+
    '
'+
    'Gallery '+
    '
'+
    '
Program-1
'+
    '
Program-2
'+
    '
'+
    '
'+
    '
'+
    '
'+
    '
'
;

/* Footer */

document.getElementById("footer").innerHTML = '
'+
    '
'+
    '
'+
    '
' +
    '
' +
    '
' +
    'Feed Southern Africa' +
    '' +
    '
' +
    '
' +
    '
' +
    '
'+
    '
'+
    '
 ' +
    '©  ' + new Date().getFullYear() + ' Feed Southern Africa. All rights reserved.' +
    '
'+
    '
'+
    '
'+
    '
';

function ff(link){
    (window).load(    document.getElementById("galleryIframe").src=link

    )};<commit_msg>trying stuff<commit_after>/* Facebook like page*/

(function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s); js.id = id;
    js.src = "//connect.facebook.net/fr_FR/sdk.js#xfbml=1&version=v2.4&appId=1534300023482847";
    fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));

/* Google analytics */

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-67287154-1', 'auto');
ga('send', 'pageview');

/* iframe loading function*/
function IFrameScroll(link){
    window.galleryIframe.location=link;
    window.location.hash='galleryIframe';
}

/* Navigation bar */

document.getElementById("nav").innerHTML =
    '
'+
    ''+
    '
'+
    '<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">'+
    'Toggle navigation'+
    ''+
    ''+
    ''+
    '</button>'+
    ''+
    'Feed Southern Africa'+
    '
'+
    ''+
    '
'+
    '
'+
    '
HOME
'+
    '
ABOUT
'+
    '
PROGRAMS
'+
    '
JOIN
'+
    '
RATES
'+
    '
CONTACT
'+
    '
'+
    'Gallery '+
    '
'+
    '
Program-1
'+
    '
Program-2
'+
    '
'+
    '
'+
    '
'+
    '
'+
    '
'
;

/* Footer */

document.getElementById("footer").innerHTML = '
'+
    '
'+
    '
'+
    '
' +
    '
' +
    '
' +
    'Feed Southern Africa' +
    '' +
    '
' +
    '
' +
    '
' +
    '
'+
    '
'+
    '
 ' +
    '©  ' + new Date().getFullYear() + ' Feed Southern Africa. All rights reserved.' +
    '
'+
    '
'+
    '
'+
    '
';

function ff(link){
    (window).load(    document.getElementById("galleryIframe").src=link

    )};<|endoftext|>


<commit_before>/*
 * JSChannel (https://github.com/mozilla/jschannel) will be loaded prior to this
 * script. We will use it use to let JSInput call 'gradeFn', and eventually
 * 'stateGetter' & 'stateSetter' in the iframe's content even if it hasn't the
 * same origin, therefore bypassing SOP:
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript
 */

var JSInput = (function ($, undefined) {
    // Initialize js inputs on current page.
    // N.B.: No library assumptions about the iframe can be made (including,
    // most relevantly, jquery). Keep in mind what happens in which context
    // when modifying this file.

    // When all the problems are first loaded, we want to make sure the
    // constructor only runs once for each iframe; but we also want to make
    // sure that if part of the page is reloaded (e.g., a problem is
    // submitted), the constructor is called again.

    /*                      Utils                               */

    // Take a string and find the nested object that corresponds to it. E.g.:
    //    _deepKey(obj, "an.example") -> obj["an"]["example"]
    function _deepKey(obj, path){
        for (var i = 0, p=path.split('.'), len = p.length; i < len; i++){
            obj = obj[p[i]];
        }
        return obj;
    };

    /*      END     Utils                                   */

    function jsinputConstructor(elem) {
        // Define an class that will be instantiated for each jsinput element
        // of the DOM

        /*                      Private methods                          */

        var section = $(elem).parent().find('section[class="jsinput"]'),
            sectionAttr = function (e) { return $(section).attr(e); },
            iframe = $(elem).find('iframe[name^="iframe_"]').get(0),
            cWindow = iframe.contentWindow,
            path = iframe.src.substring(0, iframe.src.lastIndexOf("/")+1),
            // Get the hidden input field to pass to customresponse
            inputField = $(elem).parent().find('input[id^="input_"]'),
            // Get the grade function name
            gradeFn = sectionAttr("data"),
            // Get state getter
            stateGetter = sectionAttr("data-getstate"),
            // Get state setter
            stateSetter = sectionAttr("data-setstate"),
            // Get stored state
            storedState = sectionAttr("data-stored"),
            // Bypass single-origin policy only if this attribute is "false"
            // In that case, use JSChannel to do so.
            sop = sectionAttr("data-sop"),
            channel;

        sop = (sop !== "false");

        if (!sop) {
            channel = Channel.build({
                window: cWindow,
                origin: path,
                scope: "JSInput"
            });
         }

        /*                       Public methods                     */

        // Only one public method that updates the hidden input field.
        var update = function (callback) {
            var answer, state, store;

            if (sop) {
                answer = _deepKey(cWindow, gradeFn)();
                // Setting state presumes getting state, so don't get state
                // unless set state is defined.
                if (stateGetter && stateSetter) {
                    state = unescape(_deepKey(cWindow, stateGetter)());
                    store = {
                        answer: answer,
                        state:  state
                    };
                    inputField.val(JSON.stringify(store));
                } else {
                    inputField.val(answer);
                }
                callback();
            } else {
                channel.call({
                    method: "getGrade",
                    params: "",
                    success: function(val) {
                        answer = decodeURI(val.toString());

                        // Setting state presumes getting state, so don't get
                        // state unless set state is defined.
                        if (stateGetter && stateSetter) {
                            channel.call({
                                method: "getState",
                                params: "",
                                success: function(val) {
                                    state = decodeURI(val.toString());
                                    store = {
                                        answer: answer,
                                        state:  state
                                    };
                                    inputField.val(JSON.stringify(store));
                                    callback();
                                }
                            });
                        } else {
                            inputField.val(answer);
                            callback();
                        }
                    }
                });
            }
        };

        /*                      Initialization                          */

        // Put the update function as the value of the inputField's "waitfor"
        // attribute so that it is called when the check button is clicked.
        inputField.data('waitfor', update);

        // Check whether application takes in state and there is a saved
        // state to give it. If stateSetter is specified but calling it
        // fails, wait and try again, since the iframe might still be
        // loading.
        if (stateSetter && storedState) {
            var stateValue, jsonValue;

            try {
              jsonValue = JSON.parse(storedState);
            } catch (err) {
              jsonValue = storedState;
            }

            if (typeof(jsonValue) === "object") {
                stateValue = jsonValue["state"];
            } else {
                stateValue = jsonValue;
            }

            // Try calling setstate every 200ms while it throws an exception,
            // up to five times; give up after that.
            // (Functions in the iframe may not be ready when we first try
            // calling it, but might just need more time. Give the functions
            // more time.)
            // 200 ms and 5 times are arbitrary but this has functioned with the
            // only application that has ever used JSInput, jsVGL. Something
            // more sturdy should be put in place.
            function whileloop(n) {
                if (n < 5){
                    try {
                        if (sop) {
                            _deepKey(cWindow, stateSetter)(stateValue);
                        } else {
                            channel.call({
                                method: "setState",
                                params: stateValue,
                                success: function() {
                                }
                            });
                        }
                    } catch (err) {
                        setTimeout(whileloop(n+1), 200);
                    }
                }
                else {
                    console.debug("Error: could not set state");
                }
            }
            whileloop(0);
        }
    }

    function walkDOM() {
        var dataProcessed, all;

        // Find all jsinput elements
        allSections = $('section.jsinput');

        // When a JSInput problem loads, its data-processed attribute is false,
        // so the jsconstructor will be called for it.
        // The constructor will not be called again on subsequent reruns of
        // this file by other JSInput. Only if it is reloaded, either with the
        // rest of the page or when it is submitted, will this constructor be
        // called again.
        allSections.each(function(index, value) {
            dataProcessed = ($(value).attr("data-processed") === "true");
            if (!dataProcessed) {
                jsinputConstructor(value);
                $(value).attr("data-processed", 'true');
            }
        });
    }

    // This is ugly, but without a timeout pages with multiple/heavy jsinputs
    // don't load properly.
    // 300 ms is arbitrary but this has functioned with the only application
    // that has ever used JSInput, jsVGL. Something more sturdy should be put in
    // place.
    if ($.isReady) {
        setTimeout(walkDOM, 300);
    } else {
        $(document).ready(setTimeout(walkDOM, 300));
    }

    return {
        jsinputConstructor: jsinputConstructor,
        walkDOM: walkDOM
    };

})(window.jQuery);<commit_msg>fixed retry invokation for calling setState<commit_after>/*
 * JSChannel (https://github.com/mozilla/jschannel) will be loaded prior to this
 * script. We will use it use to let JSInput call 'gradeFn', and eventually
 * 'stateGetter' & 'stateSetter' in the iframe's content even if it hasn't the
 * same origin, therefore bypassing SOP:
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript
 */

var JSInput = (function ($, undefined) {
    // Initialize js inputs on current page.
    // N.B.: No library assumptions about the iframe can be made (including,
    // most relevantly, jquery). Keep in mind what happens in which context
    // when modifying this file.

    // When all the problems are first loaded, we want to make sure the
    // constructor only runs once for each iframe; but we also want to make
    // sure that if part of the page is reloaded (e.g., a problem is
    // submitted), the constructor is called again.

    /*                      Utils                               */

    // Take a string and find the nested object that corresponds to it. E.g.:
    //    _deepKey(obj, "an.example") -> obj["an"]["example"]
    function _deepKey(obj, path){
        for (var i = 0, p=path.split('.'), len = p.length; i < len; i++){
            obj = obj[p[i]];
        }
        return obj;
    };

    /*      END     Utils                                   */

    function jsinputConstructor(elem) {
        // Define an class that will be instantiated for each jsinput element
        // of the DOM

        /*                      Private methods                          */

        var section = $(elem).parent().find('section[class="jsinput"]'),
            sectionAttr = function (e) { return $(section).attr(e); },
            iframe = $(elem).find('iframe[name^="iframe_"]').get(0),
            cWindow = iframe.contentWindow,
            path = iframe.src.substring(0, iframe.src.lastIndexOf("/")+1),
            // Get the hidden input field to pass to customresponse
            inputField = $(elem).parent().find('input[id^="input_"]'),
            // Get the grade function name
            gradeFn = sectionAttr("data"),
            // Get state getter
            stateGetter = sectionAttr("data-getstate"),
            // Get state setter
            stateSetter = sectionAttr("data-setstate"),
            // Get stored state
            storedState = sectionAttr("data-stored"),
            // Bypass single-origin policy only if this attribute is "false"
            // In that case, use JSChannel to do so.
            sop = sectionAttr("data-sop"),
            channel;

        sop = (sop !== "false");

        if (!sop) {
            channel = Channel.build({
                window: cWindow,
                origin: path,
                scope: "JSInput"
            });
         }

        /*                       Public methods                     */

        // Only one public method that updates the hidden input field.
        var update = function (callback) {
            var answer, state, store;

            if (sop) {
                answer = _deepKey(cWindow, gradeFn)();
                // Setting state presumes getting state, so don't get state
                // unless set state is defined.
                if (stateGetter && stateSetter) {
                    state = unescape(_deepKey(cWindow, stateGetter)());
                    store = {
                        answer: answer,
                        state:  state
                    };
                    inputField.val(JSON.stringify(store));
                } else {
                    inputField.val(answer);
                }
                callback();
            } else {
                channel.call({
                    method: "getGrade",
                    params: "",
                    success: function(val) {
                        answer = decodeURI(val.toString());

                        // Setting state presumes getting state, so don't get
                        // state unless set state is defined.
                        if (stateGetter && stateSetter) {
                            channel.call({
                                method: "getState",
                                params: "",
                                success: function(val) {
                                    state = decodeURI(val.toString());
                                    store = {
                                        answer: answer,
                                        state:  state
                                    };
                                    inputField.val(JSON.stringify(store));
                                    callback();
                                }
                            });
                        } else {
                            inputField.val(answer);
                            callback();
                        }
                    }
                });
            }
        };

        /*                      Initialization                          */

        // Put the update function as the value of the inputField's "waitfor"
        // attribute so that it is called when the check button is clicked.
        inputField.data('waitfor', update);

        // Check whether application takes in state and there is a saved
        // state to give it. If stateSetter is specified but calling it
        // fails, wait and try again, since the iframe might still be
        // loading.
        if (stateSetter && storedState) {
            var stateValue, jsonValue;

            try {
              jsonValue = JSON.parse(storedState);
            } catch (err) {
              jsonValue = storedState;
            }

            if (typeof(jsonValue) === "object") {
                stateValue = jsonValue["state"];
            } else {
                stateValue = jsonValue;
            }

            // Try calling setstate every 200ms while it throws an exception,
            // up to five times; give up after that.
            // (Functions in the iframe may not be ready when we first try
            // calling it, but might just need more time. Give the functions
            // more time.)
            // 200 ms and 5 times are arbitrary but this has functioned with the
            // only application that has ever used JSInput, jsVGL. Something
            // more sturdy should be put in place.
            function whileloop(n) {
                if (n > 0){
                    try {
                        if (sop) {
                            _deepKey(cWindow, stateSetter)(stateValue);
                        } else {
                            channel.call({
                                method: "setState",
                                params: stateValue,
                                success: function() {
                                }
                            });
                        }
                    } catch (err) {
                        setTimeout(function() { whileloop(n - 1); }, 200);
                    }
                }
                else {
                    console.debug("Error: could not set state");
                }
            }
            whileloop(5);
        }
    }

    function walkDOM() {
        var dataProcessed, all;

        // Find all jsinput elements
        allSections = $('section.jsinput');

        // When a JSInput problem loads, its data-processed attribute is false,
        // so the jsconstructor will be called for it.
        // The constructor will not be called again on subsequent reruns of
        // this file by other JSInput. Only if it is reloaded, either with the
        // rest of the page or when it is submitted, will this constructor be
        // called again.
        allSections.each(function(index, value) {
            dataProcessed = ($(value).attr("data-processed") === "true");
            if (!dataProcessed) {
                jsinputConstructor(value);
                $(value).attr("data-processed", 'true');
            }
        });
    }

    // This is ugly, but without a timeout pages with multiple/heavy jsinputs
    // don't load properly.
    // 300 ms is arbitrary but this has functioned with the only application
    // that has ever used JSInput, jsVGL. Something more sturdy should be put in
    // place.
    if ($.isReady) {
        setTimeout(walkDOM, 300);
    } else {
        $(document).ready(setTimeout(walkDOM, 300));
    }

    return {
        jsinputConstructor: jsinputConstructor,
        walkDOM: walkDOM
    };

})(window.jQuery);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router';
import Carousel from 'nuka-carousel';
import moment from 'moment';
import { Container, Grid, Image, Header, Divider, Message, List, Loader, Button, Modal, Form, Input, Segment, Card } from 'semantic-ui-react';
import GoogleMapContainer from './AllListings/AllListingsComponents/GoogleMap/GoogleMapContainer';
import { getCurrentListing } from '../../actions/fullListingActions';
import Listing from '../shared/Listing';
import RatingCard from '../Ratings/RatingCard';

class FullListing extends Component {

  componentDidMount() {
    console.log('Listing ID: ', this.props.listingId);
    this.props.dispatch(getCurrentListing(this.props.listingId));
  }

  convertTime(time) {
    return moment(time).fromNow();
  }

  renderRecentRatings(ratings) {
    if (!ratings) { return []; }
    return ratings
      .slice(0, 3)
      .map(r =>
        <RatingCard
          stars={r.stars}
          editable={false}
          content={r.content}
          rater={r.rater}
        />);
  }

  render() {
    const { isFetching, currentListing, userListings, user } = this.props;
    if (isFetching) {
      return <Loader active inline="centered" />;
    }

    return (
      <Container textAlign="center">
        -- {currentListing.title || 'Current Listing'} --

        {`Created ${this.convertTime(currentListing.createdAt)}` || 'Time Created'}

        <Divider />

        <Message color="grey">
          <Grid columns={2} textAlign="left">
            <Grid.Column>
              Job Description
              <Grid.Row>

{currentListing.body}

              </Grid.Row>
              <Grid.Row verticalAlign="bottom">
                <Divider hidden section />
                <Carousel>
                  {
                    currentListing.pictures.map(p => <Image key={p.id} src={p.img_path} />)
                  }
                </Carousel>
              </Grid.Row>
            </Grid.Column>
            <Grid.Column>
              <Grid.Row>
                <GoogleMapContainer />
              </Grid.Row>
              <Divider hidden />
              <Grid.Row columns={2}>
                <Grid.Column>
                  <List>
                    <List.Item>
                      <List.Icon name="users" />
                      <List.Content>{`${currentListing.user.firstName} ${currentListing.user.lastName}` || 'Customer Name'}</List.Content>
                    </List.Item>
                    <List.Item>
                      <List.Icon name="marker" />
                      <List.Content>{`${currentListing.user.city}, ${currentListing.user.state}`}</List.Content>
                    </List.Item>
                    <List.Item>
                      <List.Icon name="mail" />
                      <List.Content>
                        <a href={`${currentListing.user.email}`}>{`${currentListing.user.email}`}
                      </List.Content>
                    </List.Item>
                    <List.Item>
                      <List.Icon name="linkify" />
                      <List.Content>
                        semantic-ui.com
                      </List.Content>
                    </List.Item>
                  </List>
                </Grid.Column>
                <Divider hidden />
                <Grid.Column>
                  <Modal trigger={<Button>Contact Them!</Button>}>
                    <Modal.Header>Contact Form</Modal.Header>
                    <Modal.Content>
                      <Modal.Description>
                        Send Them A Message!
                        <Form>
                          <Form.Input label="Subject" placeholder="Subject" />
                          <Form.TextArea label="Message" placeholder="Tell them who you are and why you are contacting them..." />
                          <Form.Button>Send Message</Form.Button>
                        </Form>
                      </Modal.Description>
                    </Modal.Content>
                  </Modal>
                </Grid.Column>
              </Grid.Row>
            </Grid.Column>
          </Grid>

          <Divider clearing />
          <Divider hidden />
          <Grid>
            <Grid.Row centered>

                {`Recent Ratings for ${currentListing.user.firstName}`}

            </Grid.Row>
            <Grid.Row centered>
              <Card.Group>
                { this.renderRecentRatings(currentListing.user.ratings) }
              </Card.Group>
            </Grid.Row>
            <Grid.Row>
            <Link to={`/user/${currentListing.user.id}/ratings`}>
              View All
            </Link>
          </Grid.Row>
          </Grid>
        </Message>
      </Container>
    );
  }
}

const mapStateToProps = (state) => {
  const { currentListing, userListings, isFetching } = state.listing;
  const { user } = state.listing.currentListing;
  const { loggedInUser } = state.auth;
  const { pathname } = state.routing.locationBeforeTransitions;

  const listingId = pathname.split('/')[2];

  return {
    loggedInUser,
    currentListing,
    userListings,
    isFetching,
    listingId,
    user,
  };
};

FullListing.propTypes = {
  isFetching: React.PropTypes.bool.isRequired,
};

export default connect(mapStateToProps)(FullListing);
<commit_msg>Display all ratings link only when ratings exist<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router';
import Carousel from 'nuka-carousel';
import moment from 'moment';
import { Container, Grid, Image, Header, Divider, Message, List, Loader, Button, Modal, Form, Input, Segment, Card } from 'semantic-ui-react';
import GoogleMapContainer from './AllListings/AllListingsComponents/GoogleMap/GoogleMapContainer';
import { getCurrentListing } from '../../actions/fullListingActions';
import Listing from '../shared/Listing';
import RatingCard from '../Ratings/RatingCard';

class FullListing extends Component {

  componentDidMount() {
    console.log('Listing ID: ', this.props.listingId);
    this.props.dispatch(getCurrentListing(this.props.listingId));
  }

  convertTime(time) {
    return moment(time).fromNow();
  }

  renderRecentRatings(ratings) {
    if (!ratings) { return []; }
    return ratings
      .slice(0, 3)
      .map(r =>
        <RatingCard
          stars={r.stars}
          editable={false}
          content={r.content}
          rater={r.rater}
        />);
  }

  render() {
    const { isFetching, currentListing, userListings, user } = this.props;
    if (isFetching) {
      return <Loader active inline="centered" />;
    }

    return (
      <Container textAlign="center">
        -- {currentListing.title || 'Current Listing'} --

        {`Created ${this.convertTime(currentListing.createdAt)}` || 'Time Created'}

        <Divider />

        <Message color="grey">
          <Grid columns={2} textAlign="left">
            <Grid.Column>
              Job Description
              <Grid.Row>

{currentListing.body}

              </Grid.Row>
              <Grid.Row verticalAlign="bottom">
                <Divider hidden section />
                <Carousel>
                  {
                    currentListing.pictures.map(p => <Image key={p.id} src={p.img_path} />)
                  }
                </Carousel>
              </Grid.Row>
            </Grid.Column>
            <Grid.Column>
              <Grid.Row>
                <GoogleMapContainer />
              </Grid.Row>
              <Divider hidden />
              <Grid.Row columns={2}>
                <Grid.Column>
                  <List>
                    <List.Item>
                      <List.Icon name="users" />
                      <List.Content>{`${currentListing.user.firstName} ${currentListing.user.lastName}` || 'Customer Name'}</List.Content>
                    </List.Item>
                    <List.Item>
                      <List.Icon name="marker" />
                      <List.Content>{`${currentListing.user.city}, ${currentListing.user.state}`}</List.Content>
                    </List.Item>
                    <List.Item>
                      <List.Icon name="mail" />
                      <List.Content>
                        <a href={`${currentListing.user.email}`}>{`${currentListing.user.email}`}
                      </List.Content>
                    </List.Item>
                    <List.Item>
                      <List.Icon name="linkify" />
                      <List.Content>
                        semantic-ui.com
                      </List.Content>
                    </List.Item>
                  </List>
                </Grid.Column>
                <Divider hidden />
                <Grid.Column>
                  <Modal trigger={<Button>Contact Them!</Button>}>
                    <Modal.Header>Contact Form</Modal.Header>
                    <Modal.Content>
                      <Modal.Description>
                        Send Them A Message!
                        <Form>
                          <Form.Input label="Subject" placeholder="Subject" />
                          <Form.TextArea label="Message" placeholder="Tell them who you are and why you are contacting them..." />
                          <Form.Button>Send Message</Form.Button>
                        </Form>
                      </Modal.Description>
                    </Modal.Content>
                  </Modal>
                </Grid.Column>
              </Grid.Row>
            </Grid.Column>
          </Grid>

          <Divider clearing />
          <Divider hidden />
          <Grid centered>
            <Grid.Row>

                {`Recent Ratings for ${currentListing.user.firstName}`}

            </Grid.Row>
            { currentListing.user.ratings && !currentListing.user.ratings.length ?
                No Ratings for { currentListing.user.firstName  } :
                <Grid>
                  <Grid.Row centered>
                    <Card.Group>
                      { this.renderRecentRatings(currentListing.user.ratings) }
                    </Card.Group>
                  </Grid.Row>
                  <Grid.Row>
                    <Link to={`/user/${currentListing.user.id}/ratings`}>
                      View All
                    </Link>
                  </Grid.Row>
                </Grid>
            }
          </Grid>
        </Message>
      </Container>
    );
  }
}

const mapStateToProps = (state) => {
  const { currentListing, userListings, isFetching } = state.listing;
  const { user } = state.listing.currentListing;
  const { loggedInUser } = state.auth;
  const { pathname } = state.routing.locationBeforeTransitions;

  const listingId = pathname.split('/')[2];

  return {
    loggedInUser,
    currentListing,
    userListings,
    isFetching,
    listingId,
    user,
  };
};

FullListing.propTypes = {
  isFetching: React.PropTypes.bool.isRequired,
};

export default connect(mapStateToProps)(FullListing);
<|endoftext|>


<commit_before>var dataGridRegisterExtension;

if (typeof naja !== "undefined") {
	var isNaja2 = function () { return naja.version >= 2 };
	dataGridRegisterExtension = function (name, extension) {
		var init = extension.init;
		var success = extension.success;
		var before = extension.before;
		var complete = extension.complete;

		var NewExtension = function NewExtension(naja, name) {
			this.name = name;

			this.initialize = function (naja) {
				if(init) {
					naja.addEventListener('init', function (params)  {
						init(params.defaultOptions);
					});
				}

				if(success) {
					naja.addEventListener('success', function (params)  {
						var payload = isNaja2() ? params.payload : params.response;
						success(payload, params.options);
					});
				}

				if(before) {
					naja.addEventListener('before', function (params) {
						before(params.xhr || params.request, params.options);
					});
				}

				if(complete) {
					naja.addEventListener('complete', function (params) {
						complete(params.xhr || params.request, params.options);
					});
				}
			}
			if (!naja.version || !isNaja2()) {
				extension.initialize(naja);
			}
			return this;
		}

		if (isNaja2()) {
			naja.registerExtension(new NewExtension(null, name));
		} else {
			naja.registerExtension(NewExtension, name);
		}
	};
} else if ($.nette) {
		dataGridRegisterExtension = function (name, extension) {
			$.nette.ext(name, extension);
		};
}

dataGridRegisterExtension('ublaboo-spinners', {
	before: function(xhr, settings) {
		var el, id, row_detail, spinner_template, grid_fullname;
		if (settings.nette) {
			el = settings.nette.el;
			spinner_template = $('

');
			if (el.is('.datagrid [name="group_action[submit]"]')) {
				return el.after(spinner_template);
			} else if (el.is('.datagrid a') && el.data('toggle-detail')) {
				id = settings.nette.el.attr('data-toggle-detail');
				grid_fullname = settings.nette.el.attr('data-toggle-detail-grid-fullname');
				row_detail = $('.item-detail-' + grid_fullname + '-id-' + id);
				if (!row_detail.hasClass('loaded')) {
					return el.addClass('ublaboo-spinner-icon');
				}
			} else if (el.is('.datagrid .col-pagination a')) {
				return el.closest('.row-grid-bottom').find('.col-per-page').prepend(spinner_template);
			} else if (el.is('.datagrid .datagrid-per-page-submit')) {
				return el.closest('.row-grid-bottom').find('.col-per-page').prepend(spinner_template);
			} else if (el.is('.datagrid .reset-filter')) {
				return el.closest('.row-grid-bottom').find('.col-per-page').prepend(spinner_template);
			}
		}
	},
	complete: function() {
		$('.ublaboo-spinner').remove();
		return $('.ublaboo-spinner-icon').removeClass('ublaboo-spinner-icon');
	}
});
<commit_msg>Fix direct init<commit_after>var dataGridRegisterExtension;

if (typeof naja !== "undefined") {
	var isNaja2 = function () { return naja.version >= 2 };
	dataGridRegisterExtension = function (name, extension) {
		var init = extension.init;
		var success = extension.success;
		var before = extension.before;
		var complete = extension.complete;

		var NewExtension = function NewExtension(naja, name) {
			this.name = name;

			this.initialize = function (naja) {
				if(init) {
					naja.addEventListener('init', function (params)  {
						init(params.defaultOptions);
					});
				}

				if(success) {
					naja.addEventListener('success', function (params)  {
						var payload = isNaja2() ? params.payload : params.response;
						success(payload, params.options);
					});
				}

				if(before) {
					naja.addEventListener('before', function (params) {
						before(params.xhr || params.request, params.options);
					});
				}

				if(complete) {
					naja.addEventListener('complete', function (params) {
						complete(params.xhr || params.request, params.options);
					});
				}
			}
			if (!naja.version || !isNaja2()) {
				this.initialize(naja);
			}
			return this;
		}

		if (isNaja2()) {
			naja.registerExtension(new NewExtension(null, name));
		} else {
			naja.registerExtension(NewExtension, name);
		}
	};
} else if ($.nette) {
		dataGridRegisterExtension = function (name, extension) {
			$.nette.ext(name, extension);
		};
}

dataGridRegisterExtension('ublaboo-spinners', {
	before: function(xhr, settings) {
		var el, id, row_detail, spinner_template, grid_fullname;
		if (settings.nette) {
			el = settings.nette.el;
			spinner_template = $('

');
			if (el.is('.datagrid [name="group_action[submit]"]')) {
				return el.after(spinner_template);
			} else if (el.is('.datagrid a') && el.data('toggle-detail')) {
				id = settings.nette.el.attr('data-toggle-detail');
				grid_fullname = settings.nette.el.attr('data-toggle-detail-grid-fullname');
				row_detail = $('.item-detail-' + grid_fullname + '-id-' + id);
				if (!row_detail.hasClass('loaded')) {
					return el.addClass('ublaboo-spinner-icon');
				}
			} else if (el.is('.datagrid .col-pagination a')) {
				return el.closest('.row-grid-bottom').find('.col-per-page').prepend(spinner_template);
			} else if (el.is('.datagrid .datagrid-per-page-submit')) {
				return el.closest('.row-grid-bottom').find('.col-per-page').prepend(spinner_template);
			} else if (el.is('.datagrid .reset-filter')) {
				return el.closest('.row-grid-bottom').find('.col-per-page').prepend(spinner_template);
			}
		}
	},
	complete: function() {
		$('.ublaboo-spinner').remove();
		return $('.ublaboo-spinner-icon').removeClass('ublaboo-spinner-icon');
	}
});
<|endoftext|>


<commit_before>import { SubmissionError } from 'redux-form';
import {
  UPDATE_AVATAR_REQUEST, UPDATE_AVATAR_FAILURE, UPDATE_AVATAR_SUCCESS,
  UPDATE_USER_REQUEST, UPDATE_USER_FAILURE, UPDATE_USER_SUCCESS
} from '../constants/ActionTypes';
import { CALL_API } from '../middleware/api';

const updateAvatarRequest = (formData) => ({
  [CALL_API]: {
    types: [ UPDATE_AVATAR_REQUEST, UPDATE_AVATAR_SUCCESS, UPDATE_AVATAR_FAILURE ],
    endpoint: `account/avatar`,
    method: 'POST',
    body: formData
  }
});

const updateUserRequest = ({username, first_name, last_name}) => ({
  [CALL_API]: {
    types: [ UPDATE_USER_REQUEST, UPDATE_USER_SUCCESS, UPDATE_USER_FAILURE ],
    endpoint: `account/info`,
    method: 'POST',
    body: {
      username: username,
      first_name: first_name,
      last_name: last_name
    }
  }
});

const updatePasswordRequest = ({current_password, new_password}) => ({
  [CALL_API]: {
    types: [ UPDATE_USER_REQUEST, UPDATE_USER_SUCCESS, UPDATE_USER_FAILURE ],
    endpoint: `account/password`,
    method: 'POST',
    body: {
      current_password,
      new_password
    }
  }
});

export const updateAvatar = (values) => (dispatch, getState) =>  {
  const file = values.avatar[0];

  var formData = new FormData();
  formData.append("avatar", file);

  return dispatch(updateAvatarRequest(formData)).then(response => {
    if(response.error){
      throw new SubmissionError(response.response);
    }
  });
};

export const updateInfo = (values) => (dispatch, getState) =>  {
  return dispatch(updateUserRequest(values)).then(response => {
    if(response.error){
      throw new SubmissionError(response.response);
    }
  });
};

export const updatePassword = (values) => (dispatch, getState) =>  {
  return dispatch(updatePasswordRequest(values)).then(response => {
    if(response.error){
      throw new SubmissionError(response.response);
    }
  });
};
<commit_msg>Use schema so client state updates automatically<commit_after>import { SubmissionError } from 'redux-form';
import {
  UPDATE_AVATAR_REQUEST, UPDATE_AVATAR_FAILURE, UPDATE_AVATAR_SUCCESS,
  UPDATE_USER_REQUEST, UPDATE_USER_FAILURE, UPDATE_USER_SUCCESS
} from '../constants/ActionTypes';
import { CALL_API, Schemas } from '../middleware/api';

const updateAvatarRequest = (formData) => ({
  [CALL_API]: {
    types: [ UPDATE_AVATAR_REQUEST, UPDATE_AVATAR_SUCCESS, UPDATE_AVATAR_FAILURE ],
    endpoint: `account/avatar`,
    method: 'POST',
    schema: Schemas.USER,
    body: formData
  }
});

const updateUserRequest = ({username, first_name, last_name}) => ({
  [CALL_API]: {
    types: [ UPDATE_USER_REQUEST, UPDATE_USER_SUCCESS, UPDATE_USER_FAILURE ],
    endpoint: `account/info`,
    method: 'POST',
    schema: Schemas.USER,
    body: {
      username: username,
      first_name: first_name,
      last_name: last_name
    }
  }
});

const updatePasswordRequest = ({current_password, new_password}) => ({
  [CALL_API]: {
    types: [ UPDATE_USER_REQUEST, UPDATE_USER_SUCCESS, UPDATE_USER_FAILURE ],
    endpoint: `account/password`,
    method: 'POST',
    body: {
      current_password,
      new_password
    }
  }
});

export const updateAvatar = (values) => (dispatch, getState) =>  {
  const file = values.avatar[0];

  var formData = new FormData();
  formData.append("avatar", file);

  return dispatch(updateAvatarRequest(formData)).then(response => {
    if(response.error){
      throw new SubmissionError(response.response);
    }
  });
};

export const updateInfo = (values) => (dispatch, getState) =>  {
  return dispatch(updateUserRequest(values)).then(response => {
    if(response.error){
      throw new SubmissionError(response.response);
    }
  });
};

export const updatePassword = (values) => (dispatch, getState) =>  {
  return dispatch(updatePasswordRequest(values)).then(response => {
    if(response.error){
      throw new SubmissionError(response.response);
    }
  });
};
<|endoftext|>


<commit_before>
(function($){
    var PHPHub = {

        init: function(){
            var self = this;
            $(document).pjax('a:not(a[target="_blank"])', 'body');
            $(document).on('pjax:start', function() {
                NProgress.start();
            });
            $(document).on('pjax:end', function() {
                NProgress.done();
                self.siteBootUp();
            });
            self.siteBootUp();
            self.initLightBox();
        },

        /*
        * Things to be execute when normal page load
        * and pjax page load.
        */
        siteBootUp: function(){
            var self = this;
            self.initExternalLink();
            self.initTimeAgo();
            self.initEmoji();
            self.initScrollToTop();
            self.initTextareaAutoResize();
            self.initHeightLight();
            self.initEditorPreview();
        },

        /**
         * Open External Links In New Window
         */
        initExternalLink: function(){
            $('a[href^="http://"], a[href^="https://"]').each(function() {
               var a = new RegExp('/' + window.location.host + '/');
               if(!a.test(this.href) ) {
                   $(this).click(function(event) {
                       event.preventDefault();
                       event.stopPropagation();
                       window.open(this.href, '_blank');
                   });
               }
            });
        },

        /**
         * Automatically transform any Date format to human
         * friendly format, all you need to do is add a
         * `.timeago` class.
         */
        initTimeAgo: function(){
            moment.lang('zh-cn');
            $('.timeago').each(function(){
                $(this).text( moment( $(this).text() ).fromNow());
            });
        },

        /**
         * Enable emoji everywhere.
         */
        initEmoji: function(){
            emojify.setConfig({
                img_dir : Config.cdnDomain + 'assets/images/emoji',
                ignored_tags : {
                    'SCRIPT'  : 1,
                    'TEXTAREA': 1,
                    'A'       : 1,
                    'PRE'     : 1,
                    'CODE'    : 1
                }
            });
            emojify.run();

            $('#reply_content').textcomplete([
                { // emoji strategy
                    match: /\B:([\-+\w]*)$/,
                    search: function (term, callback) {
                        callback($.map(emojies, function (emoji) {
                            return emoji.indexOf(term) === 0 ? emoji : null;
                        }));
                    },
                    template: function (value) {
                        return '' + value;
                    },
                    replace: function (value) {
                        return ':' + value + ': ';
                    },
                    index: 1,
                    maxCount: 5
                }
            ]);
        },

        /**
         * Autoresizing the textarea when you typing.
         */
        initTextareaAutoResize: function(){
            $('textarea').autosize();
        },

        /**
         * Scroll to top in one click.
         */
        initScrollToTop: function(){
            $.scrollUp.init();
        },

        /**
         * Code heightlight.
         */
        initHeightLight: function(){
            Prism.highlightAll();
        },

        /**
         * lightbox
         */
        initLightBox: function(){
            $(document).delegate('.content-body img:not(.emoji)', 'click', function(event) {
                event.preventDefault();
                return $(this).ekkoLightbox({
                    onShown: function() {
                        if (window.console) {
                            // return console.log('Checking our the events huh?');
                        }
                    }
                });
            });
        },

        /**
         * Init post content preview
         */
        initEditorPreview: function() {
            $("#reply_content").focus(function(event) {
                $("#reply_notice").fadeIn(1500);
                $("#preview-box").fadeIn(1500);
                $("#preview-lable").fadeIn(1500);
            });
            $('#reply_content').keyup(function(){
                var replyContent = $("#reply_content");
                var oldContent = replyContent.val();

                if (oldContent) {
                    marked(oldContent, function (err, content) {
                      $('#preview-box').html(content);
                      emojify.run(document.getElementById('preview-box'));
                    });
                }
            });
        }

    }
    window.PHPHub = PHPHub;
})(jQuery);

$(document).ready(function()
{
    PHPHub.init();
});

// reply a reply
function replyOne(username){
    replyContent = $("#reply_content");
	oldContent = replyContent.val();
	prefix = "@" + username + " ";
	newContent = ''
	if(oldContent.length > 0){
	    if (oldContent != prefix) {
	        newContent = oldContent + "\n" + prefix;
	    }
	} else {
	    newContent = prefix
	}
	replyContent.focus();
	replyContent.val(newContent);
	moveEnd($("#reply_content"));
}

var moveEnd = function(obj){
	obj.focus();

	var len = obj.value === undefined ? 0 : obj.value.length;

	if (document.selection) {
		var sel = obj.createTextRange();
		sel.moveStart('character',len);
		sel.collapse();
		sel.select();
	} else if (typeof obj.selectionStart == 'number' && typeof obj.selectionEnd == 'number') {
		obj.selectionStart = obj.selectionEnd = len;
	}
}
<commit_msg>fixing show time when fall-back<commit_after>
(function($){
    var PHPHub = {

        init: function(){
            var self = this;
            $(document).pjax('a:not(a[target="_blank"])', 'body');
            $(document).on('pjax:start', function() {
                NProgress.start();
            });
            $(document).on('pjax:end', function() {
                NProgress.done();
            });
            $(document).on('pjax:complete', function() {
                NProgress.done();
                self.siteBootUp();
            });
            self.siteBootUp();
            self.initLightBox();
        },

        /*
        * Things to be execute when normal page load
        * and pjax page load.
        */
        siteBootUp: function(){
            var self = this;
            self.initExternalLink();
            self.initTimeAgo();
            self.initEmoji();
            self.initScrollToTop();
            self.initTextareaAutoResize();
            self.initHeightLight();
            self.initEditorPreview();
        },

        /**
         * Open External Links In New Window
         */
        initExternalLink: function(){
            $('a[href^="http://"], a[href^="https://"]').each(function() {
               var a = new RegExp('/' + window.location.host + '/');
               if(!a.test(this.href) ) {
                   $(this).click(function(event) {
                       event.preventDefault();
                       event.stopPropagation();
                       window.open(this.href, '_blank');
                   });
               }
            });
        },

        /**
         * Automatically transform any Date format to human
         * friendly format, all you need to do is add a
         * `.timeago` class.
         */
        initTimeAgo: function(){
            moment.lang('zh-cn');
            $('.timeago').each(function(){
                $(this).text( moment( $(this).text() ).fromNow());
            });
        },

        /**
         * Enable emoji everywhere.
         */
        initEmoji: function(){
            emojify.setConfig({
                img_dir : Config.cdnDomain + 'assets/images/emoji',
                ignored_tags : {
                    'SCRIPT'  : 1,
                    'TEXTAREA': 1,
                    'A'       : 1,
                    'PRE'     : 1,
                    'CODE'    : 1
                }
            });
            emojify.run();

            $('#reply_content').textcomplete([
                { // emoji strategy
                    match: /\B:([\-+\w]*)$/,
                    search: function (term, callback) {
                        callback($.map(emojies, function (emoji) {
                            return emoji.indexOf(term) === 0 ? emoji : null;
                        }));
                    },
                    template: function (value) {
                        return '' + value;
                    },
                    replace: function (value) {
                        return ':' + value + ': ';
                    },
                    index: 1,
                    maxCount: 5
                }
            ]);
        },

        /**
         * Autoresizing the textarea when you typing.
         */
        initTextareaAutoResize: function(){
            $('textarea').autosize();
        },

        /**
         * Scroll to top in one click.
         */
        initScrollToTop: function(){
            $.scrollUp.init();
        },

        /**
         * Code heightlight.
         */
        initHeightLight: function(){
            Prism.highlightAll();
        },

        /**
         * lightbox
         */
        initLightBox: function(){
            $(document).delegate('.content-body img:not(.emoji)', 'click', function(event) {
                event.preventDefault();
                return $(this).ekkoLightbox({
                    onShown: function() {
                        if (window.console) {
                            // return console.log('Checking our the events huh?');
                        }
                    }
                });
            });
        },

        /**
         * Init post content preview
         */
        initEditorPreview: function() {
            $("#reply_content").focus(function(event) {
                $("#reply_notice").fadeIn(1500);
                $("#preview-box").fadeIn(1500);
                $("#preview-lable").fadeIn(1500);
            });
            $('#reply_content').keyup(function(){
                var replyContent = $("#reply_content");
                var oldContent = replyContent.val();

                if (oldContent) {
                    marked(oldContent, function (err, content) {
                      $('#preview-box').html(content);
                      emojify.run(document.getElementById('preview-box'));
                    });
                }
            });
        }

    }
    window.PHPHub = PHPHub;
})(jQuery);

$(document).ready(function()
{
    PHPHub.init();
});

// reply a reply
function replyOne(username){
    replyContent = $("#reply_content");
	oldContent = replyContent.val();
	prefix = "@" + username + " ";
	newContent = ''
	if(oldContent.length > 0){
	    if (oldContent != prefix) {
	        newContent = oldContent + "\n" + prefix;
	    }
	} else {
	    newContent = prefix
	}
	replyContent.focus();
	replyContent.val(newContent);
	moveEnd($("#reply_content"));
}

var moveEnd = function(obj){
	obj.focus();

	var len = obj.value === undefined ? 0 : obj.value.length;

	if (document.selection) {
		var sel = obj.createTextRange();
		sel.moveStart('character',len);
		sel.collapse();
		sel.select();
	} else if (typeof obj.selectionStart == 'number' && typeof obj.selectionEnd == 'number') {
		obj.selectionStart = obj.selectionEnd = len;
	}
}
<|endoftext|>


<commit_before>var util              = require('util')
  , bops              = require('bops')
  , AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN
  , AbstractIterator  = require('abstract-leveldown').AbstractIterator
  , noop              = function () {}
  , setImmediate      = global.setImmediate || process.nextTick
  , redis             = require("redis")

function toKey (key) {
  return typeof key == 'string' ? key : JSON.stringify(key)
}

function RedIterator (db, options) {
  AbstractIterator.call(this, db)
  this._reverse = options.reverse
  this._limit   = options.limit
  this._count   = 0
  this._end     = options.end
  this._start   = options.start
  this._gt      = options.gt
  this._gte     = options.gte
  this._lt      = options.lt
  this._lte     = options.lte

  var i

  if (this._start) {
    for (i = 0; i < this.db._keys.length; i++) {
      if (this.db._keys[i] >= this._start) {
        this._pos = i
        if (this.db._keys[i] != this._start) {
          if (this._reverse) {
            // going backwards and key doesn't match, jump back one
            --this._pos
          }
        } else {
          if (options.exclusiveStart) {
            // key matches but it's a gt or lt
            this._pos += (this._reverse ? -1 : 1)
          }
        }
        break
      }
    }

    if (this._pos == null && !this._reverse) // no matching keys, non starter
      this._pos = -1
  }

  if (!options.start || !this._pos)
    this._pos = this._reverse ? this.db._keys.length - 1 : 0
}

util.inherits(RedIterator, AbstractIterator)

RedIterator.prototype._next = function (callback) {
  var self  = this
    , key   = self.db._keys[self._pos]
    , value

  if (self._pos >= self.db._keys.length || self._pos < 0)
    return setImmediate(callback)

  if (!!self._end && (self._reverse ? key < self._end : key > self._end))
    return setImmediate(callback)

  if (!!self._limit && self._limit > 0 && self._count++ >= self._limit)
    return setImmediate(callback)

  if (  (this._lt  && key >= this._lt)
     || (this._lte && key > this._lte)
     || (this._gt  && key <= this._gt)
     || (this._gte && key < this._gte))
    return setImmediate(callback)

  value = self.db._store[toKey(key)]
  self._pos += self._reverse ? -1 : 1

  setImmediate(function () { callback(null, key, value) })
}

function ReDOWN (location) {
  if (!(this instanceof ReDOWN))
    return new ReDOWN(location)

  AbstractLevelDOWN.call(this, typeof location == 'string' ? location : '')
  this._store = {}
  this._keys  = []
  var redis_url = require("url").parse(process.env.REDIS || process.env.REDISTOGO_URL);

  this._client  = redis.createClient(redis_url.port, redis_url.hostname);
  if (redis_url.auth) this._client.auth(redis_url.auth.split(":")[1]);
}

util.inherits(ReDOWN, AbstractLevelDOWN)

ReDOWN.prototype._open = function (options, callback) {
  this._client.on('ready', function(){
    console.log('ready')
    callback()
  })
}

ReDOWN.prototype._put = function (key, value, options, callback) {
  this._client.set(key, value, callback);
}

ReDOWN.prototype._get = function (key, options, callback) {
  this._client.get(key, callback)
}

ReDOWN.prototype._del = function (key, options, callback) {
  this._client.del(key, callback)
}

ReDOWN.prototype._batch = function (array, options, callback) {
  var err
    , i = 0
    , key
    , value

  if (Array.isArray(array)) {
    for (; i < array.length; i++) {
      if (array[i]) {
        key = bops.is(array[i].key) ? array[i].key : String(array[i].key)
        err = this._checkKeyValue(key, 'key')
        if (err) return setImmediate(function () { callback(err) })
        if (array[i].type === 'del') {
          this._del(array[i].key, options, noop)
        } else if (array[i].type === 'put') {
          value = bops.is(array[i].value) ? array[i].value : String(array[i].value)
          err = this._checkKeyValue(value, 'value')
          if (err) return setImmediate(function () { callback(err) })
          this._put(key, value, options, noop)
        }
      }
    }
  }
  setImmediate(callback)
}

ReDOWN.prototype._iterator = function (options) {
  return new RedIterator(this, options)
}

ReDOWN.prototype._isBuffer = function (obj) {
  return bops.is(obj)
}

module.exports = ReDOWN
<commit_msg>Fixes taking client as location<commit_after>var util              = require('util')
  , bops              = require('bops')
  , AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN
  , AbstractIterator  = require('abstract-leveldown').AbstractIterator
  , noop              = function () {}
  , setImmediate      = global.setImmediate || process.nextTick
  , redis             = require("redis")

function toKey (key) {
  return typeof key == 'string' ? key : JSON.stringify(key)
}

function RedIterator (db, options) {
  AbstractIterator.call(this, db)
  this._reverse = options.reverse
  this._limit   = options.limit
  this._count   = 0
  this._end     = options.end
  this._start   = options.start
  this._gt      = options.gt
  this._gte     = options.gte
  this._lt      = options.lt
  this._lte     = options.lte

  var i

  if (this._start) {
    for (i = 0; i < this.db._keys.length; i++) {
      if (this.db._keys[i] >= this._start) {
        this._pos = i
        if (this.db._keys[i] != this._start) {
          if (this._reverse) {
            // going backwards and key doesn't match, jump back one
            --this._pos
          }
        } else {
          if (options.exclusiveStart) {
            // key matches but it's a gt or lt
            this._pos += (this._reverse ? -1 : 1)
          }
        }
        break
      }
    }

    if (this._pos == null && !this._reverse) // no matching keys, non starter
      this._pos = -1
  }

  if (!options.start || !this._pos)
    this._pos = this._reverse ? this.db._keys.length - 1 : 0
}

util.inherits(RedIterator, AbstractIterator)

RedIterator.prototype._next = function (callback) {
  var self  = this
    , key   = self.db._keys[self._pos]
    , value

  if (self._pos >= self.db._keys.length || self._pos < 0)
    return setImmediate(callback)

  if (!!self._end && (self._reverse ? key < self._end : key > self._end))
    return setImmediate(callback)

  if (!!self._limit && self._limit > 0 && self._count++ >= self._limit)
    return setImmediate(callback)

  if (  (this._lt  && key >= this._lt)
     || (this._lte && key > this._lte)
     || (this._gt  && key <= this._gt)
     || (this._gte && key < this._gte))
    return setImmediate(callback)

  value = self.db._store[toKey(key)]
  self._pos += self._reverse ? -1 : 1

  setImmediate(function () { callback(null, key, value) })
}

function ReDOWN (location) {
  if (!(this instanceof ReDOWN))
    return new ReDOWN(location)

  AbstractLevelDOWN.call(this, "/tmp/db.tmp");
  this._store = {}
  this._keys  = []
  this._client = location;
}

util.inherits(ReDOWN, AbstractLevelDOWN)

ReDOWN.prototype._open = function (options, callback) {
  this._client.on('ready', function(){
    console.log('ready')
    callback()
  })
}

ReDOWN.prototype._put = function (key, value, options, callback) {
  this._client.set(key, value, callback);
}

ReDOWN.prototype._get = function (key, options, callback) {
  this._client.get(key, callback)
}

ReDOWN.prototype._del = function (key, options, callback) {
  this._client.del(key, callback)
}

ReDOWN.prototype._batch = function (array, options, callback) {
  var err
    , i = 0
    , key
    , value

  if (Array.isArray(array)) {
    for (; i < array.length; i++) {
      if (array[i]) {
        key = bops.is(array[i].key) ? array[i].key : String(array[i].key)
        err = this._checkKeyValue(key, 'key')
        if (err) return setImmediate(function () { callback(err) })
        if (array[i].type === 'del') {
          this._del(array[i].key, options, noop)
        } else if (array[i].type === 'put') {
          value = bops.is(array[i].value) ? array[i].value : String(array[i].value)
          err = this._checkKeyValue(value, 'value')
          if (err) return setImmediate(function () { callback(err) })
          this._put(key, value, options, noop)
        }
      }
    }
  }
  setImmediate(callback)
}

ReDOWN.prototype._iterator = function (options) {
  return new RedIterator(this, options)
}

ReDOWN.prototype._isBuffer = function (obj) {
  return bops.is(obj)
}

module.exports = ReDOWN
<|endoftext|>


<commit_before>var config = require("config");
var Express = require("express");
var brochure = new Express();
var hbs = require("hbs");
var Cache = require("express-disk-cache");
var cache = new Cache(config.cache_directory);
var moment = require("moment");
var fs = require("fs-extra");
const redirector = require("./redirector");

const VIEW_DIRECTORY = __dirname + "/views";
const PARTIAL_DIRECTORY = VIEW_DIRECTORY + "/partials";

const loadPartial = (partial) => {
  let name = partial.slice(0, partial.indexOf("."));
  let value = fs.readFileSync(PARTIAL_DIRECTORY + "/" + partial, "utf-8");
  hbs.registerPartial(name, value);
};

fs.readdirSync(PARTIAL_DIRECTORY).forEach(loadPartial);

if (!config.cache) {
  fs.watch(PARTIAL_DIRECTORY, { recursive: true }, (type, partial) =>
    loadPartial(partial)
  );
}

// Renders dates dynamically in the documentation.
// Can be used like so: {{{date 'MM/YYYY'}}}
hbs.registerHelper("date", function (text) {
  try {
    text = text.trim();
    text = moment.utc(Date.now()).format(text);
  } catch (e) {
    text = "";
  }

  return text;
});

// Neccessary to repeat to set the correct IP for the
// rate-limiter, because this app sits behind nginx
brochure.set("trust proxy", "loopback");

brochure.set("views", VIEW_DIRECTORY);
brochure.set("view engine", "html");
brochure.engine("html", hbs.__express);

if (config.cache === false) {
  // During development we want views to reload as we edit
  brochure.disable("view cache");
} else {
  // This will store responses to disk for NGINX to serve
  brochure.use(cache);
}

// This is the layout that HBS uses by default to render a
// page. Look into the source, but basically {{{body}}} in
// partials/layout is replaced with the view passed to
// res.render(). You can modify this in the route if needed.
brochure.locals.layout = "/partials/layout";
brochure.locals.cacheID = Date.now();

// Default page title and <meta> description
brochure.locals.title = "Blot – A blogging platform with no interface.";
brochure.locals.description =
  "Turns a folder into a blog automatically. Use your favorite text-editor to write. Text and Markdown files, Word Documents, images, bookmarks and HTML in your folder become blog posts.";

brochure.locals.price = "$" + config.stripe.plan.split("_").pop();
brochure.locals.interval =
  config.stripe.plan.indexOf("monthly") === 0 ? "month" : "year";

brochure.use(function (req, res, next) {
  if (
    req.user &&
    req.user.subscription &&
    req.user.subscription.plan &&
    req.user.subscription.plan.amount
  ) {
    res.locals.price = "$" + req.user.subscription.plan.amount / 100;
  }

  next();
});

// Without 'index: false' this will server the index.html files inside the
// views folder in lieu of using the render definied in ./routes below.
// Without 'redirect: false' this will redirect URLs to existent directories
// adding an undesirable trailing slash.
brochure.use(
  "/fonts",
  Express.static(VIEW_DIRECTORY + "/fonts", {
    index: false,
    redirect: false,
    maxAge: 86400000,
  })
);

brochure.use(Express.static(VIEW_DIRECTORY, { index: false, redirect: false }));

brochure.use(trace("before routes"));

// Now we actually load the routes for the brochure website.
brochure.use(require("./routes"));

// Redirect user to dashboard for these links
brochure.use(["/account", "/settings"], function (req, res) {
  let from;

  try {
    let referrer = require("url").parse(req.get("Referrer"));
    if (referrer.host === config.host) from = referrer.path;
  } catch (e) {}

  return res.redirect(
    "/log-in?then=" + req.originalUrl + (from ? "&from=" + from : "")
  );
});

// Will redirect old broken links
brochure.use(redirector);

// Missing page
brochure.use(function (req, res, next) {
  // Pass on requests to static files down to app/blog
  // Express application.
  if (req.path.indexOf("/static") === 0) return next();

  res.status(404);
  res.sendFile(VIEW_DIRECTORY + "/error-404.html");
});

// Some kind of other error
brochure.use(function (err, req, res, next) {
  // Prevent a linter warning for 'next' above
  // jshint unused:false
  res.locals.code = { error: true };

  if (config.environment === "development") {
    console.error(err);
    res.locals.err = err;
  }

  res.status(err.status || 500);
  res.sendFile(VIEW_DIRECTORY + "/error.html");
});

module.exports = brochure;
<commit_msg>Further fix<commit_after>var config = require("config");
var Express = require("express");
var brochure = new Express();
var hbs = require("hbs");
var Cache = require("express-disk-cache");
var cache = new Cache(config.cache_directory);
var moment = require("moment");
var fs = require("fs-extra");
const redirector = require("./redirector");
const trace = require('helper/trace');
const VIEW_DIRECTORY = __dirname + "/views";
const PARTIAL_DIRECTORY = VIEW_DIRECTORY + "/partials";

const loadPartial = (partial) => {
  let name = partial.slice(0, partial.indexOf("."));
  let value = fs.readFileSync(PARTIAL_DIRECTORY + "/" + partial, "utf-8");
  hbs.registerPartial(name, value);
};

fs.readdirSync(PARTIAL_DIRECTORY).forEach(loadPartial);

if (!config.cache) {
  fs.watch(PARTIAL_DIRECTORY, { recursive: true }, (type, partial) =>
    loadPartial(partial)
  );
}

// Renders dates dynamically in the documentation.
// Can be used like so: {{{date 'MM/YYYY'}}}
hbs.registerHelper("date", function (text) {
  try {
    text = text.trim();
    text = moment.utc(Date.now()).format(text);
  } catch (e) {
    text = "";
  }

  return text;
});

// Neccessary to repeat to set the correct IP for the
// rate-limiter, because this app sits behind nginx
brochure.set("trust proxy", "loopback");

brochure.set("views", VIEW_DIRECTORY);
brochure.set("view engine", "html");
brochure.engine("html", hbs.__express);

if (config.cache === false) {
  // During development we want views to reload as we edit
  brochure.disable("view cache");
} else {
  // This will store responses to disk for NGINX to serve
  brochure.use(cache);
}

// This is the layout that HBS uses by default to render a
// page. Look into the source, but basically {{{body}}} in
// partials/layout is replaced with the view passed to
// res.render(). You can modify this in the route if needed.
brochure.locals.layout = "/partials/layout";
brochure.locals.cacheID = Date.now();

// Default page title and <meta> description
brochure.locals.title = "Blot – A blogging platform with no interface.";
brochure.locals.description =
  "Turns a folder into a blog automatically. Use your favorite text-editor to write. Text and Markdown files, Word Documents, images, bookmarks and HTML in your folder become blog posts.";

brochure.locals.price = "$" + config.stripe.plan.split("_").pop();
brochure.locals.interval =
  config.stripe.plan.indexOf("monthly") === 0 ? "month" : "year";

brochure.use(function (req, res, next) {
  if (
    req.user &&
    req.user.subscription &&
    req.user.subscription.plan &&
    req.user.subscription.plan.amount
  ) {
    res.locals.price = "$" + req.user.subscription.plan.amount / 100;
  }

  next();
});

// Without 'index: false' this will server the index.html files inside the
// views folder in lieu of using the render definied in ./routes below.
// Without 'redirect: false' this will redirect URLs to existent directories
// adding an undesirable trailing slash.
brochure.use(
  "/fonts",
  Express.static(VIEW_DIRECTORY + "/fonts", {
    index: false,
    redirect: false,
    maxAge: 86400000,
  })
);

brochure.use(Express.static(VIEW_DIRECTORY, { index: false, redirect: false }));

brochure.use(trace("before routes"));

// Now we actually load the routes for the brochure website.
brochure.use(require("./routes"));

// Redirect user to dashboard for these links
brochure.use(["/account", "/settings"], function (req, res) {
  let from;

  try {
    let referrer = require("url").parse(req.get("Referrer"));
    if (referrer.host === config.host) from = referrer.path;
  } catch (e) {}

  return res.redirect(
    "/log-in?then=" + req.originalUrl + (from ? "&from=" + from : "")
  );
});

// Will redirect old broken links
brochure.use(redirector);

// Missing page
brochure.use(function (req, res, next) {
  // Pass on requests to static files down to app/blog
  // Express application.
  if (req.path.indexOf("/static") === 0) return next();

  res.status(404);
  res.sendFile(VIEW_DIRECTORY + "/error-404.html");
});

// Some kind of other error
brochure.use(function (err, req, res, next) {
  // Prevent a linter warning for 'next' above
  // jshint unused:false
  res.locals.code = { error: true };

  if (config.environment === "development") {
    console.error(err);
    res.locals.err = err;
  }

  res.status(err.status || 500);
  res.sendFile(VIEW_DIRECTORY + "/error.html");
});

module.exports = brochure;
<|endoftext|>