<commit_before>/*! modernizr 3.0.0-alpha.3 (Custom Build) | MIT *
 * http://v3.modernizr.com/download/#-cssremunit-csstransforms-csstransitions-fontface-mediaqueries-opacity-shiv !*/
!function(e,t,n){function r(e,t){return typeof e===t}function o(){var e,t,n,o,i,a,s;for(var l in y){if(e=[],t=y[l],t.name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(n=0;n<t.options.aliases.length;n++)e.push(t.options.aliases[n].toLowerCase());for(o=r(t.fn,"function")?t.fn():t.fn,i=0;i<e.length;i++)a=e[i],s=a.split("."),1===s.length?Modernizr[s[0]]=o:(!Modernizr[s[0]]||Modernizr[s[0]]instanceof Boolean||(Modernizr[s[0]]=new Boolean(Modernizr[s[0]])),Modernizr[s[0]][s[1]]=o),g.push((o?"":"no-")+s.join("-"))}}function i(e){var t=C.className,n=Modernizr._config.classPrefix||"";if(Modernizr._config.enableJSClass){var r=new RegExp("(^|\\s)"+n+"no-js(\\s|$)");t=t.replace(r,"$1"+n+"js$2")}Modernizr._config.enableClasses&&(t+=" "+n+e.join(" "+n),C.className=t)}function a(){var e=t.body;return e||(e=S("body"),e.fake=!0),e}function s(e,t,n,r){var o,i,s,l,c="modernizr",u=S("div"),f=a();if(parseInt(n,10))for(;n--;)s=S("div"),s.id=r?r[n]:c+(n+1),u.appendChild(s);return o=["",'<style id="s',c,'">',e,"</style>"].join(""),u.id=c,(f.fake?f:u).innerHTML+=o,f.appendChild(u),f.fake&&(f.style.background="",f.style.overflow="hidden",l=C.style.overflow,C.style.overflow="hidden",C.appendChild(f)),i=t(u,e),f.fake?(f.parentNode.removeChild(f),C.style.overflow=l,C.offsetHeight):u.parentNode.removeChild(u),!!i}function l(e,t){return!!~(""+e).indexOf(t)}function c(e){return e.replace(/([a-z])-([a-z])/g,function(e,t,n){return t+n.toUpperCase()}).replace(/^-/,"")}function u(e,t){return function(){return e.apply(t,arguments)}}function f(e,t,n){var o;for(var i in e)if(e[i]in t)return n===!1?e[i]:(o=t[e[i]],r(o,"function")?u(o,n||t):o);return!1}function d(e){return e.replace(/([A-Z])/g,function(e,t){return"-"+t.toLowerCase()}).replace(/^ms-/,"-ms-")}function m(t,r){var o=t.length;if("CSS"in e&&"supports"in e.CSS){for(;o--;)if(e.CSS.supports(d(t[o]),r))return!0;return!1}if("CSSSupportsRule"in e){for(var i=[];o--;)i.push("("+d(t[o])+":"+r+")");return i=i.join(" or "),s("@supports ("+i+") { #modernizr { position: absolute; } }",function(e){return"absolute"==getComputedStyle(e,null).position})}return n}function p(e,t,o,i){function a(){u&&(delete M.style,delete M.modElem)}if(i=r(i,"undefined")?!1:i,!r(o,"undefined")){var s=m(e,o);if(!r(s,"undefined"))return s}var u,f,d,p,h;for(M.style||(u=!0,M.modElem=S("modernizr"),M.style=M.modElem.style),d=e.length,f=0;d>f;f++)if(p=e[f],h=M.style[p],l(p,"-")&&(p=c(p)),M.style[p]!==n){if(i||r(o,"undefined"))return a(),"pfx"==t?p:!0;try{M.style[p]=o}catch(v){}if(M.style[p]!=h)return a(),"pfx"==t?p:!0}return a(),!1}function h(e,t,n,o,i){var a=e.charAt(0).toUpperCase()+e.slice(1),s=(e+" "+j.join(a+" ")+a).split(" ");return r(t,"string")||r(t,"undefined")?p(s,t,o,i):(s=(e+" "+k.join(a+" ")+a).split(" "),f(s,t,n))}function v(e,t,r){return h(e,n,n,t,r)}var g=[];!function(e,t){function n(e,t){var n=e.createElement("p"),r=e.getElementsByTagName("head")[0]||e.documentElement;return n.innerHTML="x<style>"+t+"</style>",r.insertBefore(n.lastChild,r.firstChild)}function r(){var e=E.elements;return"string"==typeof e?e.split(" "):e}function o(e,t){var n=E.elements;"string"!=typeof n&&(n=n.join(" ")),"string"!=typeof e&&(e=e.join(" ")),E.elements=n+" "+e,c(t)}function i(e){var t=y[e[v]];return t||(t={},g++,e[v]=g,y[g]=t),t}function a(e,n,r){if(n||(n=t),f)return n.createElement(e);r||(r=i(n));var o;return o=r.cache[e]?r.cache[e].cloneNode():h.test(e)?(r.cache[e]=r.createElem(e)).cloneNode():r.createElem(e),!o.canHaveChildren||p.test(e)||o.tagUrn?o:r.frag.appendChild(o)}function s(e,n){if(e||(e=t),f)return e.createDocumentFragment();n=n||i(e);for(var o=n.frag.cloneNode(),a=0,s=r(),l=s.length;l>a;a++)o.createElement(s[a]);return o}function l(e,t){t.cache||(t.cache={},t.createElem=e.createElement,t.createFrag=e.createDocumentFragment,t.frag=t.createFrag()),e.createElement=function(n){return E.shivMethods?a(n,e,t):t.createElem(n)},e.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+r().join().replace(/[\w\-:]+/g,function(e){return t.createElem(e),t.frag.createElement(e),'c("'+e+'")'})+");return n}")(E,t.frag)}function c(e){e||(e=t);var r=i(e);return!E.shivCSS||u||r.hasCSS||(r.hasCSS=!!n(e,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),f||l(e,r),e}var u,f,d="3.7.2",m=e.html5||{},p=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,h=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",g=0,y={};!function(){try{var e=t.createElement("a");e.innerHTML="<xyz></xyz>",u="hidden"in e,f=1==e.childNodes.length||function(){t.createElement("a");var e=t.createDocumentFragment();return"undefined"==typeof e.cloneNode||"undefined"==typeof e.createDocumentFragment||"undefined"==typeof e.createElement}()}catch(n){u=!0,f=!0}}();var E={elements:m.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:d,shivCSS:m.shivCSS!==!1,supportsUnknownElements:f,shivMethods:m.shivMethods!==!1,type:"default",shivDocument:c,createElement:a,createDocumentFragment:s,addElements:o};e.html5=E,c(t)}(this,t);var y=[],E={_version:"3.0.0-alpha.3",_config:{classPrefix:"voxel-",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var n=this;setTimeout(function(){t(n[e])},0)},addTest:function(e,t,n){y.push({name:e,fn:t,options:n})},addAsyncTest:function(e){y.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=E,Modernizr=new Modernizr;var C=t.documentElement,S=function(){return"function"!=typeof t.createElement?t.createElement(arguments[0]):t.createElement.apply(t,arguments)};Modernizr.addTest("cssremunit",function(){var e=S("div");try{e.style.fontSize="3rem"}catch(t){}return/rem/.test(e.style.fontSize)});var b=E._config.usePrefixes?" -webkit- -moz- -o- -ms- ".split(" "):[];E._prefixes=b,Modernizr.addTest("opacity",function(){var e=S("div"),t=e.style;return t.cssText=b.join("opacity:.55;"),/^0.55$/.test(t.opacity)});var x=E.testStyles=s,w=function(){var e=navigator.userAgent,t=e.match(/applewebkit\/([0-9]+)/gi)&&parseFloat(RegExp.$1),n=e.match(/w(eb)?osbrowser/gi),r=e.match(/windows phone/gi)&&e.match(/iemobile\/([0-9])+/gi)&&parseFloat(RegExp.$1)>=9,o=533>t&&e.match(/android/gi);return n||o||r}();w?Modernizr.addTest("fontface",!1):x('@font-face {font-family:"font";src:url("https://")}',function(e,n){var r=t.getElementById("smodernizr"),o=r.sheet||r.styleSheet,i=o?o.cssRules&&o.cssRules[0]?o.cssRules[0].cssText:o.cssText||"":"",a=/src/i.test(i)&&0===i.indexOf(n.split(" ")[0]);Modernizr.addTest("fontface",a)});var _=function(){var t=e.matchMedia||e.msMatchMedia;return t?function(e){var n=t(e);return n&&n.matches||!1}:function(t){var n=!1;return s("@media "+t+" { #modernizr { position: absolute; } }",function(t){n="absolute"==(e.getComputedStyle?e.getComputedStyle(t,null):t.currentStyle).position}),n}}(),T=E.mq=_;Modernizr.addTest("mediaqueries",T("only all"));var z="Moz O ms Webkit",j=E._config.usePrefixes?z.split(" "):[];E._cssomPrefixes=j;var k=E._config.usePrefixes?z.toLowerCase().split(" "):[];E._domPrefixes=k;var F={elem:S("modernizr")};Modernizr._q.push(function(){delete F.elem});var M={style:F.elem.style};Modernizr._q.unshift(function(){delete M.style}),E.testAllProps=h,E.testAllProps=v,Modernizr.addTest("csstransforms",function(){return-1===navigator.userAgent.indexOf("Android 2.")&&v("transform","scale(1)",!0)}),Modernizr.addTest("csstransitions",v("transition","all",!0)),o(),i(g),delete E.addTest,delete E.addAsyncTest;for(var N=0;N<Modernizr._q.length;N++)Modernizr._q[N]();e.Modernizr=Modernizr}(window,document);
<commit_msg>Upgrade Modernizr to include CSS filter detection.<commit_after>/*! modernizr 3.0.0-alpha.3 (Custom Build) | MIT *
 * http://v3.modernizr.com/download/#-cssfilters-cssremunit-csstransforms-csstransitions-fontface-mediaqueries-opacity-shiv !*/
!function(e,t,n){function r(e,t){return typeof e===t}function o(){var e,t,n,o,i,s,a;for(var l in y){if(e=[],t=y[l],t.name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(n=0;n<t.options.aliases.length;n++)e.push(t.options.aliases[n].toLowerCase());for(o=r(t.fn,"function")?t.fn():t.fn,i=0;i<e.length;i++)s=e[i],a=s.split("."),1===a.length?Modernizr[a[0]]=o:(!Modernizr[a[0]]||Modernizr[a[0]]instanceof Boolean||(Modernizr[a[0]]=new Boolean(Modernizr[a[0]])),Modernizr[a[0]][a[1]]=o),g.push((o?"":"no-")+a.join("-"))}}function i(e){var t=C.className,n=Modernizr._config.classPrefix||"";if(Modernizr._config.enableJSClass){var r=new RegExp("(^|\\s)"+n+"no-js(\\s|$)");t=t.replace(r,"$1"+n+"js$2")}Modernizr._config.enableClasses&&(t+=" "+n+e.join(" "+n),C.className=t)}function s(){var e=t.body;return e||(e=E("body"),e.fake=!0),e}function a(e,t,n,r){var o,i,a,l,c="modernizr",u=E("div"),f=s();if(parseInt(n,10))for(;n--;)a=E("div"),a.id=r?r[n]:c+(n+1),u.appendChild(a);return o=["",'<style id="s',c,'">',e,"</style>"].join(""),u.id=c,(f.fake?f:u).innerHTML+=o,f.appendChild(u),f.fake&&(f.style.background="",f.style.overflow="hidden",l=C.style.overflow,C.style.overflow="hidden",C.appendChild(f)),i=t(u,e),f.fake?(f.parentNode.removeChild(f),C.style.overflow=l,C.offsetHeight):u.parentNode.removeChild(u),!!i}function l(e,t){return!!~(""+e).indexOf(t)}function c(e){return e.replace(/([a-z])-([a-z])/g,function(e,t,n){return t+n.toUpperCase()}).replace(/^-/,"")}function u(e,t){return function(){return e.apply(t,arguments)}}function f(e,t,n){var o;for(var i in e)if(e[i]in t)return n===!1?e[i]:(o=t[e[i]],r(o,"function")?u(o,n||t):o);return!1}function d(e){return e.replace(/([A-Z])/g,function(e,t){return"-"+t.toLowerCase()}).replace(/^ms-/,"-ms-")}function p(t,r){var o=t.length;if("CSS"in e&&"supports"in e.CSS){for(;o--;)if(e.CSS.supports(d(t[o]),r))return!0;return!1}if("CSSSupportsRule"in e){for(var i=[];o--;)i.push("("+d(t[o])+":"+r+")");return i=i.join(" or "),a("@supports ("+i+") { #modernizr { position: absolute; } }",function(e){return"absolute"==getComputedStyle(e,null).position})}return n}function m(e,t,o,i){function s(){u&&(delete P.style,delete P.modElem)}if(i=r(i,"undefined")?!1:i,!r(o,"undefined")){var a=p(e,o);if(!r(a,"undefined"))return a}var u,f,d,m,h;for(P.style||(u=!0,P.modElem=E("modernizr"),P.style=P.modElem.style),d=e.length,f=0;d>f;f++)if(m=e[f],h=P.style[m],l(m,"-")&&(m=c(m)),P.style[m]!==n){if(i||r(o,"undefined"))return s(),"pfx"==t?m:!0;try{P.style[m]=o}catch(v){}if(P.style[m]!=h)return s(),"pfx"==t?m:!0}return s(),!1}function h(e,t,n,o,i){var s=e.charAt(0).toUpperCase()+e.slice(1),a=(e+" "+k.join(s+" ")+s).split(" ");return r(t,"string")||r(t,"undefined")?m(a,t,o,i):(a=(e+" "+F.join(s+" ")+s).split(" "),f(a,t,n))}function v(e,t,r){return h(e,n,n,t,r)}var g=[];!function(e,t){function n(e,t){var n=e.createElement("p"),r=e.getElementsByTagName("head")[0]||e.documentElement;return n.innerHTML="x<style>"+t+"</style>",r.insertBefore(n.lastChild,r.firstChild)}function r(){var e=S.elements;return"string"==typeof e?e.split(" "):e}function o(e,t){var n=S.elements;"string"!=typeof n&&(n=n.join(" ")),"string"!=typeof e&&(e=e.join(" ")),S.elements=n+" "+e,c(t)}function i(e){var t=y[e[v]];return t||(t={},g++,e[v]=g,y[g]=t),t}function s(e,n,r){if(n||(n=t),f)return n.createElement(e);r||(r=i(n));var o;return o=r.cache[e]?r.cache[e].cloneNode():h.test(e)?(r.cache[e]=r.createElem(e)).cloneNode():r.createElem(e),!o.canHaveChildren||m.test(e)||o.tagUrn?o:r.frag.appendChild(o)}function a(e,n){if(e||(e=t),f)return e.createDocumentFragment();n=n||i(e);for(var o=n.frag.cloneNode(),s=0,a=r(),l=a.length;l>s;s++)o.createElement(a[s]);return o}function l(e,t){t.cache||(t.cache={},t.createElem=e.createElement,t.createFrag=e.createDocumentFragment,t.frag=t.createFrag()),e.createElement=function(n){return S.shivMethods?s(n,e,t):t.createElem(n)},e.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+r().join().replace(/[\w\-:]+/g,function(e){return t.createElem(e),t.frag.createElement(e),'c("'+e+'")'})+");return n}")(S,t.frag)}function c(e){e||(e=t);var r=i(e);return!S.shivCSS||u||r.hasCSS||(r.hasCSS=!!n(e,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),f||l(e,r),e}var u,f,d="3.7.2",p=e.html5||{},m=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,h=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",g=0,y={};!function(){try{var e=t.createElement("a");e.innerHTML="<xyz></xyz>",u="hidden"in e,f=1==e.childNodes.length||function(){t.createElement("a");var e=t.createDocumentFragment();return"undefined"==typeof e.cloneNode||"undefined"==typeof e.createDocumentFragment||"undefined"==typeof e.createElement}()}catch(n){u=!0,f=!0}}();var S={elements:p.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:d,shivCSS:p.shivCSS!==!1,supportsUnknownElements:f,shivMethods:p.shivMethods!==!1,type:"default",shivDocument:c,createElement:s,createDocumentFragment:a,addElements:o};e.html5=S,c(t)}(this,t);var y=[],S={_version:"3.0.0-alpha.3",_config:{classPrefix:"voxel-",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var n=this;setTimeout(function(){t(n[e])},0)},addTest:function(e,t,n){y.push({name:e,fn:t,options:n})},addAsyncTest:function(e){y.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=S,Modernizr=new Modernizr;var C=t.documentElement,E=function(){return"function"!=typeof t.createElement?t.createElement(arguments[0]):t.createElement.apply(t,arguments)};Modernizr.addTest("cssremunit",function(){var e=E("div");try{e.style.fontSize="3rem"}catch(t){}return/rem/.test(e.style.fontSize)});var b=S._config.usePrefixes?" -webkit- -moz- -o- -ms- ".split(" "):[];S._prefixes=b,Modernizr.addTest("opacity",function(){var e=E("div"),t=e.style;return t.cssText=b.join("opacity:.55;"),/^0.55$/.test(t.opacity)});var x="CSS"in e&&"supports"in e.CSS,T="supportsCSS"in e;Modernizr.addTest("supports",x||T),Modernizr.addTest("cssfilters",function(){var r=E("div");if(r.style.cssText=b.join("filter:blur(2px); "),Modernizr.supports){var o="CSS"in e?e.CSS.supports("filter","url()"):e.supportsCSS("filter","url()");return o}return!!r.style.length&&(t.documentMode===n||t.documentMode>9)});var w=S.testStyles=a,_=function(){var e=navigator.userAgent,t=e.match(/applewebkit\/([0-9]+)/gi)&&parseFloat(RegExp.$1),n=e.match(/w(eb)?osbrowser/gi),r=e.match(/windows phone/gi)&&e.match(/iemobile\/([0-9])+/gi)&&parseFloat(RegExp.$1)>=9,o=533>t&&e.match(/android/gi);return n||o||r}();_?Modernizr.addTest("fontface",!1):w('@font-face {font-family:"font";src:url("https://")}',function(e,n){var r=t.getElementById("smodernizr"),o=r.sheet||r.styleSheet,i=o?o.cssRules&&o.cssRules[0]?o.cssRules[0].cssText:o.cssText||"":"",s=/src/i.test(i)&&0===i.indexOf(n.split(" ")[0]);Modernizr.addTest("fontface",s)});var z=function(){var t=e.matchMedia||e.msMatchMedia;return t?function(e){var n=t(e);return n&&n.matches||!1}:function(t){var n=!1;return a("@media "+t+" { #modernizr { position: absolute; } }",function(t){n="absolute"==(e.getComputedStyle?e.getComputedStyle(t,null):t.currentStyle).position}),n}}(),j=S.mq=z;Modernizr.addTest("mediaqueries",j("only all"));var M="Moz O ms Webkit",k=S._config.usePrefixes?M.split(" "):[];S._cssomPrefixes=k;var F=S._config.usePrefixes?M.toLowerCase().split(" "):[];S._domPrefixes=F;var N={elem:E("modernizr")};Modernizr._q.push(function(){delete N.elem});var P={style:N.elem.style};Modernizr._q.unshift(function(){delete P.style}),S.testAllProps=h,S.testAllProps=v,Modernizr.addTest("csstransforms",function(){return-1===navigator.userAgent.indexOf("Android 2.")&&v("transform","scale(1)",!0)}),Modernizr.addTest("csstransitions",v("transition","all",!0)),o(),i(g),delete S.addTest,delete S.addAsyncTest;for(var A=0;A<Modernizr._q.length;A++)Modernizr._q[A]();e.Modernizr=Modernizr}(window,document);
<|endoftext|>


<commit_before>/* global $ */
$(document).ready(function () {
  'use strict'
  var danyRok = 960
  var historia = String()
  var koniec = 0 // TODO ogarnąć radzenie sobie z końcem
  var poleTekstowe = document.getElementById('historia')
  var rokKonca = 2016
  var start = 1
  var status
  var zdanie = 'To jest test.'

  // Kod importowany, powiększże literę
  function wielkaPierwszaLitera (arg) {
    var argo = arg
    return argo.charAt(0).toUpperCase() + argo.slice(1)
  }

  // Konwertuj numer arabski na rzymski
  // http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter
  function romanizuj (num) {
    if (!+num) {
      return false
    }
    var digits = String(+num).split('')
    var key = ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM', '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC', '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX']
    var roman = ''
    var i = 3
    while (i--) {
      roman = (key[+digits.pop() + (i * 10)] || '') + roman
    }
    return Array(+digits.join('') + 1).join('M') + roman
  }

  // Losuje któryś z N elementów
  var losuj = function (n) {
    return Math.floor(Math.random() * (n))
  }

  // Prototyp słowa, które pozwala wyciągać wariant metodą .get()
  // Miałem tu ciekawe perypetie, bo nie da się elementów arraya wprost wepchnąć do konstruktora
  // Trzeba pchnąć jeden array, dlatego niżej w get musi wejść najpierw w array[0]
  // A niżej w słowniku trzeba trzepać [[...]]
  // Problemy nieistotne (już), ważne że da się wyciągać deklinację
  function Slowo (materia) {
    this.warianty = Array(materia)
    this.daj = function (deklinacja) {
      var liczba = this.warianty[0].length
      var wylosowane = losuj(liczba)
      var slowo = this.warianty[0][wylosowane][deklinacja]
      return slowo
    }
  }

  // Właściwy słownik
  // Użycie: slowo.daj(deklinacja)
  var bitwa = new Slowo([['bitwa', 'bitwy'], ['potyczka', 'potyczki'], ['starcie', 'starcia']])
  var cesarzWczesny = new Slowo([['Berengar', 'Beregara'], ['Henryk', 'Henryka'], ['Ludwik', 'Ludwika'], ['Otton', 'Ottona']])
  var imieWczesne = new Slowo([['Leszko', 'Leszka'], ['Mieszko', 'Mieszka'], ['Przedbor', 'Przedbora']])
  var miastoWczesne = new Slowo([['Biskupin', 'Biskupinem', 'Biskupinie'], ['Cedynia', 'Cedynią', 'Cedyni'], ['Płock', 'Płockiem', 'Płocku']])
  var plemieObce = new Slowo([['Bułgarzy', 'Bułgarów'], ['Czesi', 'Czechów'], ['Rusini', 'Rusinów']])
  var plemieWlasne = new Slowo([['Lędzianie', 'Lędzian'], ['Polanie', 'Polan'], ['Wiślanie', 'Wiślan']])
  var wizytowal = new Slowo([['gościł u'], ['nawiedził'], ['odwiedził'], ['wizytował']])
  var wladcaWczesny = new Slowo([['kniaź', 'kniazia', 'kniazia'], ['książę', 'księcia', 'księcia'], ['wojewoda', 'wojewody', 'wojewodę']])
  var wyruszyl = new Slowo([['najechał'], ['podjął wyprawę'], ['ruszył'], ['wyruszył']])
  var zjazdWczesny = new Slowo([['sobór'], ['zjazd']])
  var zwyciezyli = new Slowo([['pokonali'], ['rozgromili'], ['złamali obronę'], ['zwyciężyli']])

  // A tutaj wielki generator
  var generator = function () { // eslint-disable-line no-unused-vars
    if (start === 1) { // Generuj chrzest
      status = imieWczesne.daj(0) + ', władca ' + plemieWlasne.daj(1) + ', przyjmuje chrzest od ' + plemieObce.daj(1)
      start = 0
    } else if (start === 0 && danyRok < 1200) { // Generuj pierwszą epokę
      var wariant = losuj(4) // arg = liczba generatorów, ale indeksowane od 0
      if (wariant === 0) { // Władca wyruszył na plemię
        status = imieWczesne.daj(0) + ', ' + wladcaWczesny.daj(0) + ' ' + plemieWlasne.daj(1) + ', ' + wyruszyl.daj(0) + ' na ' + plemieObce.daj(1)
      } else if (wariant === 1) { // Bitwa pod X, Z zwycięża Y
        status = bitwa.daj(0) + ' pod ' + miastoWczesne.daj(1) + '. ' + plemieObce.daj(0) + ' ' + zwyciezyli.daj(0) + ' ' + plemieWlasne.daj(1)
      } else if (wariant === 2) { // Bitwa pod X, Y zwycięża Z
        status = bitwa.daj(0) + ' pod ' + miastoWczesne.daj(1) + '. ' + plemieWlasne.daj(0) + ' ' + zwyciezyli.daj(0) + ' ' + plemieObce.daj(1)
      } else if (wariant === 3) {
        var kturyCesarz = losuj(4) + 1
        kturyCesarz = romanizuj(kturyCesarz)
        status = zjazdWczesny.daj(0) + ' w ' + miastoWczesne.daj(2) + '. ' + cesarzWczesny.daj(0) + ' ' + kturyCesarz + ' ' + wizytowal.daj(0) + ' ' + wladcaWczesny.daj(2) + ' ' + imieWczesne.daj(1)
      }
    } else if (danyRok >= 1200 && danyRok < 1400) { // Generuj drugą epokę
      // Generatory późniejszego średniowiecza
    } else if (danyRok >= 1400 && danyRok < 1600) {
      // Generatory renesansu
    } else if (danyRok >= 1600 && danyRok < 1800) {
      // Generatory baroku
    } else if (danyRok >= 1800 && danyRok < 1914) {
      // Generatory zaborcze
    } else if (danyRok >= 1914 && danyRok < 1946) {
      // Generatory wojenne
    } else if (danyRok >= 1946 && danyRok < 1989) {
      // Generatory komunistyczne
    } else if (danyRok >= 1989 && danyRok < rokKonca) {
      // Generatory współczesne
    }
    status = wielkaPierwszaLitera(status)
    return status
  }

  // Maszynka do kompilowania zdań w historię
  var wystawZdanie = function (wygenerowane) { // TODO: wkomponować to w generator
    var status = '' + danyRok + ' – ' + wygenerowane + '. '
    historia = historia + status + ' '
  }

  // Główna pętla
  var historiaPolski = function () {
    if (start === 1) { // Chrzest Polski w zachowanej dekadzie
      danyRok = danyRok + losuj(10)
      zdanie = generator()
      wystawZdanie(zdanie)
    } else if (danyRok < 1200) { // Wczesne średniowiecze
      danyRok = danyRok + losuj(40) + 1
      zdanie = generator()
      wystawZdanie(zdanie)
    } else if (danyRok >= 1200 && danyRok < 1400) { // Późne średniowiecze
      danyRok = danyRok + losuj(30) + 1
      zdanie = 'późne'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1400 && danyRok < 1600) { // Renesans
      danyRok = danyRok + losuj(25) + 1
      zdanie = 'renesans'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1600 && danyRok < 1800) { // Barok
      danyRok = danyRok + losuj(25) + 1
      zdanie = 'barok'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1800 && danyRok < 1914) { // Zabory
      danyRok = danyRok + losuj(20) + 1
      zdanie = 'zabory'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1914 && danyRok < 1946) { // Wojny i międzywojnie
      danyRok = danyRok + losuj(10) + 1
      zdanie = 'wojnie'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1946 && danyRok < 1989) { // Komunizm
      danyRok = danyRok + losuj(10) + 1
      zdanie = 'komunism'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1989 && danyRok < rokKonca) { // III RP
      danyRok = danyRok + losuj(3) + 1
      zdanie = 'epoka iii rp'
      wystawZdanie(zdanie)
    } else if (danyRok >= rokKonca) {
      danyRok = 2018 // Zamknięcie krypty!
      zdanie = 'Tworzę historię' // TODO wykryj czy komputer, tablet czy telefon
      wystawZdanie(zdanie)
      koniec = 1 // TODO jeśli koniec = 1 to czyścimy ekran i stawiamy nowego tarota (potrzebna generacja całego txtu)
      return 0
    }
    historiaPolski()
    if (koniec === 1) {
      // 'Przelej myśli na papier'
      poleTekstowe.innerHTML += historia
      koniec = 2
      return 1
    }
    if (koniec === 2) {
      return 1
    }
  }

  // Co się stanie po naciśnięciu?
  // TODO: Dynamika przycisku: 0. Jaka jest moja historia? 1. To nie jest moja historia 2. To jest moja historia 1<>2
  $('#przycisk').click(function () {
    historiaPolski()
  })
})
<commit_msg>wolę pracować na laptopie<commit_after>/* global $ */
$(document).ready(function () {
  'use strict'
  var danyRok = 960
  var historia = String()
  var koniec = 0 // TODO ogarnąć radzenie sobie z końcem
  var poleTekstowe = document.getElementById('historia')
  var rokKonca = 2016
  var start = 1
  var status
  var zdanie = 'To jest test.'

  // Kod importowany, powiększże literę
  function wielkaPierwszaLitera (arg) {
    var argo = arg
    return argo.charAt(0).toUpperCase() + argo.slice(1)
  }

  // Konwertuj numer arabski na rzymski
  // http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter
  function romanizuj (num) {
    if (!+num) {
      return false
    }
    var digits = String(+num).split('')
    var key = ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM', '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC', '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX']
    var roman = ''
    var i = 3
    while (i--) {
      roman = (key[+digits.pop() + (i * 10)] || '') + roman
    }
    return Array(+digits.join('') + 1).join('M') + roman
  }

  // Losuje któryś z N elementów
  var losuj = function (n) {
    return Math.floor(Math.random() * (n))
  }

  // Prototyp słowa, które pozwala wyciągać wariant metodą .get()
  // Miałem tu ciekawe perypetie, bo nie da się elementów arraya wprost wepchnąć do konstruktora
  // Trzeba pchnąć jeden array, dlatego niżej w get musi wejść najpierw w array[0]
  // A niżej w słowniku trzeba trzepać [[...]]
  // Problemy nieistotne (już), ważne że da się wyciągać deklinację
  function Slowo (materia) {
    this.warianty = Array(materia)
    this.daj = function (deklinacja) {
      var liczba = this.warianty[0].length
      var wylosowane = losuj(liczba)
      var slowo = this.warianty[0][wylosowane][deklinacja]
      return slowo
    }
  }

  // Właściwy słownik
  // Użycie: slowo.daj(deklinacja)
  var bitwa = new Slowo([['bitwa', 'bitwy'], ['potyczka', 'potyczki'], ['starcie', 'starcia']])
  var budynekWczesny = new Slowo([['baszta', 'baszty'], ['palisada', 'palisady'], ['wały', 'wałów'], ['wieża', 'wieży'], ['zamek', 'zamku']])
  var cesarzWczesny = new Slowo([['Berengar', 'Beregara'], ['Henryk', 'Henryka'], ['Ludwik', 'Ludwika'], ['Otton', 'Ottona']])
  var imieWczesne = new Slowo([['Leszko', 'Leszka'], ['Mieszko', 'Mieszka'], ['Przedbor', 'Przedbora']])
  var miastoWczesne = new Slowo([['Biskupin', 'Biskupinem', 'Biskupinie'], ['Cedynia', 'Cedynią', 'Cedyni'], ['Płock', 'Płockiem', 'Płocku']])
  var plemieObce = new Slowo([['Bułgarzy', 'Bułgarów'], ['Czesi', 'Czechów'], ['Rusini', 'Rusinów']])
  var plemieWlasne = new Slowo([['Lędzianie', 'Lędzian'], ['Polanie', 'Polan'], ['Wiślanie', 'Wiślan']])
  var startuje = new Slowo([['rozpoczął'], ['zaczął']])
  var startujeSie = new Slowo([['rozpoczęła się'], ['zaczęła się']])
  var wizytowal = new Slowo([['gościł u'], ['nawiedził'], ['odwiedził'], ['wizytował']])
  var wladcaWczesny = new Slowo([['kniaź', 'kniazia', 'kniazia'], ['książę', 'księcia', 'księcia'], ['wojewoda', 'wojewody', 'wojewodę']])
  var wyruszyl = new Slowo([['najechał'], ['podjął wyprawę'], ['ruszył'], ['wyruszył']])
  var zjazdWczesny = new Slowo([['sobór'], ['zjazd']])
  var zwyciezyli = new Slowo([['pokonali'], ['rozgromili'], ['złamali obronę'], ['zwyciężyli']])

  // A tutaj wielki generator
  var generator = function () { // eslint-disable-line no-unused-vars
    if (start === 1) { // Generuj chrzest
      status = imieWczesne.daj(0) + ', władca ' + plemieWlasne.daj(1) + ', przyjął chrzest od ' + plemieObce.daj(1)
      start = 0
    } else if (start === 0 && danyRok < 1200) { // Generuj pierwszą epokę
      var wariant = losuj(6) // arg = liczba generatorów, ale indeksowane od 0
      if (wariant === 0) { // Władca wyruszył na plemię
        status = imieWczesne.daj(0) + ', ' + wladcaWczesny.daj(0) + ' ' + plemieWlasne.daj(1) + ', ' + wyruszyl.daj(0) + ' na ' + plemieObce.daj(1)
      } else if (wariant === 1) { // Bitwa pod X, Z zwycięża Y
        status = bitwa.daj(0) + ' pod ' + miastoWczesne.daj(1) + '. ' + plemieObce.daj(0) + ' ' + zwyciezyli.daj(0) + ' ' + plemieWlasne.daj(1)
      } else if (wariant === 2) { // Bitwa pod X, Y zwycięża Z
        status = bitwa.daj(0) + ' pod ' + miastoWczesne.daj(1) + '. ' + plemieWlasne.daj(0) + ' ' + zwyciezyli.daj(0) + ' ' + plemieObce.daj(1)
      } else if (wariant === 3) {
        var kturyCesarz = losuj(4) + 1
        kturyCesarz = romanizuj(kturyCesarz)
        status = zjazdWczesny.daj(0) + ' w ' + miastoWczesne.daj(2) + '. ' + cesarzWczesny.daj(0) + ' ' + kturyCesarz + ' ' + wizytowal.daj(0) + ' ' + wladcaWczesny.daj(2) + ' ' + imieWczesne.daj(1)
      } else if (wariant === 5) {
        status = wladcaWczesny.daj(0) + ' ' + imieWczesne.daj(0) + ' ' + startuje.daj(0) + ' budowę ' + budynekWczesny.daj(1) + ' w ' + miastoWczesne.daj(2)
      }
    } else if (danyRok >= 1200 && danyRok < 1400) { // Generuj drugą epokę
      // Generatory późniejszego średniowiecza
    } else if (danyRok >= 1400 && danyRok < 1600) {
      // Generatory renesansu
    } else if (danyRok >= 1600 && danyRok < 1800) {
      // Generatory baroku
    } else if (danyRok >= 1800 && danyRok < 1914) {
      // Generatory zaborcze
    } else if (danyRok >= 1914 && danyRok < 1946) {
      // Generatory wojenne
    } else if (danyRok >= 1946 && danyRok < 1989) {
      // Generatory komunistyczne
    } else if (danyRok >= 1989 && danyRok < rokKonca) {
      // Generatory współczesne
    }
    status = wielkaPierwszaLitera(status)
    return status
  }

  // Maszynka do kompilowania zdań w historię
  var wystawZdanie = function (wygenerowane) { // TODO: wkomponować to w generator
    var status = '' + danyRok + ' – ' + wygenerowane + '. '
    historia = historia + status + ' '
  }

  // Główna pętla
  var historiaPolski = function () {
    if (start === 1) { // Chrzest Polski w zachowanej dekadzie
      danyRok = danyRok + losuj(10)
      zdanie = generator()
      wystawZdanie(zdanie)
    } else if (danyRok < 1200) { // Wczesne średniowiecze
      danyRok = danyRok + losuj(40) + 1
      zdanie = generator()
      wystawZdanie(zdanie)
    } else if (danyRok >= 1200 && danyRok < 1400) { // Późne średniowiecze
      danyRok = danyRok + losuj(30) + 1
      zdanie = 'późne'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1400 && danyRok < 1600) { // Renesans
      danyRok = danyRok + losuj(25) + 1
      zdanie = 'renesans'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1600 && danyRok < 1800) { // Barok
      danyRok = danyRok + losuj(25) + 1
      zdanie = 'barok'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1800 && danyRok < 1914) { // Zabory
      danyRok = danyRok + losuj(20) + 1
      zdanie = 'zabory'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1914 && danyRok < 1946) { // Wojny i międzywojnie
      danyRok = danyRok + losuj(10) + 1
      zdanie = 'wojnie'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1946 && danyRok < 1989) { // Komunizm
      danyRok = danyRok + losuj(10) + 1
      zdanie = 'komunism'
      wystawZdanie(zdanie)
    } else if (danyRok >= 1989 && danyRok < rokKonca) { // III RP
      danyRok = danyRok + losuj(3) + 1
      zdanie = 'epoka iii rp'
      wystawZdanie(zdanie)
    } else if (danyRok >= rokKonca) {
      danyRok = 2018 // Zamknięcie krypty!
      zdanie = 'Tworzę historię' // TODO wykryj czy komputer, tablet czy telefon
      wystawZdanie(zdanie)
      koniec = 1 // TODO jeśli koniec = 1 to czyścimy ekran i stawiamy nowego tarota (potrzebna generacja całego txtu)
      return 0
    }
    historiaPolski()
    if (koniec === 1) {
      // 'Przelej myśli na papier'
      poleTekstowe.innerHTML += historia
      koniec = 2
      return 1
    }
    if (koniec === 2) {
      return 1
    }
  }

  // Co się stanie po naciśnięciu?
  // TODO: Dynamika przycisku: 0. Jaka jest moja historia? 1. To nie jest moja historia 2. To jest moja historia 1<>2
  $('#przycisk').click(function () {
    historiaPolski()
  })
})
<|endoftext|>


<commit_before>(function($) {
    "use strict";

    $.fn.fallzuSelectpicker = function(devOption) {
        var render = function(el, name, template) {
            el.after(
                '
' +
                    '<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">' +
                        '未指定' +
                        '' +
                    '</button>' +
                    '
' + template + '
' +
                '
'
            );
        };

        $(this).each(function() {
            var el = $(this);

            // Check select element
            var elName = el.attr('name');
            if (el.is('select') && elName != undefined) {
                var template = '';
                el.children().each(function() {
                    var rootOption = $(this);

                    // Check isGroup
                    if (rootOption.is('optgroup')) {
                        // Coming soon
                    } else {
                        template +=
                            '
' +
                                '' +
                                    rootOption.text() +
                                '' +
                            '
';
                    }

                });

                render(el, elName, template);
                el.hide();

                // Binding event
                var dropdownDiv = el.next('.fallzu-select-dropdown[data-name=' + elName + ']').first();
                dropdownDiv.find('.fallzu-select-option').on('click', function(e) {
                    e.preventDefault();
                    var value = $(this).data('val');
                    var text = $(this).text();

                    dropdownDiv.find('.fallzu-select-text').text(text);
                    el.find('option[value=' + value + ']').prop('selected', true);
                });
            }
        });
    };
})(jQuery);
<commit_msg>add group option<commit_after>(function($) {
    "use strict";

    $.fn.fallzuSelectpicker = function(devOption) {
        var render = function(el, name, template) {
            el.after(
                '
' +
                    '<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">' +
                        '未指定' +
                        '' +
                    '</button>' +
                    '
' + template + '
' +
                '
'
            );
        };

        $(this).each(function() {
            var el = $(this);

            // Check select element
            var elName = el.attr('name');
            if (el.is('select') && elName != undefined) {
                var template = '';
                var seletLength = el.children().length;
                el.children().each(function(optionIndex) {
                    var rootOption = $(this);

                    // Check isGroup
                    if (rootOption.is('optgroup')) {
                        rootOption.each(function() {
                            var optionGroup = $(this);
                            var label = optionGroup.attr('label');
                            var length = optionGroup.children().length;

                            optionGroup.children().each(function(index) {
                                var option = $(this);
                                // Label
                                var labelStr = (index === 0) ? ('
' + label + '
') : ('');
                                // hr line
                                var hrStr = (index === length - 1 && optionIndex != seletLength - 1)
                                            ? ('

')
                                            : ('');

                                template +=
                                    '
' +
                                        labelStr +
                                        '' +
                                            option.text() +
                                        '' +
                                        hrStr +
                                    '
';
                            });
                        });
                    } else {
                        template +=
                            '
' +
                                '' +
                                    rootOption.text() +
                                '' +
                            '
';
                    }

                });

                render(el, elName, template);
                el.hide();

                // Binding event
                var dropdownDiv = el.next('.fallzu-select-dropdown[data-name=' + elName + ']').first();
                dropdownDiv.find('.fallzu-select-option').on('click', function(e) {
                    e.preventDefault();
                    var value = $(this).data('val');
                    var text = $(this).text();

                    dropdownDiv.find('.fallzu-select-text').text(text);
                    el.find('option[value=' + value + ']').prop('selected', true);
                });
            }
        });
    };
})(jQuery);
<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular.module('dimApp').directive('dimFarming', Farming);

  function Farming() {
    return {
      controller: FarmingCtrl,
      controllerAs: 'vm',
      bindToController: true,
      scope: {},
      template: `

{{vm.service.itemsMoved}}

DIM is moving Engram and Glimmer items from {{vm.service.store.name}} to the vault and leaving one space open per item type to prevent anything from going to the Postmaster.

<input id="farm-greens" type='checkbox' ng-model='vm.settings.farmGreens' />

<dim-simple-item ng-repeat="item in vm.service.consolidate track by $index" item-data="item" ng-click="vm.consolidate(item, vm.service.store)"></dim-simple-item>

          <button ng-click="vm.stop($event)"></button>

`
    };
  }

  FarmingCtrl.$inject = ['dimFarmingService', 'dimItemMoveService', 'dimSettingsService'];

  function FarmingCtrl(dimFarmingService, dimItemMoveService, dimSettingsService) {
    var vm = this;

    angular.extend(vm, {
      service: dimFarmingService,
      settings: dimSettingsService.farming,
      consolidate: dimItemMoveService.consolidate,
      stop: function($event) {
        $event.preventDefault();
        dimFarmingService.stop();
      }
    });
  }
})();
<commit_msg>Update farming<commit_after>(function() {
  'use strict';

  angular.module('dimApp').directive('dimFarming', Farming);

  function Farming() {
    return {
      controller: FarmingCtrl,
      controllerAs: 'vm',
      bindToController: true,
      scope: {},
      template: `

{{vm.service.itemsMoved}}

{{::'farming_desc' | translate}}

<input id="farm-greens" type='checkbox' ng-model='vm.settings.farmGreens' />{{::'farming_config1' | translate}}

{{::'farming_quickmove' | translate}}

<dim-simple-item ng-repeat="item in vm.service.consolidate track by $index" item-data="item" ng-click="vm.consolidate(item, vm.service.store)"></dim-simple-item>

          <button ng-click="vm.stop($event)">{{::'stop' | translate}}</button>

`
    };
  }

  FarmingCtrl.$inject = ['dimFarmingService', 'dimItemMoveService', 'dimSettingsService'];

  function FarmingCtrl(dimFarmingService, dimItemMoveService, dimSettingsService) {
    var vm = this;

    angular.extend(vm, {
      service: dimFarmingService,
      settings: dimSettingsService.farming,
      consolidate: dimItemMoveService.consolidate,
      stop: function($event) {
        $event.preventDefault();
        dimFarmingService.stop();
      }
    });
  }
})();
<|endoftext|>


<commit_before>jsio('from shared.javascript import Class, bind, delayedFunction')
jsio('import fan.ui.lists.List')

var SortableItem = Class(function() {
	this.init = function(id) { this._id = id }
	this.getId = function() { return this._id }
	this.toString = function() { return (this._sortValue ? 0 : 1) + ':' + this._id }
	this.setSortValue = function(value) { this._sortValue = value }
})

// TODO Move all the methods of this SortedList into List
exports = Class(fan.ui.lists.List, function(supr){

	this._className += ' SortedList'

	this.query = function(query) {
		this._query = query
		return this
	}

	this.sortBy = function(sortBy) {
		this._sortBy = sortBy
		return this
	}

	this.groupBy = function(groupBy, displayProp) {
		this._groupBy = groupBy
		this._groupDisplayProp = displayProp
		this._groupsById = {}
		this._groupsByValue = {}
		return this
	}

	this._createContent = function() {
		supr(this, '_createContent')
		this._defaultGroup = this._create({ className: 'group', parent: this._element })
		this._queryId = fin.query(this._query, bind(this, '_onQueryUpdated'))
	}

	this._onQueryUpdated = function(mutation) {
		if (mutation.op == 'sadd') { this.addItems(mutation.args) }
		if (mutation.op == 'srem') { this.removeItems(mutation.args) }
		this._render()
	}

	this._addItem = function(itemId) {
		var item = new SortableItem(itemId)
		if (this._sortBy) {
			fin.observe(itemId, this._sortBy, bind(this, '_onSortPropChange', itemId))
		}
		if (this._groupBy) {
			fin.observe(itemId, this._groupBy, bind(this, '_onGroupPropChange', itemId))
		}
		this._items.push(item)
		this._itemsById[itemId] = item
		return item
	}

	this._onSortPropChange = function(itemId, op, value) {
		this._itemsById[itemId].setSortValue(value)
		this._render()
	}

	this._getParentFor = function(itemId) {
		return this._groupsById && this._groupsById[itemId] || this._defaultGroup
	}

	this.createDelayedMethod('_render', function() {
		this._items.sort()
		supr(this, '_render')
	})

	this._onGroupPropChange = function(itemId, op, value) {
		if (!value) {
			delete this._groupsById[itemId]
			return
		}
		var groups = this._groupsByValue
		if (!groups[value]) {
			groups[value] = this._create({ className: 'group', parent: this._element })
			var header = this._create({ className: 'header', parent: groups[value] })
			fin.observe(value, this._groupDisplayProp, function(op, value) { header.innerHTML = value })
		}
		this._groupsById[itemId] = groups[value]
		this._render()
	}
})

<commit_msg>If there is a sort value, use that. Else, put the item at the end of the list by giving it value zzz<commit_after>jsio('from shared.javascript import Class, bind, delayedFunction')
jsio('import fan.ui.lists.List')

var SortableItem = Class(function() {
	this.init = function(id) { this._id = id }
	this.getId = function() { return this._id }
	this.toString = function() {
		var sortValue = (this._sortValue ? this._sortValue : 'zzz') + ':' + this._id // zzz is there to come last
		return sortValue.toLowerCase()
	}
	this.setSortValue = function(value) { this._sortValue = value }
})

// TODO Move all the methods of this SortedList into List
exports = Class(fan.ui.lists.List, function(supr){

	this._className += ' SortedList'

	this.query = function(query) {
		this._query = query
		return this
	}

	this.sortBy = function(sortBy) {
		this._sortBy = sortBy
		return this
	}

	this.groupBy = function(groupBy, displayProp) {
		this._groupBy = groupBy
		this._groupDisplayProp = displayProp
		this._groupsById = {}
		this._groupsByValue = {}
		return this
	}

	this._createContent = function() {
		supr(this, '_createContent')
		this._defaultGroup = this._create({ className: 'group', parent: this._element })
		this._queryId = fin.query(this._query, bind(this, '_onQueryUpdated'))
	}

	this._onQueryUpdated = function(mutation) {
		if (mutation.op == 'sadd') { this.addItems(mutation.args) }
		if (mutation.op == 'srem') { this.removeItems(mutation.args) }
		this._render()
	}

	this._addItem = function(itemId) {
		var item = new SortableItem(itemId)
		if (this._sortBy) {
			fin.observe(itemId, this._sortBy, bind(this, '_onSortPropChange', itemId))
		}
		if (this._groupBy) {
			fin.observe(itemId, this._groupBy, bind(this, '_onGroupPropChange', itemId))
		}
		this._items.push(item)
		this._itemsById[itemId] = item
		return item
	}

	this._onSortPropChange = function(itemId, op, value) {
		this._itemsById[itemId].setSortValue(value)
		this._render()
	}

	this._getParentFor = function(itemId) {
		return this._groupsById && this._groupsById[itemId] || this._defaultGroup
	}

	this.createDelayedMethod('_render', function() {
		this._items.sort()
		supr(this, '_render')
	})

	this._onGroupPropChange = function(itemId, op, value) {
		if (!value) {
			delete this._groupsById[itemId]
			return
		}
		var groups = this._groupsByValue
		if (!groups[value]) {
			groups[value] = this._create({ className: 'group', parent: this._element })
			var header = this._create({ className: 'header', parent: groups[value] })
			fin.observe(value, this._groupDisplayProp, function(op, value) { header.innerHTML = value })
		}
		this._groupsById[itemId] = groups[value]
		this._render()
	}
})

<|endoftext|>


<commit_before>var fs = require('fs');
var url = require('url');
var pem = require('pem');
var https = require('https');
var join = require('path').join;
var cheerio = require('cheerio');
var request = require('request');
var thunkify = require('thunkify');

// CRX packaging module, instantiated with the `new` keyword
var Extension = require('crx');

// POST /generate
module.exports = function *() {
    // Get target URL from input
    var url = this.request.body.url;

    // Build .crx config for the provided URL
    var crxConfig = yield exports.buildCrxConfig(url);

    // Generate the .crx file based on the config
    var crxBuffer = yield exports.generateCrx(crxConfig);

    // Send it to the browser (save to disk)
    yield exports.sendCrx(this, crxConfig, crxBuffer);
};

exports.getCrxTitle = function (dom, crxConfig) {

    // Extract extension title from the dom's <title> tag
    var title = dom('title').text().trim() || crxConfig.parsedUrl.hostname;

    // Handle custom use-cases per hostname
    switch (crxConfig.host) {
        case 'messenger.com':
            // Fix weird 0x8234 chars in FB messenger <title>
            title = 'Messenger';
            break;
    }
    return title;
};
exports.buildCrxConfig = function *(targetUrl) {

    var parsedUrl = exports.parseUrl(targetUrl);

    // Prepare crx object with default values
    var crxConfig = {
        url: targetUrl,
        parsedUrl: parsedUrl,
        title: parsedUrl.hostname,
        filename: parsedUrl.hostname + '.crx'
    };

    // Normalize hostname for custom use-cases
    crxConfig.host = parsedUrl.hostname.toLowerCase().replace('www.', '');

    var dom;

    // Execute GET request to provided URL
    // May fail for internal URLs, continue anyway
    try {
        dom = yield exports.getPageDOM(crxConfig.url);
    }
    catch (exc) {
        return crxConfig;
    }

    // Extract .crx icon from page's shortcut-icon <link> element
    crxConfig.icon = dom('link[rel="icon"], link[rel="shortcut icon"]').attr('href');

    crxConfig.title = exports.getCrxTitle(dom, crxConfig);
};

exports.parseUrl = function (targetUrl) {
    // Bad input?
    if (!targetUrl) {
        throw new Error('Please provide a URL to continue.');
    }

    // Parse URL (to retrieve hostname and verify its validity)
    var parsedUrl = url.parse(targetUrl);

    // Parse failed?
    if (!parsedUrl || !parsedUrl.protocol || parsedUrl.protocol.indexOf('http') == -1) {
        throw new Error('Please provide a valid URL for your extension. (It must start with http(s)://)');
    }

    return parsedUrl;
};

exports.getPageDOM = function* (url) {

    // Prepare request (send fake browser user-agent header)
    var req = {
        url: url,
        headers: {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
        }
    };

    var response = yield thunkify(request)(req);

    // Load DOM into Cheerio (HTML parser)
    return cheerio.load(response[0].body);
};

exports.generateCrx = function* (crxConfig) {
    // Generate pem certificate
    var cert = yield thunkify(pem.createCertificate)({days: 365 * 10, selfSigned: true});

    // Init new .crx extension with our private key
    var crx = new Extension({privateKey: cert.clientKey});

    // Load extension manifest and default icon
    yield crx.load(join(__dirname, "../lib/extension/files"));

    // Set extension title to extension URL's <title>
    crx.manifest.name = crxConfig.title;

    // Ask for permission to access the specified URL
    crx.manifest.app.urls.push(crxConfig.url);

    // Configure the launch behavior of the extension to the specfied URL
    crx.manifest.app.launch.web_url = crxConfig.url;

    // Override extension icon if we prepared one for this host
    yield exports.overrideIconIfExists(crxConfig, crx);

    // Only continue if we haven't overriden the icon
    if (!crxConfig.iconOverriden) {
        // Got a favicon from the host's HTML?
        if (crxConfig.icon) {
            // Download it and overwrite default icon
            yield exports.downloadIcon(crxConfig, crx);
        }
        else {
            // Set a placeholder icon instead (letter)
            yield exports.setPlaceholderIcon(crxConfig, crx);
        }
    }

    // Pack the extension into a .crx and return its buffer
    var crxBuffer = yield crx.pack();

    // Return buffer
    return crxBuffer;
};

exports.downloadIcon = function*(crxConfig, crx) {
    // Convert relative icon path to absolute
    var absoluteIconUrl = url.resolve(crxConfig.url, crxConfig.icon);

    // Resolve succeeded?
    if (absoluteIconUrl) {
        // Set download path as current extension icon's path
        var downloadPath = crx.path + "/" + crx.manifest.icons['128'];

        // Download it
        yield exports.downloadFile(absoluteIconUrl, downloadPath);
    }
};

exports.overrideIconIfExists = function*(crxConfig, crx) {
    // Build path to override icon
    var iconPath = join(__dirname, '../assets/icons/' + crxConfig.host + '.png');

    try {
        // Check if icon exists
        fs.accessSync(iconPath, fs.F_OK);
    }
    catch (e) {
        // No such file
        return;
    }

    // Set target copy path as current extension icon's path
    var copyToPath = crx.path + "/" + crx.manifest.icons['128'];

    // Copy the local file and override extension's default icon
    yield exports.copyLocalFile(iconPath, copyToPath);

    // Avoid downloading the original favicon or setting a placeholder one
    crxConfig.iconOverriden = true;
};

exports.setPlaceholderIcon = function*(crxConfig, crx) {
    // Grab first char (hopefully a letter)
    var letter = crxConfig.parsedUrl.hostname.substring(0, 1).toUpperCase();

    // Not an English letter?
    if (!letter.match(/[A-Z]/)) {
        return;
    }

    // Build path to placeholder letter icon
    var copyFromPath = join(__dirname, '../lib/extension/icons/fallback/' + letter + '.png');

    // Set target copy path as current extension icon's path
    var copyToPath = crx.path + "/" + crx.manifest.icons['128'];

    // Copy the local file and override extension's default icon
    yield exports.copyLocalFile(copyFromPath, copyToPath);
};

exports.sendCrx = function*(request, crxConfig, crxBuffer) {
    // Set content-type to .crx extension mime type
    request.set('content-type', 'application/x-chrome-extension');

    // Set extension filename
    request.set('content-disposition', 'attachment; filename=' + crxConfig.filename);

    // Set the request body to the .crx file buffer
    request.body = crxBuffer;
};

exports.downloadFile = function (url, filePath) {
    // Promisify the request
    return new Promise(function (resolve, reject) {
        try {
            // Create write stream
            var stream = fs.createWriteStream(filePath);

            // Wait for finish event
            stream.on('finish', function () {
                // Resolve the promise
                return resolve(true);
            });

            // Pipe the request to a file
            return request(url).pipe(stream);
        } catch (e) {
            // Failed
            return reject(e);
        }
    });
};

exports.copyLocalFile = function (from, to) {
    // Promisify the request
    return new Promise(function (resolve, reject) {
        try {
            // Create write stream
            var writeStream = fs.createWriteStream(to);

            // Wait for finish event
            writeStream.on('finish', function () {
                // Resolve the promise
                return resolve(true);
            });

            // Pipe the "from" stream into the "to" stream
            fs.createReadStream(from).pipe(writeStream);
        } catch (e) {
            // Failed
            return reject(e);
        }
    });
};<commit_msg>Reordered function<commit_after>var fs = require('fs');
var url = require('url');
var pem = require('pem');
var https = require('https');
var join = require('path').join;
var cheerio = require('cheerio');
var request = require('request');
var thunkify = require('thunkify');

// CRX packaging module, instantiated with the `new` keyword
var Extension = require('crx');

// POST /generate
module.exports = function *() {
    // Get target URL from input
    var url = this.request.body.url;

    // Build .crx config for the provided URL
    var crxConfig = yield exports.buildCrxConfig(url);

    // Generate the .crx file based on the config
    var crxBuffer = yield exports.generateCrx(crxConfig);

    // Send it to the browser (save to disk)
    yield exports.sendCrx(this, crxConfig, crxBuffer);
};

exports.buildCrxConfig = function *(targetUrl) {

    var parsedUrl = exports.parseUrl(targetUrl);

    // Prepare crx object with default values
    var crxConfig = {
        url: targetUrl,
        parsedUrl: parsedUrl,
        title: parsedUrl.hostname,
        filename: parsedUrl.hostname + '.crx'
    };

    // Normalize hostname for custom use-cases
    crxConfig.host = parsedUrl.hostname.toLowerCase().replace('www.', '');

    var dom;

    // Execute GET request to provided URL
    // May fail for internal URLs, continue anyway
    try {
        dom = yield exports.getPageDOM(crxConfig.url);
    }
    catch (exc) {
        return crxConfig;
    }

    // Extract .crx icon from page's shortcut-icon <link> element
    crxConfig.icon = dom('link[rel="icon"], link[rel="shortcut icon"]').attr('href');

    crxConfig.title = exports.getCrxTitle(dom, crxConfig);
};

exports.getCrxTitle = function (dom, crxConfig) {

    // Extract extension title from the dom's <title> tag
    var title = dom('title').text().trim() || crxConfig.parsedUrl.hostname;

    // Handle custom use-cases per hostname
    switch (crxConfig.host) {
        case 'messenger.com':
            // Fix weird 0x8234 chars in FB messenger <title>
            title = 'Messenger';
            break;
    }
    return title;
};

exports.parseUrl = function (targetUrl) {
    // Bad input?
    if (!targetUrl) {
        throw new Error('Please provide a URL to continue.');
    }

    // Parse URL (to retrieve hostname and verify its validity)
    var parsedUrl = url.parse(targetUrl);

    // Parse failed?
    if (!parsedUrl || !parsedUrl.protocol || parsedUrl.protocol.indexOf('http') == -1) {
        throw new Error('Please provide a valid URL for your extension. (It must start with http(s)://)');
    }

    return parsedUrl;
};

exports.getPageDOM = function* (url) {

    // Prepare request (send fake browser user-agent header)
    var req = {
        url: url,
        headers: {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
        }
    };

    var response = yield thunkify(request)(req);

    // Load DOM into Cheerio (HTML parser)
    return cheerio.load(response[0].body);
};

exports.generateCrx = function* (crxConfig) {
    // Generate pem certificate
    var cert = yield thunkify(pem.createCertificate)({days: 365 * 10, selfSigned: true});

    // Init new .crx extension with our private key
    var crx = new Extension({privateKey: cert.clientKey});

    // Load extension manifest and default icon
    yield crx.load(join(__dirname, "../lib/extension/files"));

    // Set extension title to extension URL's <title>
    crx.manifest.name = crxConfig.title;

    // Ask for permission to access the specified URL
    crx.manifest.app.urls.push(crxConfig.url);

    // Configure the launch behavior of the extension to the specfied URL
    crx.manifest.app.launch.web_url = crxConfig.url;

    // Override extension icon if we prepared one for this host
    yield exports.overrideIconIfExists(crxConfig, crx);

    // Only continue if we haven't overriden the icon
    if (!crxConfig.iconOverriden) {
        // Got a favicon from the host's HTML?
        if (crxConfig.icon) {
            // Download it and overwrite default icon
            yield exports.downloadIcon(crxConfig, crx);
        }
        else {
            // Set a placeholder icon instead (letter)
            yield exports.setPlaceholderIcon(crxConfig, crx);
        }
    }

    // Pack the extension into a .crx and return its buffer
    var crxBuffer = yield crx.pack();

    // Return buffer
    return crxBuffer;
};

exports.downloadIcon = function*(crxConfig, crx) {
    // Convert relative icon path to absolute
    var absoluteIconUrl = url.resolve(crxConfig.url, crxConfig.icon);

    // Resolve succeeded?
    if (absoluteIconUrl) {
        // Set download path as current extension icon's path
        var downloadPath = crx.path + "/" + crx.manifest.icons['128'];

        // Download it
        yield exports.downloadFile(absoluteIconUrl, downloadPath);
    }
};

exports.overrideIconIfExists = function*(crxConfig, crx) {
    // Build path to override icon
    var iconPath = join(__dirname, '../assets/icons/' + crxConfig.host + '.png');

    try {
        // Check if icon exists
        fs.accessSync(iconPath, fs.F_OK);
    }
    catch (e) {
        // No such file
        return;
    }

    // Set target copy path as current extension icon's path
    var copyToPath = crx.path + "/" + crx.manifest.icons['128'];

    // Copy the local file and override extension's default icon
    yield exports.copyLocalFile(iconPath, copyToPath);

    // Avoid downloading the original favicon or setting a placeholder one
    crxConfig.iconOverriden = true;
};

exports.setPlaceholderIcon = function*(crxConfig, crx) {
    // Grab first char (hopefully a letter)
    var letter = crxConfig.parsedUrl.hostname.substring(0, 1).toUpperCase();

    // Not an English letter?
    if (!letter.match(/[A-Z]/)) {
        return;
    }

    // Build path to placeholder letter icon
    var copyFromPath = join(__dirname, '../lib/extension/icons/fallback/' + letter + '.png');

    // Set target copy path as current extension icon's path
    var copyToPath = crx.path + "/" + crx.manifest.icons['128'];

    // Copy the local file and override extension's default icon
    yield exports.copyLocalFile(copyFromPath, copyToPath);
};

exports.sendCrx = function*(request, crxConfig, crxBuffer) {
    // Set content-type to .crx extension mime type
    request.set('content-type', 'application/x-chrome-extension');

    // Set extension filename
    request.set('content-disposition', 'attachment; filename=' + crxConfig.filename);

    // Set the request body to the .crx file buffer
    request.body = crxBuffer;
};

exports.downloadFile = function (url, filePath) {
    // Promisify the request
    return new Promise(function (resolve, reject) {
        try {
            // Create write stream
            var stream = fs.createWriteStream(filePath);

            // Wait for finish event
            stream.on('finish', function () {
                // Resolve the promise
                return resolve(true);
            });

            // Pipe the request to a file
            return request(url).pipe(stream);
        } catch (e) {
            // Failed
            return reject(e);
        }
    });
};

exports.copyLocalFile = function (from, to) {
    // Promisify the request
    return new Promise(function (resolve, reject) {
        try {
            // Create write stream
            var writeStream = fs.createWriteStream(to);

            // Wait for finish event
            writeStream.on('finish', function () {
                // Resolve the promise
                return resolve(true);
            });

            // Pipe the "from" stream into the "to" stream
            fs.createReadStream(from).pipe(writeStream);
        } catch (e) {
            // Failed
            return reject(e);
        }
    });
};<|endoftext|>


<commit_before>/*
 Copyright 2016 Mozilla

 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 this file except in compliance with the License. You may obtain a copy of the
 License at http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software distributed
 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 CONDITIONS OF ANY KIND, either express or implied. See the License for the
 specific language governing permissions and limitations under the License.
 */

/**
 * When life gives you callbacks, write your own promise wrapper.
 *
 * @module SQLite
 */

import sqlite3 from 'sqlite3';
import thenifyAll from 'thenify-all';

const Promise = global.Promise;
const debug = false;

export function verbose() {
  sqlite3.verbose();
}

/**
 * Turn methods on `source` that return callbacks into methods on `dest` that are bound to
 * `source` as if invoked as method calls.
 *
 * @param source an object with methods named by `methods`.
 * @param dest an object upon which attributes will be set.
 * @param methods an array of method names.
 */
function thenifyMethods(source, dest, methods) {
  const wrapped = thenifyAll(source, {}, methods);
  for (const method of methods) {
    dest[method] = wrapped[method].bind(source);
  }
}

export class DB {
  constructor(db) {
    this.db = db;
    thenifyMethods(db, this, ['close', 'get', 'all', 'each', 'exec']);
  }

  prepare(sql, params) {
    return new Promise((resolve, reject) => {
      const statement = this.db.prepare(sql, params, (err) => {
        if (err) {
          reject(err);
        } else {
          resolve(statement);
        }
      });
    });
  }

  run(sql, params) {
    return new Promise((resolve, reject) => {
      this.db.run(sql, params, function(err) {
        if (debug) {
          console.log(`Running: ${sql}, ${JSON.stringify(params)}`);
        }

        if (err) {
          console.log(`SQL error: ${err} in ${sql}.`);
          reject(err);
        } else {
          resolve({ lastID: this.lastID, changes: this.changes });
        }
      });
    });
  }

  /**
   *
   * @param filename the file path to open
   * @param mode any mode flags to pass to `sqlite3.Database`.
   *             Defaults to OPEN_CREATE | OPEN_READWRITE.
   * @returns Promise that resolves to the opened database.
   */
  static open(filename, mode = sqlite3.OPEN_CREATE | sqlite3.OPEN_READWRITE) {
    return new Promise((resolve, reject) => {
      const sq = new sqlite3.Database(filename, mode, (err) => {
        if (err) {
          reject(err);
        } else {
          resolve(new DB(sq));
        }
      });
    });
  }
}
<commit_msg>Provide our own working db.each method. r=nalexander<commit_after>/*
 Copyright 2016 Mozilla

 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 this file except in compliance with the License. You may obtain a copy of the
 License at http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software distributed
 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 CONDITIONS OF ANY KIND, either express or implied. See the License for the
 specific language governing permissions and limitations under the License.
 */

/**
 * When life gives you callbacks, write your own promise wrapper.
 *
 * @module SQLite
 */

import sqlite3 from 'sqlite3';
import thenifyAll from 'thenify-all';

const Promise = global.Promise;
const debug = false;

export function verbose() {
  sqlite3.verbose();
}

/**
 * Turn methods on `source` that return callbacks into methods on `dest` that are bound to
 * `source` as if invoked as method calls.
 *
 * @param source an object with methods named by `methods`.
 * @param dest an object upon which attributes will be set.
 * @param methods an array of method names.
 */
function thenifyMethods(source, dest, methods) {
  const wrapped = thenifyAll(source, {}, methods);
  for (const method of methods) {
    dest[method] = wrapped[method].bind(source);
  }
}

export class DB {
  constructor(db) {
    this.db = db;
    thenifyMethods(db, this, ['close', 'get', 'all', 'exec']);
  }

  prepare(sql, params) {
    return new Promise((resolve, reject) => {
      const statement = this.db.prepare(sql, params, (err) => {
        if (err) {
          reject(err);
        } else {
          resolve(statement);
        }
      });
    });
  }

  /**
   * Invokes the provided `onRow` callback with each result row.
   * Returns a promise that resolves to the number of returned rows.
   *
   * @param sql the query to run.
   * @param params any parameters to bind.
   * @param onRow a function of one argument, `(row)`.
   * @returns {Promise<int>} the number of returned rows.
   */
  each(sql, params, onRow) {
    return new Promise((resolve, reject) => {
      let done = false;

      const rowCallback = (err, row) => {
        if (done) {
          return;
        }

        if (err) {
          console.log(`SQL error in row function: ${err} in ${sql}.`);
          done = true;
          reject(err);
          return;
        }

        onRow(row);
      };

      const completionCallback = (err, count) => {
        if (err) {
          console.log(`SQL error in completion function: ${err} in ${sql}.`);
          reject(err);
          return;
        }

        resolve(count);
      };

      this.db.each(sql, params, rowCallback, completionCallback);
    });
  }

  run(sql, params) {
    return new Promise((resolve, reject) => {
      this.db.run(sql, params, function(err) {
        if (debug) {
          console.log(`Running: ${sql}, ${JSON.stringify(params)}`);
        }

        if (err) {
          console.log(`SQL error: ${err} in ${sql}.`);
          reject(err);
        } else {
          resolve({ lastID: this.lastID, changes: this.changes });
        }
      });
    });
  }

  /**
   *
   * @param filename the file path to open
   * @param mode any mode flags to pass to `sqlite3.Database`.
   *             Defaults to OPEN_CREATE | OPEN_READWRITE.
   * @returns Promise that resolves to the opened database.
   */
  static open(filename, mode = sqlite3.OPEN_CREATE | sqlite3.OPEN_READWRITE) {
    return new Promise((resolve, reject) => {
      const sq = new sqlite3.Database(filename, mode, (err) => {
        if (err) {
          reject(err);
        } else {
          resolve(new DB(sq));
        }
      });
    });
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import {render} from 'react-dom';

import App from './components/app/App';

import {Store} from 'react-chrome-redux';
import {Provider} from 'react-redux';

const proxyStore = new Store({
  portName: 'example'
});

render(
    <Provider store={proxyStore}><App /></Provider>
  , document.getElementById('app'));
<commit_msg>wait for proxyStore to connect to store<commit_after>import React from 'react';
import {render} from 'react-dom';

import App from './components/app/App';

import {Store} from 'react-chrome-redux';
import {Provider} from 'react-redux';

const proxyStore = new Store({
  portName: 'example'
});

proxyStore.ready().then(() => {
  render(
     <Provider store={proxyStore}><App /></Provider>
    ,document.getElementById('app'));
});

<|endoftext|>


<commit_before>Template.attachmentsGalery.events({
  'click .js-add-attachment': Popup.open('cardAttachments'),
  'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete',
    function() {
      Attachments.remove(this._id);
      Popup.close();
    }
  ),
  // If we let this event bubble, FlowRouter will handle it and empty the page
  // content, see #101.
  'click .js-download'(event) {
    event.stopPropagation();
  },
  'click .js-add-cover'() {
    Cards.findOne(this.cardId).setCover(this._id);
  },
  'click .js-remove-cover'() {
    Cards.findOne(this.cardId).unsetCover();
  },
  'click .js-preview-image'(evt) {
    Popup.open('previewAttachedImage').call(this, evt);
    // when multiple thumbnails, if click one then another very fast,
    // we might get a wrong width from previous img.
    // when popup reused, onRendered() won't be called, so we cannot get there.
    // here make sure to get correct size when this img fully loaded.
    const img = $('img.preview-large-image')[0];
    if (!img) return;
    const rePosPopup = () => {
      const w = img.width;
      const h = img.height;
      // if the image is too large, we resize & center the popup.
      if (w > 300) {
        $('div.pop-over').css({
          width: (w + 20),
          position: 'absolute',
          left: (window.innerWidth - w)/2,
          top: (window.innerHeight - h)/2,
        });
      }
    };
    const url = $(evt.currentTarget).attr('src');
    if (img.src === url && img.complete)
      rePosPopup();
    else
      img.onload = rePosPopup;
  },
});

Template.previewAttachedImagePopup.events({
  'click .js-large-image-clicked'(){
    Popup.close();
  },
});

Template.cardAttachmentsPopup.events({
  'change .js-attach-file'(evt) {
    const card = this;
    FS.Utility.eachFile(evt, (f) => {
      const file = new FS.File(f);
      file.boardId = card.boardId;
      file.cardId = card._id;
      file.userId = Meteor.userId();
      Attachments.insert(file);
      Popup.close();
    });
  },
  'click .js-computer-upload'(evt, tpl) {
    tpl.find('.js-attach-file').click();
    evt.preventDefault();
  },
  'click .js-upload-clipboard-image': Popup.open('previewClipboardImage'),
});

let pastedResults = null;

Template.previewClipboardImagePopup.onRendered(() => {
  // we can paste image from clipboard
  $(document.body).pasteImageReader((results) => {
    if (results.dataURL.startsWith('data:image/')) {
      $('img.preview-clipboard-image').attr('src', results.dataURL);
      pastedResults = results;
    }
  });

  // we can also drag & drop image file to it
  $(document.body).dropImageReader((results) => {
    if (results.dataURL.startsWith('data:image/')) {
      $('img.preview-clipboard-image').attr('src', results.dataURL);
      pastedResults = results;
    }
  });
});

Template.previewClipboardImagePopup.events({
  'click .js-upload-pasted-image'() {
    const results = pastedResults;
    if (results && results.file) {
      const card = this;
      const file = new FS.File(results.file);
      if (!results.name) {
        // if no filename, it's from clipboard. then we give it a name, with ext name from MIME type
        if (typeof results.file.type === 'string') {
          file.name(results.file.type.replace('image/', 'clipboard.'));
        }
      }
      file.updatedAt(new Date());
      file.boardId = card.boardId;
      file.cardId = card._id;
      file.userId = Meteor.userId();
      Attachments.insert(file);
      pastedResults = null;
      $(document.body).pasteImageReader(() => {});
      Popup.close();
    }
  },
});
<commit_msg>Added - auto update card cover with latest uploaded image attachment of card<commit_after>Template.attachmentsGalery.events({
  'click .js-add-attachment': Popup.open('cardAttachments'),
  'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete',
    function() {
      Attachments.remove(this._id);
      Popup.close();
    }
  ),
  // If we let this event bubble, FlowRouter will handle it and empty the page
  // content, see #101.
  'click .js-download'(event) {
    event.stopPropagation();
  },
  'click .js-add-cover'() {
    Cards.findOne(this.cardId).setCover(this._id);
  },
  'click .js-remove-cover'() {
    Cards.findOne(this.cardId).unsetCover();
  },
  'click .js-preview-image'(evt) {
    Popup.open('previewAttachedImage').call(this, evt);
    // when multiple thumbnails, if click one then another very fast,
    // we might get a wrong width from previous img.
    // when popup reused, onRendered() won't be called, so we cannot get there.
    // here make sure to get correct size when this img fully loaded.
    const img = $('img.preview-large-image')[0];
    if (!img) return;
    const rePosPopup = () => {
      const w = img.width;
      const h = img.height;
      // if the image is too large, we resize & center the popup.
      if (w > 300) {
        $('div.pop-over').css({
          width: (w + 20),
          position: 'absolute',
          left: (window.innerWidth - w)/2,
          top: (window.innerHeight - h)/2,
        });
      }
    };
    const url = $(evt.currentTarget).attr('src');
    if (img.src === url && img.complete)
      rePosPopup();
    else
      img.onload = rePosPopup;
  },
});

Template.previewAttachedImagePopup.events({
  'click .js-large-image-clicked'(){
    Popup.close();
  },
});

Template.cardAttachmentsPopup.events({
  'change .js-attach-file'(evt) {
    const card = this;
    FS.Utility.eachFile(evt, (f) => {
      const file = new FS.File(f);
      file.boardId = card.boardId;
      file.cardId = card._id;
      file.userId = Meteor.userId();

      const attachment = Attachments.insert(file);

      if (attachment && attachment._id && attachment.isImage()) {
        card.setCover(attachment._id);
      }

      Popup.close();
    });
  },
  'click .js-computer-upload'(evt, tpl) {
    tpl.find('.js-attach-file').click();
    evt.preventDefault();
  },
  'click .js-upload-clipboard-image': Popup.open('previewClipboardImage'),
});

let pastedResults = null;

Template.previewClipboardImagePopup.onRendered(() => {
  // we can paste image from clipboard
  $(document.body).pasteImageReader((results) => {
    if (results.dataURL.startsWith('data:image/')) {
      $('img.preview-clipboard-image').attr('src', results.dataURL);
      pastedResults = results;
    }
  });

  // we can also drag & drop image file to it
  $(document.body).dropImageReader((results) => {
    if (results.dataURL.startsWith('data:image/')) {
      $('img.preview-clipboard-image').attr('src', results.dataURL);
      pastedResults = results;
    }
  });
});

Template.previewClipboardImagePopup.events({
  'click .js-upload-pasted-image'() {
    const results = pastedResults;
    if (results && results.file) {
      const card = this;
      const file = new FS.File(results.file);
      if (!results.name) {
        // if no filename, it's from clipboard. then we give it a name, with ext name from MIME type
        if (typeof results.file.type === 'string') {
          file.name(results.file.type.replace('image/', 'clipboard.'));
        }
      }
      file.updatedAt(new Date());
      file.boardId = card.boardId;
      file.cardId = card._id;
      file.userId = Meteor.userId();
      Attachments.insert(file);
      pastedResults = null;
      $(document.body).pasteImageReader(() => {});
      Popup.close();
    }
  },
});
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Link } from 'react-router';
import DocumentTitle from 'react-document-title';

import * as TeamActions from '../../actions/TeamActions';
import * as UserActions from '../../actions/UserActions';
import assignToEmpty from '../../utils/assign';

/* Components */
import Team from '../fragments/Team';

class TeamPage extends Component {
  componentDidMount() {
    const { actions, params, teams } = this.props;
    actions.userActiveChanged(teams[params.id].users.map(user => user.id));
  }

  componentWillUpdate(props) {
    const { actions, params, teams } = props;
    actions.userActiveChanged(teams[params.id].users.map(user => user.id));
  }

  componentWillUnmount() {
    this.props.actions.userActiveChanged([]);
  }

  deleteTeam(id) {
    this.props.actions.teamDelete(id, this.redirectToTeamsPage.bind(this));
  }

  redirectToTeamsPage() {
    this.props.history.pushState(null, '/teams');
  }

  render() {
    const { teams, history, params, isAdmin, actions, users } = this.props;

    const team = teams[params.id];
    if (!team) {
      history.pushState(null, '/404');
      return ;
    }

    let editLink;
    let deleteButton;
    if (isAdmin) {
      editLink = (
        <Link className="btn btn-secondary btn-sm" to={`/team/${team.id}/edit`}>Edit team</Link>
      );

      deleteButton = (
        <button className="btn btn-secondary btn-sm" type="button"
          onClick={this.deleteTeam.bind(this, team.id)}>Delete</button>
      );
    }

    const canLink = isAdmin;
    const canUnlink = canLink;
    const onLink = actions.teamLinkUser;
    const onUnlink = actions.teamUnlinkUser;

    return (
      <DocumentTitle title={`Team: ${team.name} | X-Map`}>

          <Link to="/" className="close btn btn-sm btn-secondary">×</Link>

{team.name}

Team profile

#{team.id}

              {editLink}{deleteButton}

            <Team team={team} canLink={canLink} canUnlink={canUnlink} onLink={onLink} onUnlink={onUnlink} users={users}/>

      </DocumentTitle>
    );
  }
}

TeamPage.propTypes = {
  teams: PropTypes.object.isRequired,
  users: PropTypes.object.isRequired,
  params: PropTypes.shape({
    id: PropTypes.string.isRequired
  }).isRequired,
  history: PropTypes.object.isRequired,
  isAdmin: PropTypes.bool,
  actions: PropTypes.object
};

function mapStateToProps(state) {
  return {
    teams: state.teams,
    users: state.users,
    isAdmin: state.session.isAdmin
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(assignToEmpty(TeamActions, UserActions), dispatch)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(TeamPage);
<commit_msg>Ask for confirmation on delete team #100<commit_after>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Link } from 'react-router';
import DocumentTitle from 'react-document-title';

import * as TeamActions from '../../actions/TeamActions';
import * as UserActions from '../../actions/UserActions';
import assignToEmpty from '../../utils/assign';

/* Components */
import Team from '../fragments/Team';

class TeamPage extends Component {
  componentDidMount() {
    const { actions, params, teams } = this.props;
    actions.userActiveChanged(teams[params.id].users.map(user => user.id));
  }

  componentWillUpdate(props) {
    const { actions, params, teams } = props;
    actions.userActiveChanged(teams[params.id].users.map(user => user.id));
  }

  componentWillUnmount() {
    this.props.actions.userActiveChanged([]);
  }

  deleteTeam(id) {
    if (confirm(`Are you sure about permanently delete this team?`)) {
      this.props.actions.teamDelete(id, this.redirectToTeamsPage.bind(this));
    }
  }

  redirectToTeamsPage() {
    this.props.history.pushState(null, '/teams');
  }

  render() {
    const { teams, history, params, isAdmin, actions, users } = this.props;

    const team = teams[params.id];
    if (!team) {
      history.pushState(null, '/404');
      return ;
    }

    let editLink;
    let deleteButton;
    if (isAdmin) {
      editLink = (
        <Link className="btn btn-secondary btn-sm" to={`/team/${team.id}/edit`}>Edit team</Link>
      );

      deleteButton = (
        <button className="btn btn-secondary btn-sm" type="button"
          onClick={this.deleteTeam.bind(this, team.id)}>Delete</button>
      );
    }

    const canLink = isAdmin;
    const canUnlink = canLink;
    const onLink = actions.teamLinkUser;
    const onUnlink = actions.teamUnlinkUser;

    return (
      <DocumentTitle title={`Team: ${team.name} | X-Map`}>

          <Link to="/" className="close btn btn-sm btn-secondary">×</Link>

{team.name}

Team profile

#{team.id}

              {editLink}{deleteButton}

            <Team team={team} canLink={canLink} canUnlink={canUnlink} onLink={onLink} onUnlink={onUnlink} users={users}/>

      </DocumentTitle>
    );
  }
}

TeamPage.propTypes = {
  teams: PropTypes.object.isRequired,
  users: PropTypes.object.isRequired,
  params: PropTypes.shape({
    id: PropTypes.string.isRequired
  }).isRequired,
  history: PropTypes.object.isRequired,
  isAdmin: PropTypes.bool,
  actions: PropTypes.object
};

function mapStateToProps(state) {
  return {
    teams: state.teams,
    users: state.users,
    isAdmin: state.session.isAdmin
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(assignToEmpty(TeamActions, UserActions), dispatch)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(TeamPage);
<|endoftext|>


<commit_before>// Based on Interface Query (iQuery), jQuery plugin, v1.1
// http://e-infotainment.com/projects/interface-query/

(function ($) {
    function trigger($elem, eventType, event, relatedTarget) {
        var originalType = event.type,
            originalEvent = event.originalEvent,
            originalTarget = event.target,
            originalRelatedTarget = event.relatedTarget;

        try {
            event.target = $elem[0];
            event.type = eventType;
            event.originalEvent = null;

            if (relatedTarget)
                event.relatedTarget = relatedTarget;

            $elem.trigger(event);
        }
        finally {
            event.type = originalType;
            event.originalEvent = originalEvent;
            event.target = originalTarget;
            event.relatedTarget = originalRelatedTarget;
        }
    }

    $.fn.forwardMouseEvents = function () {
        var $this = this,
            $lastT = null;

        $this.on('mouseleave', function (e) {
            if ($lastT) {
                if (e.relatedTarget !== $lastT[0]) {
                    trigger($lastT, 'mouseout', e, e.relatedTarget);
                    $lastT = null;
                }
            }
        }).on('mousemove mousedown mouseup mousewheel click dblclick', function (e) {
            if (!$this.is(':visible'))
                return;

            var be = e.originalEvent,
                et = be.type,
                mx = be.clientX,
                my = be.clientY,
                $t;

            $this.hide();
            $t = $(document.elementFromPoint(mx, my));
            $this.show();

            if (!$t) {
                if ($lastT) {
                    trigger($lastT, 'mouseout', e);
                    $lastT = null;
                }
                return;
            }

            trigger($t, et, e);

            if (!$lastT || $t[0] !== $lastT[0]) {
                if ($lastT) {
                    trigger($lastT, 'mouseout', e, $t[0]);
                }
                trigger($t, 'mouseover', e, $lastT ? $lastT[0] : $this[0]);
            }
            $lastT = $t;
        });

        return $this;
    };
})(jQuery);
<commit_msg>Unix line endings.<commit_after>// Based on Interface Query (iQuery), jQuery plugin, v1.1
// http://e-infotainment.com/projects/interface-query/

(function ($) {
    function trigger($elem, eventType, event, relatedTarget) {
        var originalType = event.type,
            originalEvent = event.originalEvent,
            originalTarget = event.target,
            originalRelatedTarget = event.relatedTarget;

        try {
            event.target = $elem[0];
            event.type = eventType;
            event.originalEvent = null;

            if (relatedTarget)
                event.relatedTarget = relatedTarget;

            $elem.trigger(event);
        }
        finally {
            event.type = originalType;
            event.originalEvent = originalEvent;
            event.target = originalTarget;
            event.relatedTarget = originalRelatedTarget;
        }
    }

    $.fn.forwardMouseEvents = function () {
        var $this = this,
            $lastT = null;

        $this.on('mouseleave', function (e) {
            if ($lastT) {
                if (e.relatedTarget !== $lastT[0]) {
                    trigger($lastT, 'mouseout', e, e.relatedTarget);
                    $lastT = null;
                }
            }
        }).on('mousemove mousedown mouseup mousewheel click dblclick', function (e) {
            if (!$this.is(':visible'))
                return;

            var be = e.originalEvent,
                et = be.type,
                mx = be.clientX,
                my = be.clientY,
                $t;

            $this.hide();
            $t = $(document.elementFromPoint(mx, my));
            $this.show();

            if (!$t) {
                if ($lastT) {
                    trigger($lastT, 'mouseout', e);
                    $lastT = null;
                }
                return;
            }

            trigger($t, et, e);

            if (!$lastT || $t[0] !== $lastT[0]) {
                if ($lastT) {
                    trigger($lastT, 'mouseout', e, $t[0]);
                }
                trigger($t, 'mouseover', e, $lastT ? $lastT[0] : $this[0]);
            }
            $lastT = $t;
        });

        return $this;
    };
})(jQuery);
<|endoftext|>


<commit_before>
steal.plugins('jquery/event').then(function($){

$.fn.
/**
 * @function jQuery.fn.triggerAsync
 * @plugin jquery/event/default
 * @parent jquery.event.pause
 *
 * Triggers an event and calls success when the event has finished propagating through the DOM and
 * preventDefault is not called.
 *
 *     $('#panel').triggerAsync('show', function(){
 *       $('#panel').show();
 *     })
 *
 * You can also provide a callback that gets called if preventDefault was called on the event:
 *
 *     $('#panel').triggerAsync('show', function(){
 *       $('#panel').show();
 *     },function(){
 *       $('#other').addClass('error');
 *     })
 *
 * triggerAsync is designed to work with the [jquery.event.pause] plugin although it is defined in
 * jquery/event/default
 *
 * ## API
 *
 *
 * @param {String} type The type of event
 * @param {Object} data The data for the event
 * @param {Function} success(event) a callback function
 * @param {Function} prevented(event) called if preventDefault is called on the
 */
triggerAsync = function(type, data, success, prevented){
	if(typeof data == 'function'){
		success = data;
		data = undefined;
	}

	if ( this[0] ) {
		var event = $.Event( type ),
			old = event.preventDefault;

		event.preventDefault = function(){
			old.apply(this, arguments);
			prevented && prevented(this)
		}
		//event._success= success;
		jQuery.event.trigger( {type: type, _success: success}, data, this[0]  );
	} else{
		success.call(this);
	}
	return this;
}

/**
 * @add jQuery.event.special
 */
//cache default types for performance
var types = {}, rnamespaces= /\.(.*)$/, $event = $.event;
/**
 * @attribute default
 * @parent specialevents
 * @plugin jquery/event/default
 * @download  http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/default/default.js
 * @test jquery/event/default/qunit.html
 * Allows you to perform default actions as a result of an event.
 *
 * Event based APIs are a powerful way of exposing functionality of your widgets.  It also fits in
 * quite nicely with how the DOM works.
 *
 *
 * Like default events in normal functions (e.g. submitting a form), synthetic default events run after
 * all event handlers have been triggered and no event handler has called
 * preventDefault or returned false.
 *
 * To listen for a default event, just prefix the event with default.
 *
 *     $("div").bind("default.show", function(ev){ ... });
 *     $("ul").delegate("li","default.activate", function(ev){ ... });
 *
 *
 * ## Example
 *
 * Lets look at how you could build a simple tabs widget with default events.
 * First with just jQuery:
 *
 * Default events are useful in cases where you want to provide an event based
 * API for users of your widgets.  Users can simply listen to your synthetic events and
 * prevent your default functionality by calling preventDefault.
 *
 * In the example below, the tabs widget provides a show event.  Users of the
 * tabs widget simply listen for show, and if they wish for some reason, call preventDefault
 * to avoid showing the tab.
 *
 * In this case, the application developer doesn't want to show the second
 * tab until the checkbox is checked.
 *
 * @demo jquery/event/default/defaultjquery.html
 *
 * Lets see how we would build this with JavaScriptMVC:
 *
 * @demo jquery/event/default/default.html
 */
$event.special["default"] = {
	add: function( handleObj ) {
		//save the type
		types[handleObj.namespace.replace(rnamespaces,"")] = true;

		//move the handler ...
		var origHandler = handleObj.handler;

		handleObj.origHandler = origHandler;
		handleObj.handler = function(ev, data){
			if(!ev._defaultActions) ev._defaultActions = [];
			ev._defaultActions.push({element: this, handler: origHandler, event: ev, data: data, currentTarget: ev.currentTarget})
		}
	},
	setup: function() {return true},
	triggerDefault : function(event, elem){

		var defaultGetter = jQuery.Event("default."+event.type);

		$.extend(defaultGetter,{
			target: elem,
			_defaultActions: event._defaultActions,
			exclusive : true
		});

		defaultGetter.stopPropagation();

		//default events only work on elements
		if(elem){
			$event.handle.call(elem, defaultGetter);
		}
	},
	checkAndRunDefaults : function(event, elem){
		//fire if there are default actions to run &&
	    //        we have not prevented default &&
	    //        propagation has been stopped or we are at the document element
	    //        we have reached the document
		if (!event.isDefaultPrevented() &&
		    (!event.isPaused || !event.isPaused()) &&  // no paused function or it's not paused
	         event._defaultActions  &&
	        ( ( event.isPropagationStopped() ) ||
	          ( !elem.parentNode && !elem.ownerDocument ) )

	        ) {
			var origNamespace = event.namespace,
				origType = event.type,
				origLiveFired = event.liveFired;
			// put event back
			event.namespace= event.type;
			event.type = "default";
			event.liveFired = null;

			// call each event handler
			for(var i = 0 ; i < event._defaultActions.length; i++){
				var a  = event._defaultActions[i],
					oldHandle = event.handled;
				event.currentTarget = a.currentTarget;
				a.handler.call(a.element, event, a.data);
				event.handled = event.handled === null ? oldHandle : true;
	        }

			event._defaultActions = null; //set to null so everyone else on this element ignores it

			if(event._success){
				event._success(event);
			}

			event.namespace= origNamespace;
			event.type = origType;
			event.liveFired = origLiveFired;

	    }
	}
}

// overwrite trigger to allow default types
var oldTrigger = $event.trigger,
	triggerDefault = $event.special['default'].triggerDefault,
	checkAndRunDefaults = $event.special['default'].checkAndRunDefaults,
	oldData = jQuery._data;

$._data = function(elem, name, data){
	// always need to supply a function to call for handle
	if(!data && name === "handle"){
		var func = oldData.apply(this, arguments);
		return function(e){
			// Discard the second event of a jQuery.event.trigger() and
			// when an event is called after a page has unloaded
			return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
				jQuery.event.handle.apply( this, arguments ) :
				undefined;
		}
	}
	return oldData.apply(this, arguments)
}

$event.trigger =  function defaultTriggerer( event, data, elem, onlyHandlers){
	// Event object or event type
	var type = event.type || event,
		namespaces = [],

	// Caller can pass in an Event, Object, or just an event type string
	event = typeof event === "object" ?
		// jQuery.Event object
		event[ jQuery.expando ] ? event :
		// Object literal
		new jQuery.Event( type, event ) :
		// Just the event type (string)
		new jQuery.Event( type );

    event._defaultActions = []; //set depth for possibly reused events

	oldTrigger.call($.event, event, data, elem, onlyHandlers);
};

});<commit_msg>accidental commit of wrong file, reverted file.<commit_after>steal.plugins('jquery/event/livehack', 'jquery/event/handle').then(function($){

var current,
	rnamespaces = /\.(.*)$/,
	returnFalse = function(){return false},
	returnTrue = function(){return true};

/**
 * @page jquery.event.pause Pause-Resume
 * @plugin jquery/event/pause
 * @parent specialevents
 * The jquery/event/pause plugin adds the ability to pause and
 * resume events.
 *
 *     $('#todos').bind('show', function(ev){
 *       ev.pause();
 *
 *       $(this).load('todos.html', function(){
 *         ev.resume();
 *       });
 *     })
 *
 * When an event is paused, stops calling other event handlers for the
 * event (similar to event.stopImmediatePropagation() ).  But when
 * resume is called on the event, it will begin calling events on event handlers
 * after the 'paused' event handler.
 *
 *
 * Pause-able events complement the [jQuery.event.special.default default]
 * events plugin, providing the ability to easy create widgets with
 * an asynchronous API.
 *
 * ## Example
 *
 * Consider a basic tabs widget that:
 *
 *   - trigger's a __show__ event on panels when they are to be displayed
 *   - shows the panel after the show event.
 *
 * The sudo code for this controller might look like:
 *
 *     $.Controller('Tabs',{
 *       ".button click" : function( el ){
 *         var panel = this.getPanelFromButton( el );
 *         panel.triggerAsync('show', function(){
 *           panel.show();
 *         })
 *       }
 *     })
 *
 * Someone using this plugin would be able to delay the panel showing until ready:
 *
 *     $('#todos').bind('show', function(ev){
 *       ev.pause();
 *
 *       $(this).load('todos.html', function(){
 *         ev.resume();
 *       });
 *     })
 *
 * Or prevent the panel from showing at all:
 *
 *     $('#todos').bind('show', function(ev){
 *       if(! isReady()){
 *         ev.preventDefault();
 *       }
 *     })
 *
 * ## Limitations
 *
 * The element and event handler that the pause is within can not be removed before
 * resume is called.
 *
 * ## Big Example
 *
 * The following example shows a tabs widget where the user is prompted to save, ignore, or keep editing
 * a tab when a new tab is clicked.
 *
 * @demo jquery/event/pause/pause.html
 *
 * It's a long, but great example of how to do some pretty complex state management with JavaScriptMVC.
 *
 */
$.Event.prototype.isPaused = returnFalse

/**
 * @function
 * @parent jquery.event.pause
 * Pauses an event (to be resumed later);
 */
$.Event.prototype.pause = function(){
	current = this;
	this.stopImmediatePropagation();
	this.isPaused = returnTrue;
};
/**
 * @function
 * @parent jquery.event.pause
 *
 * Resumes an event
 */
$.Event.prototype.resume = function(){
	this.isPaused = this.isImmediatePropagationStopped = this.isPropagationStopped = returnFalse;

	var el = this.liveFired || this.currentTarget || this.target,
		defult = $.event.special['default'],
		oldType = this.type;

	// if we were in a 'live' -> run our liveHandler
	if(this.handleObj.origHandler){
		var cur = this.currentTarget;
		this.currentTarget = this.liveFired;
		this.liveFired = undefined;

		liveHandler.call(el, this, cur );
		el = cur;
	}
	if(this.isImmediatePropagationStopped()){
		return false;
	}

	// skip the event the first pass because we've already handled it
	this.firstPass = true;

	if(!this.isPropagationStopped()){
		$.event.trigger(this, [this.handleObj], el, false);
	}

};

function liveHandler( event, after ) {
	var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
		elems = [],
		selectors = [],
		events = jQuery._data( this, "events" );

	// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
	if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
		return;
	}

	if ( event.namespace ) {
		namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
	}

	event.liveFired = this;

	var live = events.live.slice(0);

	for ( j = 0; j < live.length; j++ ) {
		handleObj = live[j];

		if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
			selectors.push( handleObj.selector );

		} else {
			live.splice( j--, 1 );
		}
	}

	match = jQuery( event.target ).closest( selectors, event.currentTarget );

	for ( i = 0, l = match.length; i < l; i++ ) {
		close = match[i];

		for ( j = 0; j < live.length; j++ ) {
			handleObj = live[j];

			if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
				elem = close.elem;
				related = null;

				// Those two events require additional checking
				if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
					event.type = handleObj.preType;
					related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];

					// Make sure not to accidentally match a child element with the same selector
					if ( related && jQuery.contains( elem, related ) ) {
						related = elem;
					}
				}

				if ( !related || related !== elem ) {
					elems.push({ elem: elem, handleObj: handleObj, level: close.level });
				}
			}
		}
	}

	for ( i = 0, l = elems.length; i < l; i++ ) {
		match = elems[i];
		// inserted to only call elements after this point ...
		if(after) {
			if(after === match.elem){
				after = undefined;
			}
			continue;
		}

		if ( maxLevel && match.level > maxLevel ) {
			break;
		}

		event.currentTarget = match.elem;
		event.data = match.handleObj.data;
		event.handleObj = match.handleObj;

		ret = match.handleObj.origHandler.apply( match.elem, arguments );

		if ( ret === false || event.isPropagationStopped() ) {
			maxLevel = match.level;

			if ( ret === false ) {
				stop = false;
			}
			if ( event.isImmediatePropagationStopped() ) {
				break;
			}
		}
	}

	return stop;
}

});<|endoftext|>