{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./jswebplayer/assets/linkicon.png","webpack:///./jswebplayer/assets/options.js","webpack:///./jswebplayer/assets/soundicon.png","webpack:///./jswebplayer/assets/soundicon_pressed.png","webpack:///./jswebplayer/vendor/debugout.js?cf71","webpack:///./jswebplayer/vendor/debugout.js","webpack:///./node_modules/script-loader/addScript.js","webpack:///./src/dialog.ts","webpack:///./src/editor.ts","webpack:///./src/modals.html","webpack:///./src/shapes.ts","webpack:///./src/tutorial.html"],"names":[],"mappings":";QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;;AClFA;AAAe,oFAAuB,iBAAiB,E;;;;;;;;;;;ACAvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;;;;;;;;;;;;ACXA;AAAe,oFAAuB,kBAAkB,E;;;;;;;;;;;;ACAxD;AAAe,oFAAuB,0BAA0B,E;;;;;;;;;;;ACAhE,mBAAO,CAAC,6FAA2E,EAAE,mBAAO,CAAC,wIAAmI,E;;;;;;;;;;;ACAhO,2IAA2I,sBAAsB,wDAAwD,iFAAiF,gEAAgE,iCAAiC,8EAA8E,+HAA+H,yGAAyG,oFAAoF,4FAA4F,+EAA+E,0EAA0E,gFAAgF,6BAA6B,8BAA8B,kCAAkC,uBAAuB,qCAAqC,iBAAiB,0EAA0E,uCAAuC,wGAAwG,0DAA0D,SAAS,gFAAgF,iEAAiE,sBAAsB,sCAAsC,uDAAuD,oCAAoC,oDAAoD,WAAW,SAAS,8JAA8J,OAAO,8GAA8G,kDAAkD,qDAAqD,OAAO,6EAA6E,6CAA6C,qCAAqC,yBAAyB,mIAAmI,kBAAkB,OAAO,gCAAgC,oCAAoC,0CAA0C,WAAW,SAAS,yCAAyC,6EAA6E,4BAA4B,4IAA4I,6CAA6C,qEAAqE,mCAAmC,OAAO,qGAAqG,uCAAuC,iBAAiB,sCAAsC,oDAAoD,0BAA0B,8CAA8C,wBAAwB,gCAAgC,wCAAwC,uCAAuC,oBAAoB,qBAAqB,OAAO,sDAAsD,mCAAmC,gEAAgE,mCAAmC,sDAAsD,4GAA4G,kDAAkD,iEAAiE,SAAS,yEAAyE,OAAO,wEAAwE,iBAAiB,mCAAmC,8BAA8B,8EAA8E,gDAAgD,SAAS,wCAAwC,OAAO,wEAAwE,gEAAgE,mDAAmD,uCAAuC,WAAW,OAAO,iCAAiC,WAAW,SAAS,+CAA+C,+BAA+B,SAAS,2CAA2C,gCAAgC,SAAS,OAAO,yEAAyE,2CAA2C,8CAA8C,oDAAoD,gFAAgF,qCAAqC,yDAAyD,WAAW,wCAAwC,oFAAoF,+DAA+D,kCAAkC,8BAA8B,+GAA+G,oDAAoD,mEAAmE,WAAW,SAAS,uBAAuB,+BAA+B,gCAAgC,OAAO,iPAAiP,6BAA6B,yBAAyB,mCAAmC,iCAAiC,oCAAoC,8BAA8B,wDAAwD,oCAAoC,eAAe,0DAA0D,sCAAsC,eAAe,oBAAoB,sCAAsC,eAAe,aAAa,OAAO,mCAAmC,aAAa,WAAW,OAAO,8BAA8B,WAAW,4BAA4B,SAAS,OAAO,sBAAsB,SAAS,OAAO,uGAAuG,2DAA2D,2CAA2C,SAAS,0BAA0B,6DAA6D,KAAK,yBAAyB,wDAAwD,sBAAsB,mCAAmC,qEAAqE,gDAAgD,0DAA0D,kEAAkE,8BAA8B,gDAAgD,mFAAmF,4CAA4C,eAAe,OAAO,mFAAmF,4CAA4C,eAAe,kBAAkB,aAAa,yBAAyB,mCAAmC,mEAAmE,oCAAoC,EAAE,2DAA2D,kBAAkB,8DAA8D,yBAAyB,8CAA8C,2BAA2B,gBAAgB,OAAO,uDAAuD,4HAA4H,+DAA+D,8BAA8B,gDAAgD,oFAAoF,oEAAoE,eAAe,OAAO,oFAAoF,qEAAqE,0FAA0F,eAAe,aAAa,yBAAyB,mCAAmC,sCAAsC,2DAA2D,kBAAkB,iDAAiD,yCAAyC,2BAA2B,kBAAkB,OAAO,qCAAqC,iBAAiB,qEAAqE,qCAAqC,iBAAiB,qDAAqD,aAAa,sCAAsC,kBAAkB,+DAA+D,kBAAkB,qGAAqG,mCAAmC,aAAa,OAAO,yBAAyB,aAAa,6DAA6D,gCAAgC,mDAAmD,kBAAkB,SAAS,OAAO,8CAA8C,qBAAqB,uBAAuB,WAAW,OAAO,uBAAuB,SAAS,mBAAmB,OAAO,8CAA8C,qCAAqC,sCAAsC,uDAAuD,SAAS,iCAAiC,OAAO,+BAA+B,+CAA+C,OAAO,gGAAgG,uCAAuC,mDAAmD,uCAAuC,oCAAoC,8CAA8C,wCAAwC,+BAA+B,yCAAyC,wCAAwC,0BAA0B,6EAA6E,kDAAkD,2CAA2C,uCAAuC,gEAAgE,+CAA+C,6DAA6D,4DAA4D,gGAAgG,OAAO,uCAAuC,4BAA4B,4BAA4B,kDAAkD,WAAW,sBAAsB,OAAO,6EAA6E,+DAA+D,oBAAoB,oCAAoC,kCAAkC,gDAAgD,4CAA4C,0EAA0E,gEAAgE,kCAAkC,SAAS,OAAO,4EAA4E,KAAK,C;;;;;;;;;;;ACAv2Y;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA;AACA,EAAE;AACF;AACA;AACA;;;;;;;;;;;;;AC1BA;AAAA;AAAA;AACA,yBAAyB;AACzB;AACA;AACA,qBAAqB;AACrB,mBAAmB;AACnB,mBAAmB;AACnB;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8B,8BAA8B,GAAG,+BAA+B;AAC9F;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sEAAsE,EAAE;AACxE,uEAAuE,2BAA2B,+BAA+B,EAAE;AACnI;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA,0EAA0E,8BAA8B;AACxG;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA,mCAAmC,sBAAsB;AACzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAwC,MAAM;AAC9C;AACA,yCAAyC,MAAM;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA,iBAAiB;AACjB,qCAAqC,EAAE;AACvC,qCAAqC;AACrC,aAAa;AACb,SAAS;AACT;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kFAAkF,UAAU;AAC5F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA4B;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mDAAmD,eAAe,YAAY,eAAe,SAAS,kCAAkC;AACxI;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAuB,OAAO;AAC9B;AACA;AACA;AACA;AACA;AACA,iCAAiC;AACjC,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACptBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAkC;AACA;AACQ;AACC;AAC3C;AAC4C;AACC;AACQ;AACd;AACvC;AACA,yCAAyC,qDAAQ;AACd;AACnC,qCAAqC,mDAAM;AAC3C;AACA;AACA;AACA;AACA,8CAAM;AACN;AACA;AACA,qFAAqF,OAAO;AAC5F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qDAAqD;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mGAAmG,YAAY,cAAc;AAC7H;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA,oEAAoE,KAAK,IAAI,2BAA2B,cAAc,IAAI,KAAK,UAAU;AACzI;AACA,8BAA8B,KAAK,GAAG,KAAK;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,wCAAwC;AACxC;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gDAAgD,SAAS,oBAAoB,QAAQ,oBAAoB;AACzG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,gCAAgC,8CAAM;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,qCAAqC;AACxE;AACA;AACA;AACA;AACA,sBAAsB,iBAAiB,SAAS,EAAE;AAClD;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,8CAAM;AAClB,iBAAiB,8CAAM,2CAA2C,EAAE;AACpE,iBAAiB,8CAAM;AACvB,iBAAiB,8CAAM;AACvB,sBAAsB,8CAAM,iDAAiD,8CAAM;AACnF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0BAA0B,iBAAiB,eAAe,EAAE;AAC5D;AACA;AACA;AACA;AACA;AACA;AACA,sCAAsC;AACtC;AACA,SAAS;AACT;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kDAAkD,KAAK;AACvD;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA,kDAAkD,KAAK;AACvD;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yDAAyD,KAAK;AAC9D;AACA;AACA;AACA,kFAAkF,KAAK,EAAE,SAAS;AAClG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC;AACvC,uCAAuC;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gDAAgD,yBAAyB;AACzE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,8CAAM;AAClB;AACA;AACA;AACA,oBAAoB,8CAAM;AAC1B;AACA,oBAAoB,8CAAM;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,8CAAM;AAClB;AACA;AACA;AACA;AACA;AACA,YAAY,8CAAM;AAClB;AACA,QAAQ,8CAAM;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB,KAAK,8CAAM,gFAAgF,EAAE;AACjH;AACA;AACA;AACA;AACA;AACA,mBAAmB,iGAAiG;AACpH;AACA,SAAS;AACT;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,8CAAM;AAClB;AACA;AACA;AACA;AACA,YAAY,8CAAM;AAClB,YAAY,8CAAM;AAClB,YAAY,8CAAM;AAClB;AACA;AACA;AACA,gBAAgB,8CAAM;AACtB,gBAAgB,8CAAM;AACtB,gBAAgB,8CAAM;AACtB;AACA;AACA,YAAY,8CAAM;AAClB;AACA;AACA;AACA;AACA;AACA,iDAAiD,OAAO;AACxD;AACA;AACA;AACA;AACA;AACA,8CAA8C,OAAO;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,8CAAM;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6DAA6D,aAAa;AAC1E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6DAA6D,aAAa;AAC1E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qCAAqC,iBAAiB;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,mCAAmC,2CAA2C;AAC9E,8CAA8C;AAC9C;AACA;AACA,qBAAqB,8CAAM;AAC3B,0BAA0B,8CAAM;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA,uBAAuB,yBAAyB,EAAE;AAClD,oCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,gBAAgB;AAChB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,mBAAmB,6BAA6B;AAChD,qBAAqB,4BAA4B;AACjD,mBAAmB,mCAAmC;AACtD,qBAAqB,6BAA6B;AAClD,qBAAqB,kCAAkC;AACvD,wBAAwB,iCAAiC;AACzD,oBAAoB,mCAAmC;AACvD,mBAAmB,mCAAmC;AACtD,SAAS;AACT,KAAK;AACL;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gCAAgC,UAAU;AAC1C;AACA,6BAA6B,mBAAmB;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8DAA8D,sCAAsC,EAAE;AACtG;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0DAA0D,uCAAuC,EAAE;AACnG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oDAAoD,gCAAgC;AACpF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B;AAC/B;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,QAAQ,8CAAM;AACd,aAAa,8CAAM,2CAA2C,EAAE;AAChE,aAAa,8CAAM,4CAA4C,kBAAkB,6BAA6B,EAAE;AAChH,WAAW,8CAAM,0CAA0C,8CAAM;AACjE,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8CAA8C,OAAO;AACrD;AACA;AACA;AACA;AACA;AACA,eAAe,YAAY;AAC3B,gDAAgD,OAAO;AACvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+DAA+D,OAAO;AACtE;AACA;AACA;AACA;AACA;AACA,2BAA2B,8CAAM;AACjC;AACA,8BAA8B;AAC9B;AACA,WAAW,8CAAM;AACjB;AACA;AACA;AACA,4DAA4D,OAAO;AACnE,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,8BAA8B,sBAAsB,GAAG,8CAAM,QAAQ,GAAG,OAAO;AAC/E;AACA;AACA,4BAA4B,8CAAM;AAClC;AACA,KAAK;AACL;AACA;AACA;AACA,2BAA2B,OAAO,iDAAiD,OAAO;AAC1F,KAAK;AACL;AACA;AACA;AACA;AACA,kEAAkE,OAAO,8BAA8B,OAAO;AAC9G,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,8CAAM;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,8CAAM;AACd;AACA;AACA;AACA;AACA;AACA,SAAS,8CAAM;AACf;AACA;AACA,sDAAsD,8CAAM;AAC5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,gBAAgB,8CAAM;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,8CAAM;AACd;AACA;AACA;AACA,YAAY,8CAAM;AAClB;AACA;AACA;AACA;AACA;AACA,QAAQ,8CAAM;AACd;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,8CAAM;AACV;AACA;AACA;AACA;AACA;AACA,YAAY,8CAAM;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gFAAgF;AAChF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,8CAAM;AACV,CAAC;AACD;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qFAAqF;AACrF;AACA;AACA;AACA,6DAA6D,2CAA2C,eAAe;AACvH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,sBAAsB;AACrD;AACA;AACA;AACA;AACA;AACA,0CAA0C,sBAAsB;AAChE;AACA;AACA;AACA,0CAA0C,sBAAsB;AAChE;AACA,kBAAkB,8CAAM;AACxB;AACA;AACA;AACA,uCAAuC;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,2CAA2C,eAAe;AAC1D;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oCAAoC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,8CAAM;AACV;AACA;AACA;AACA,8BAA8B,GAAG,cAAc,yBAAyB,SAAS,wCAAwC;AACzH;AACA;AACA;AACA,0DAA0D,EAAE;AAC5D;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8B,2BAA2B;AACzD;AACA,QAAQ,8CAAM;AACd,QAAQ,8CAAM;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,8CAAM;AACd,QAAQ,8CAAM;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,wBAAwB;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kEAAkE,OAAO;AACzE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAsC;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+CAA+C;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;AC74CA,67BAA67B,wmNAAwmN,qLAAqL,0wDAA0wD,s2HAAs2H,yJAAyJ,qNAAqN,mipBAAmipB,iXAAiX,0uBAA0uB,4LAA4L,mrFAAmrF,uMAAuM,8bAA8b,m2FAAm2F,6lGAA6lG,8FAA8F,+jE;;;;;;;;;;;;ACAx05C;AAAA;AAAA;AAAkC;AAC3B;AACP;AACA;AACA,uBAAuB,UAAU;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6DAA6D,oBAAoB,EAAE;AACnF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA,aAAa;AACb;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,kBAAkB;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,8CAAM;AACtB,qBAAqB,8CAAM,2CAA2C,EAAE;AACxE,qBAAqB,8CAAM;AAC3B,mBAAmB,8CAAM;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,iBAAiB;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,8CAAM;AAClB,YAAY,8CAAM;AAClB;AACA;AACA;AACA;AACA,aAAa;AACb,gBAAgB,8CAAM;AACtB,gBAAgB,8CAAM;AACtB,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC;AACjC,gBAAgB,8CAAM;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAwB,8CAAM;AAC9B;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB,8CAAM;AAC/B;AACA,yBAAyB,8CAAM;AAC/B;AACA,yBAAyB,8CAAM;AAC/B;AACA;AACA,iBAAiB;AACjB,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iEAAiE,QAAQ;AACzE;AACA;AACA;AACA,+FAA+F,QAAQ;AACvG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAwC,QAAQ;AAChD;AACA;AACA;AACA,uCAAuC,SAAS;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,gCAAgC,qBAAqB;AACrD;AACA;AACA,iCAAiC;AACjC,4BAA4B,kBAAkB;AAC9C;AACA;AACA;AACA;AACA,+BAA+B,iCAAiC;AAChE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;AC9QA,gcAAgc,gJAAgJ,+hK","file":"orange.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/editor.ts\");\n","export default __webpack_public_path__ + \"linkicon.png\";","optionsData = {\r\n\tdebugPanel: false,\r\n\tlogLevel: 'info',\t//debug, info, error\r\n\tlogLineNumbers: true,\r\n\tlogBalanceTimestep: false,\r\n\tdebuggerWhenAssertFailed: true,\r\n\trotateShapesLikeInPervologo: true,\r\n\ttextboxView: 'quill', //'textarea' or 'quill'\r\n\tfontWhitelist: ['Arial', 'Helvetica Neue','Times New Roman','Courier New','Verdana','Impact'],\r\n\tquillShowToolbar: true,\r\n\tdoubleDrawing: false,\r\n}","export default __webpack_public_path__ + \"soundicon.png\";","export default __webpack_public_path__ + \"soundicon_pressed.png\";","require(\"!!D:\\\\a\\\\1\\\\s\\\\wwwroot\\\\player\\\\node_modules\\\\script-loader\\\\addScript.js\")(require(\"!!D:\\\\a\\\\1\\\\s\\\\wwwroot\\\\player\\\\node_modules\\\\raw-loader\\\\index.js!D:\\\\a\\\\1\\\\s\\\\wwwroot\\\\player\\\\jswebplayer\\\\vendor\\\\debugout.js\"))","module.exports = \"/*\\r\\n\\r\\n debugout.js\\r\\n by @inorganik\\r\\n \\r\\n*/\\r\\n\\r\\n// save all the console.logs\\r\\nfunction debugout() {\\r\\n\\tvar self = this;\\r\\n\\r\\n\\t// OPTIONS\\r\\n\\tself.realTimeLoggingOn = true; // log in real time (forwards to console.log)\\r\\n\\tself.doubleLineNumber = true; // get caller lineNumber\\r\\n\\tself.lineNumberOnlyInFile = true;\\r\\n\\tself.useTimestamps = false; // insert a timestamp in front of each log\\r\\n\\tself.useLocalStorage = false; // store the output using window.localStorage() and continuously add to the same log each session\\r\\n\\tself.recordLogs = true; // set to false after you're done debugging to avoid the log eating up memory\\r\\n\\tself.autoTrim = true; // to avoid the log eating up potentially endless memory\\r\\n\\tself.maxLines = 2500; // if autoTrim is true, this many most recent lines are saved\\r\\n\\tself.tailNumLines = 100; // how many lines tail() will retrieve\\r\\n\\tself.logFilename = 'debugout.txt'; // filename of log downloaded with downloadLog()\\r\\n\\tself.maxDepth = 25; // max recursion depth for logged objects\\r\\n\\r\\n\\t// vars\\r\\n\\tself.depth = 0;\\r\\n\\tself.parentSizes = [0];\\r\\n\\tself.currentResult = '';\\r\\n\\tself.startTime = new Date();\\r\\n\\tself.output = '';\\r\\n\\r\\n\\tthis.version = function() { return '0.5.0' }\\r\\n\\r\\n\\t/*\\r\\n\\t\\tUSER METHODS\\r\\n\\t*/\\t\\r\\n\\tthis.getLog = function() {\\r\\n\\t\\tvar retrievalTime = new Date();\\r\\n\\t\\t// if recording is off, so dev knows why they don't have any logs\\r\\n\\t\\tif (!self.recordLogs) {\\r\\n\\t\\t\\tself.log('[debugout.js] log recording is off.');\\r\\n\\t\\t}\\r\\n\\t\\t// if using local storage, get values\\r\\n\\t\\tif (self.useLocalStorage) {\\r\\n\\t\\t\\tvar saved = window.localStorage.getItem('debugout.js');\\r\\n\\t\\t\\tif (saved) {\\r\\n\\t\\t\\t\\tsaved = JSON.parse(saved);\\r\\n\\t\\t\\t\\tself.startTime = new Date(saved.startTime);\\r\\n\\t\\t\\t\\tself.output = saved.log;\\r\\n\\t\\t\\t\\tretrievalTime = new Date(saved.lastLog);\\r\\n\\t\\t\\t}\\r\\n\\t\\t}\\r\\n\\t\\treturn self.output\\r\\n\\t\\t\\t+ '\\\\n---- Log retrieved: '+retrievalTime+' ----\\\\n'\\r\\n\\t\\t\\t+ self.formatSessionDuration(self.startTime, retrievalTime);\\r\\n\\t}\\r\\n\\t// accepts optional number or uses the default for number of lines\\r\\n\\tthis.tail = function(numLines) {\\r\\n\\t\\tvar numLines = numLines || self.tailLines;\\r\\n\\t\\treturn self.trimLog(self.getLog(), numLines);\\r\\n\\t}\\r\\n\\t// accepts a string to search for\\r\\n\\tthis.search = function(string) {\\r\\n\\t\\tvar lines = self.output.split('\\\\n');\\r\\n\\t\\tvar rgx = new RegExp(string);\\r\\n\\t\\tvar matched = [];\\r\\n\\t\\t// can't use a simple Array.prototype.filter() here\\r\\n\\t\\t// because we need to add the line number\\r\\n\\t\\tfor (var i = 0; i < lines.length; i++) {\\r\\n\\t\\t\\tvar addr = '['+i+'] ';\\r\\n\\t\\t\\tif (lines[i].match(rgx)) {\\r\\n\\t\\t\\t\\tmatched.push(addr + lines[i]);\\r\\n\\t\\t\\t}\\r\\n\\t\\t}\\r\\n\\t\\tvar result = matched.join('\\\\n');\\r\\n\\t\\tif (result.length == 0) result = 'Nothing found for \\\"'+string+'\\\".';\\r\\n\\t\\treturn result\\r\\n\\t}\\r\\n\\t// accepts the starting line and how many lines after the starting line you want\\r\\n\\tthis.getSlice = function(lineNumber, numLines) {\\r\\n\\t\\tvar lines = self.output.split('\\\\n');\\r\\n\\t\\tvar segment = lines.slice(lineNumber, lineNumber + numLines);\\r\\n\\t\\treturn segment.join('\\\\n');\\r\\n\\t}\\r\\n\\t// immediately downloads the log - for desktop browser use\\r\\n\\tthis.downloadLog = function() {\\r\\n\\t var file = \\\"data:text/plain;charset=utf-8,\\\";\\r\\n\\t var logFile = self.getLog();\\r\\n\\t var encoded = encodeURIComponent(logFile);\\r\\n\\t file += encoded;\\r\\n\\t var a = document.createElement('a');\\r\\n\\t a.href = file;\\r\\n\\t a.target = '_blank';\\r\\n\\t a.download = self.logFilename;\\r\\n\\t document.body.appendChild(a);\\r\\n\\t a.click();\\r\\n\\t a.remove();\\r\\n\\t}\\r\\n\\t// clears the log\\r\\n\\tthis.clear = function() {\\r\\n\\t\\tvar clearTime = new Date();\\r\\n\\t\\tself.output = '---- Log cleared: '+clearTime+' ----\\\\n';\\r\\n\\t\\tif (self.useLocalStorage) {\\r\\n\\t\\t\\t// local storage\\r\\n\\t\\t\\tvar saveObject = {\\r\\n\\t\\t\\t\\tstartTime: self.startTime,\\r\\n\\t\\t\\t\\tlog: self.output,\\r\\n\\t\\t\\t\\tlastLog: clearTime\\r\\n\\t\\t\\t}\\r\\n\\t\\t\\tsaveObject = JSON.stringify(saveObject);\\r\\n\\t\\t\\twindow.localStorage.setItem('debugout.js', saveObject);\\r\\n\\t\\t}\\r\\n\\t\\tif (self.realTimeLoggingOn) console.log('[debugout.js] clear()');\\r\\n\\t}\\r\\n\\t\\r\\n\\t//Wrapper for logWithLine\\r\\n\\tthis.log = function(...args){\\r\\n\\t\\tlet line;\\r\\n\\t\\tif (self.doubleLineNumber){\\r\\n\\t\\t\\tlet e = new Error(); //TODO: IE check\\r\\n\\t\\t\\tlet stack = e.stack.toString().split(/\\\\r\\\\n|\\\\n/);\\r\\n\\t\\t\\tline = ' [' + stack[2] + ']';\\r\\n\\t\\t}\\r\\n\\t\\tthis.logWithLine(line, ...args);\\r\\n\\t}\\r\\n\\t// records a log\\r\\n\\tthis.logWithLine = function(line, ...args) {\\r\\n\\t\\t// log in real time\\r\\n\\t\\tif (self.realTimeLoggingOn) {\\r\\n\\t\\t\\tif ( line && !self.lineNumberOnlyInFile){\\r\\n\\t\\t\\t\\tconsole.log(...args, line);\\r\\n\\t\\t\\t} else {\\r\\n\\t\\t\\t\\tconsole.log(...args);\\r\\n\\t\\t\\t}\\r\\n\\t\\t}\\r\\n\\t\\t// record log\\r\\n\\t\\tfor (obj of args){\\r\\n\\t\\t\\tself._recordObj(obj);\\r\\n\\t\\t}\\r\\n\\t\\tif (line && self.doubleLineNumber){\\r\\n\\t\\t\\tself._recordObj(line);\\r\\n\\t\\t}\\r\\n\\t}\\r\\n\\t\\r\\n\\t//run for each argument\\r\\n\\tthis._recordObj = function(obj){\\r\\n\\t\\tvar type = self.determineType(obj);\\r\\n\\t\\tif (type != null && self.recordLogs) {\\r\\n\\t\\t\\tvar addition = self.formatType(type, obj);\\r\\n\\t\\t\\t// timestamp, formatted for brevity\\r\\n\\t\\t\\tif (self.useTimestamps) {\\r\\n\\t\\t\\t\\tvar logTime = new Date();\\r\\n\\t\\t\\t\\tself.output += self.formatTimestamp(logTime);\\r\\n\\t\\t\\t}\\r\\n\\t\\t\\tself.output += addition+'\\\\n';\\r\\n\\t\\t\\tif (self.autoTrim) self.output = self.trimLog(self.output, self.maxLines);\\r\\n\\t\\t\\t// local storage\\r\\n\\t\\t\\tif (self.useLocalStorage) {\\r\\n\\t\\t\\t\\tvar last = new Date();\\r\\n\\t\\t\\t\\tvar saveObject = {\\r\\n\\t\\t\\t\\t\\tstartTime: self.startTime,\\r\\n\\t\\t\\t\\t\\tlog: self.output,\\r\\n\\t\\t\\t\\t\\tlastLog: last\\r\\n\\t\\t\\t\\t}\\r\\n\\t\\t\\t\\tsaveObject = JSON.stringify(saveObject);\\r\\n\\t\\t\\t\\twindow.localStorage.setItem('debugout.js', saveObject);\\r\\n\\t\\t\\t}\\r\\n\\t\\t}\\r\\n\\t\\tself.depth = 0;\\r\\n\\t\\tself.parentSizes = [0];\\r\\n\\t\\tself.currentResult = '';\\r\\n\\t}\\r\\n\\t/*\\r\\n\\t\\tMETHODS FOR CONSTRUCTING THE LOG\\r\\n\\t*/\\r\\n\\r\\n\\t// like typeof but classifies objects of type 'object'\\r\\n\\t// kept separate from formatType() so you can use at your convenience!\\r\\n\\tthis.determineType = function(object) {\\r\\n\\t\\tif (object != null) {\\r\\n\\t\\t\\tvar typeResult;\\r\\n\\t\\t\\tvar type = typeof object;\\r\\n\\t\\t\\tif (type == 'object') {\\r\\n\\t\\t\\t\\tvar len = object.length;\\r\\n\\t\\t\\t\\tif (len == null) {\\r\\n\\t\\t\\t\\t\\tif (typeof object.getTime == 'function') {\\r\\n\\t\\t\\t\\t\\t\\ttypeResult = 'Date';\\r\\n\\t\\t\\t\\t\\t}\\r\\n\\t\\t\\t\\t\\telse if (typeof object.test == 'function') {\\r\\n\\t\\t\\t\\t\\t\\ttypeResult = 'RegExp';\\r\\n\\t\\t\\t\\t\\t}\\r\\n\\t\\t\\t\\t\\telse {\\r\\n\\t\\t\\t\\t\\t\\ttypeResult = 'Object';\\r\\n\\t\\t\\t\\t\\t}\\r\\n\\t\\t\\t\\t} else {\\r\\n\\t\\t\\t\\t\\ttypeResult = 'Array';\\r\\n\\t\\t\\t\\t}\\r\\n\\t\\t\\t} else {\\r\\n\\t\\t\\t\\ttypeResult = type;\\r\\n\\t\\t\\t}\\r\\n\\t\\t\\treturn typeResult;\\r\\n\\t\\t} else {\\r\\n\\t\\t\\treturn null;\\r\\n\\t\\t}\\r\\n\\t}\\r\\n\\t// format type accordingly, recursively if necessary\\r\\n\\tthis.formatType = function(type, obj) {\\r\\n\\t\\tif (self.maxDepth && self.depth >= self.maxDepth) {\\r\\n\\t\\t\\treturn '... (max-depth reached)';\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tswitch(type) {\\r\\n\\t\\t\\tcase 'Object' :\\r\\n\\t\\t\\t\\tself.currentResult += '{\\\\n';\\r\\n\\t\\t\\t\\tself.depth++;\\r\\n\\t\\t\\t\\tself.parentSizes.push(self.objectSize(obj));\\r\\n\\t\\t\\t\\tvar i = 0;\\r\\n\\t\\t\\t\\tfor (var prop in obj) {\\r\\n\\t\\t\\t\\t\\tself.currentResult += self.indentsForDepth(self.depth);\\r\\n\\t\\t\\t\\t\\tself.currentResult += prop + ': ';\\r\\n\\t\\t\\t\\t\\tvar subtype = self.determineType(obj[prop]);\\r\\n\\t\\t\\t\\t\\tvar subresult = self.formatType(subtype, obj[prop]);\\r\\n\\t\\t\\t\\t\\tif (subresult) {\\r\\n\\t\\t\\t\\t\\t\\tself.currentResult += subresult;\\r\\n\\t\\t\\t\\t\\t\\tif (i != self.parentSizes[self.depth]-1) self.currentResult += ',';\\r\\n\\t\\t\\t\\t\\t\\tself.currentResult += '\\\\n';\\r\\n\\t\\t\\t\\t\\t} else {\\r\\n\\t\\t\\t\\t\\t\\tif (i != self.parentSizes[self.depth]-1) self.currentResult += ',';\\r\\n\\t\\t\\t\\t\\t\\tself.currentResult += '\\\\n';\\r\\n\\t\\t\\t\\t\\t}\\r\\n\\t\\t\\t\\t\\ti++;\\r\\n\\t\\t\\t\\t}\\r\\n\\t\\t\\t\\tself.depth--;\\r\\n\\t\\t\\t\\tself.parentSizes.pop();\\r\\n\\t\\t\\t\\tself.currentResult += self.indentsForDepth(self.depth);\\r\\n\\t\\t\\t\\tself.currentResult += '}';\\r\\n\\t\\t\\t\\tif (self.depth == 0) return self.currentResult;\\r\\n\\t\\t\\t\\tbreak;\\r\\n\\t\\t\\tcase 'Array' :\\r\\n\\t\\t\\t\\tself.currentResult += '[';\\r\\n\\t\\t\\t\\tself.depth++;\\r\\n\\t\\t\\t\\tself.parentSizes.push(obj.length);\\r\\n\\t\\t\\t\\tfor (var i = 0; i < obj.length; i++) {\\r\\n\\t\\t\\t\\t\\tvar subtype = self.determineType(obj[i]);\\r\\n\\t\\t\\t\\t\\tif (subtype == 'Object' || subtype == 'Array') self.currentResult += '\\\\n' + self.indentsForDepth(self.depth);\\r\\n\\t\\t\\t\\t\\tvar subresult = self.formatType(subtype, obj[i]);\\r\\n\\t\\t\\t\\t\\tif (subresult) {\\r\\n\\t\\t\\t\\t\\t\\tself.currentResult += subresult;\\r\\n\\t\\t\\t\\t\\t\\tif (i != self.parentSizes[self.depth]-1) self.currentResult += ', ';\\r\\n\\t\\t\\t\\t\\t\\tif (subtype == 'Array') self.currentResult += '\\\\n';\\r\\n\\t\\t\\t\\t\\t} else {\\r\\n\\t\\t\\t\\t\\t\\tif (i != self.parentSizes[self.depth]-1) self.currentResult += ', ';\\r\\n\\t\\t\\t\\t\\t\\tif (subtype != 'Object') self.currentResult += '\\\\n';\\r\\n\\t\\t\\t\\t\\t\\telse if (i == self.parentSizes[self.depth]-1) self.currentResult += '\\\\n';\\r\\n\\t\\t\\t\\t\\t}\\r\\n\\t\\t\\t\\t}\\r\\n\\t\\t\\t\\tself.depth--;\\r\\n\\t\\t\\t\\tself.parentSizes.pop();\\r\\n\\t\\t\\t\\tself.currentResult += ']';\\r\\n\\t\\t\\t\\tif (self.depth == 0) return self.currentResult;\\r\\n\\t\\t\\t\\tbreak;\\r\\n\\t\\t\\tcase 'function' :\\r\\n\\t\\t\\t\\tobj += '';\\r\\n\\t\\t\\t\\tvar lines = obj.split('\\\\n');\\r\\n\\t\\t\\t\\tfor (var i = 0; i < lines.length; i++) {\\r\\n\\t\\t\\t\\t\\tif (lines[i].match(/\\\\}/)) self.depth--;\\r\\n\\t\\t\\t\\t\\tself.currentResult += self.indentsForDepth(self.depth);\\r\\n\\t\\t\\t\\t\\tif (lines[i].match(/\\\\{/)) self.depth++;\\r\\n\\t\\t\\t\\t\\tself.currentResult += lines[i] + '\\\\n';\\r\\n\\t\\t\\t\\t}\\r\\n\\t\\t\\t\\treturn self.currentResult;\\r\\n\\t\\t\\t\\tbreak;\\r\\n\\t\\t\\tcase 'RegExp' :\\r\\n\\t\\t\\t\\treturn '/'+obj.source+'/';\\r\\n\\t\\t\\t\\tbreak;\\r\\n\\t\\t\\tcase 'Date' :\\r\\n\\t\\t\\tcase 'string' : \\r\\n\\t\\t\\t\\tif (self.depth > 0 || obj.length == 0) {\\r\\n\\t\\t\\t\\t\\treturn '\\\"'+obj+'\\\"';\\r\\n\\t\\t\\t\\t} else {\\r\\n\\t\\t\\t\\t\\treturn obj;\\r\\n\\t\\t\\t\\t}\\r\\n\\t\\t\\tcase 'boolean' :\\r\\n\\t\\t\\t\\tif (obj) return 'true';\\r\\n\\t\\t\\t\\telse return 'false';\\r\\n\\t\\t\\tcase 'number' :\\r\\n\\t\\t\\t\\treturn obj+'';\\r\\n\\t\\t\\t\\tbreak;\\r\\n\\t\\t}\\r\\n\\t}\\r\\n\\tthis.indentsForDepth = function(depth) {\\r\\n\\t\\tvar str = '';\\r\\n\\t\\tfor (var i = 0; i < depth; i++) {\\r\\n\\t\\t\\tstr += '\\\\t';\\r\\n\\t\\t}\\r\\n\\t\\treturn str;\\r\\n\\t}\\r\\n\\tthis.trimLog = function(log, maxLines) {\\r\\n\\t\\tvar lines = log.split('\\\\n');\\r\\n\\t\\tif (lines.length > maxLines) {\\r\\n\\t\\t\\tlines = lines.slice(lines.length - maxLines);\\r\\n\\t\\t}\\r\\n\\t\\treturn lines.join('\\\\n');\\r\\n\\t}\\r\\n\\tthis.lines = function() {\\r\\n\\t\\treturn self.output.split('\\\\n').length;\\r\\n\\t}\\r\\n\\t// calculate testing time\\r\\n\\tthis.formatSessionDuration = function(startTime, endTime) {\\r\\n\\t\\tvar msec = endTime - startTime;\\r\\n\\t\\tvar hh = Math.floor(msec / 1000 / 60 / 60);\\r\\n\\t\\tvar hrs = ('0' + hh).slice(-2);\\r\\n\\t\\tmsec -= hh * 1000 * 60 * 60;\\r\\n\\t\\tvar mm = Math.floor(msec / 1000 / 60);\\r\\n\\t\\tvar mins = ('0' + mm).slice(-2);\\r\\n\\t\\tmsec -= mm * 1000 * 60;\\r\\n\\t\\tvar ss = Math.floor(msec / 1000);\\r\\n\\t\\tvar secs = ('0' + ss).slice(-2);\\r\\n\\t\\tmsec -= ss * 1000;\\r\\n\\t\\treturn '---- Session duration: '+hrs+':'+mins+':'+secs+' ----'\\r\\n\\t}\\r\\n\\tthis.formatTimestamp = function(timestamp) {\\r\\n\\t\\tvar year = timestamp.getFullYear();\\r\\n\\t\\tvar date = timestamp.getDate();\\r\\n\\t\\tvar month = ('0' + (timestamp.getMonth() +1)).slice(-2);\\r\\n\\t\\tvar hrs = Number(timestamp.getHours()); \\r\\n\\t\\tvar mins = ('0' + timestamp.getMinutes()).slice(-2);\\r\\n\\t\\tvar secs = ('0' + timestamp.getSeconds()).slice(-2);\\r\\n\\t\\treturn '['+ year + '-' + month + '-' + date + ' ' + hrs + ':' + mins + ':'+secs + ']: ';\\r\\n\\t}\\r\\n\\tthis.objectSize = function(obj) {\\r\\n\\t var size = 0, key;\\r\\n\\t for (key in obj) {\\r\\n\\t if (obj.hasOwnProperty(key)) size++;\\r\\n\\t }\\r\\n\\t return size;\\r\\n\\t}\\r\\n\\r\\n\\t/*\\r\\n\\t\\tSTART/RESUME LOG\\r\\n\\t*/\\r\\n\\tif (self.useLocalStorage) {\\r\\n\\t\\tvar saved = window.localStorage.getItem('debugout.js');\\r\\n\\t\\tif (saved) {\\r\\n\\t\\t\\tsaved = JSON.parse(saved);\\r\\n\\t\\t\\tself.output = saved.log;\\r\\n\\t\\t\\tvar start = new Date(saved.startTime);\\r\\n\\t\\t\\tvar end = new Date(saved.lastLog);\\r\\n\\t\\t\\tself.output += '\\\\n---- Session end: '+saved.lastLog+' ----\\\\n';\\r\\n\\t\\t\\tself.output += self.formatSessionDuration(start, end);\\r\\n\\t\\t\\tself.output += '\\\\n\\\\n';\\r\\n\\t\\t}\\r\\n\\t} \\r\\n\\tself.output += '---- Session started: '+self.startTime+' ----\\\\n\\\\n';\\r\\n}\"","/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\nmodule.exports = function(src) {\n\tfunction log(error) {\n\t\t(typeof console !== \"undefined\")\n\t\t&& (console.error || console.log)(\"[Script Loader]\", error);\n\t}\n\n\t// Check for IE =< 8\n\tfunction isIE() {\n\t\treturn typeof attachEvent !== \"undefined\" && typeof addEventListener === \"undefined\";\n\t}\n\n\ttry {\n\t\tif (typeof execScript !== \"undefined\" && isIE()) {\n\t\t\texecScript(src);\n\t\t} else if (typeof eval !== \"undefined\") {\n\t\t\teval.call(null, src);\n\t\t} else {\n\t\t\tlog(\"EvalError: No eval function available\");\n\t\t}\n\t} catch (error) {\n\t\tlog(error);\n\t}\n}\n","let wurl = window.URL || window.webkitURL;\r\nconst doublepadding = 20; // TODO: sync with @padding in form\r\nconst htmlElem = jQuery('html');\r\nconst addRemoveLink = jQuery('.addRemoveLink');\r\nconst mapOneDrive = { 'images': 'folder,photo', 'audio': 'folder,.wav', '.js': 'folder,.js', '.mwx,.mj3': 'folder,.mwx,.mj3' };\r\nconst mapAccept = { 'images': 'image/*', 'audio': 'audio/*', '.js': 'text/*,.js', '.mwx,.mj3': '*' };\r\nconst mapGoogle = { 'images': 'image/png,image/jpeg,image/jpg,image/gif', 'audio': 'audio/x-wav', '.js': 'text/plain,text/javascript,application/x-javascript', '.mwx,.mj3': 'application/octet-stream' };\r\n// The Client ID obtained from the Google API Console. Replace with your own Client ID.\r\nconst developerKey = 'AIzaSyD3JYp3wKAqKu12lMzJiEU4sRAaWC5be00';\r\nconst clientId = '414889912550-9fr0fth7dpukcefs2biceo4lreima34g.apps.googleusercontent.com';\r\nconst scope = 'https://www.googleapis.com/auth/drive.file';\r\nconst appId = '414889912550';\r\nexport class Dialog {\r\n constructor(app, msg) {\r\n this.msg = msg;\r\n this.app = app;\r\n if (!app)\r\n return;\r\n this.userproc = app.getProject().getGlobals().userproc;\r\n $('#textreadonly').bind('change', function (e) {\r\n if (this.checked) {\r\n $('#textshowtoolbar').attr('disabled', 'true');\r\n }\r\n else {\r\n $('#textshowtoolbar').removeAttr('disabled');\r\n }\r\n });\r\n }\r\n static localisableContent(id) {\r\n let elem = document.getElementById(id);\r\n if (elem) {\r\n let content = window.getComputedStyle(elem).content;\r\n // only some content is surrounded with quotes\r\n if (content[0] == '\"')\r\n content = content.slice(1, -1);\r\n return content;\r\n }\r\n return id;\r\n }\r\n static setLocale(lang) {\r\n this.locale = lang;\r\n }\r\n static setProjectTitle(name, page) {\r\n let prj = jQuery('div.prjname');\r\n if (name) {\r\n jQuery('input.prjname').val(name);\r\n jQuery('span:nth-child(1)', prj).text(name);\r\n }\r\n if (page)\r\n jQuery('span:nth-child(2)', prj).text(page);\r\n prj.attr('title', prj.first().text());\r\n document.title = prj.first().text() + ' - ' + jQuery('meta[name=\"app-title\"]').attr('content');\r\n }\r\n static showNewProject() {\r\n var overlay = jQuery('#newproject');\r\n var d = jQuery('form', overlay);\r\n var dismiss = jQuery('[data-dismiss=modal]', d);\r\n dismiss.click(close);\r\n jQuery('#standard, #large, #small').click(function () {\r\n jQuery('#projectwidth, #projectheight').attr('readonly', 'true');\r\n });\r\n jQuery('#custom').click(function () {\r\n jQuery('#projectwidth, #projectheight').removeAttr('readonly');\r\n jQuery('#projectwidth').focus();\r\n });\r\n jQuery('#projectwidth, #projectheight').keyup(function () {\r\n Dialog.validSize(this.id);\r\n });\r\n d.submit(function () {\r\n let val = jQuery(':checked', d).val();\r\n if (!val) {\r\n let result = Dialog.validSize('projectwidth');\r\n result = Dialog.validSize('projectheight') && result;\r\n if (result)\r\n val = `[${jQuery('#projectwidth').val()},${jQuery('#projectheight').val()}]`;\r\n else\r\n return false;\r\n }\r\n let href = '/projects/edit?projectsize=' + val;\r\n if (window['isDirty']()) {\r\n close();\r\n Dialog.prompt([\r\n [Dialog.localisableContent('locNo'), function () { }],\r\n [Dialog.localisableContent('locYes'), function () { window['needSave'](false); window.location.replace(href); }],\r\n ], Dialog.localisableContent('locUnsavedChanges'), Dialog.localisableContent('locSureToLeave'));\r\n }\r\n else\r\n window.location.replace(href);\r\n return false;\r\n });\r\n function close() {\r\n overlay.removeClass('show').fadeOut();\r\n d.off('submit');\r\n dismiss.off('click');\r\n jQuery('#standard, #large, #small, #custom').off('click');\r\n jQuery('#projectwidth, #projectheight').off('keyup');\r\n }\r\n overlay.addClass('show').show();\r\n }\r\n static validSize(id, min = 40, max = 2000) {\r\n id = '#' + id;\r\n let value = jQuery(id).val();\r\n let n = parseInt(value);\r\n let result = !isNaN(n) && min <= n && n <= max && isFinite(value) && n == parseFloat(value);\r\n if (result)\r\n jQuery(id).removeClass('is-invalid');\r\n else\r\n jQuery(id).addClass('is-invalid');\r\n return result;\r\n }\r\n populateProcedures(elem, argsNum) {\r\n var userproc = this.userproc;\r\n var localise = Dialog.localisableContent;\r\n elem.each(function () {\r\n while (this.options.length)\r\n this.remove(0);\r\n this.add(new Option('-', ''));\r\n userproc.forEach((v, k) => {\r\n if (v.procProperties && v.procProperties.argsnum == argsNum)\r\n this.add(new Option(k));\r\n });\r\n // if somebody calls a userproc with a stringified JSON, we're in trouble\r\n let x = new Option(localise('locNewHandler'), JSON.stringify({ new: true, argsNum: argsNum }));\r\n this.add(x);\r\n });\r\n }\r\n setProcedure(elem, propValue) {\r\n var name = propValue ? propValue._name.toLowerCase() : '';\r\n if (name && !this.userproc.has(name))\r\n elem.each(function () {\r\n this.add(new Option(name), 0);\r\n });\r\n return name;\r\n }\r\n show(e, data) {\r\n // the following line is editor.donePopover\r\n jQuery(`[data-hint-order=${window['hintCounter']}]`)['popover']('dispose');\r\n let pause = this.app.setDragPause;\r\n pause(true);\r\n var dt = data.type;\r\n if (dt == 'midi')\r\n dt = 'audio';\r\n var overlay = jQuery('#' + dt + 'dialog');\r\n jQuery('#pagename').attr('readonly', data.isWallpaper);\r\n var d = jQuery('form', overlay);\r\n var dismiss = jQuery('[data-dismiss=modal]', d);\r\n var delButton = jQuery('.delete', d);\r\n delButton.click(function () {\r\n window['needSave'](true);\r\n close();\r\n data.remove();\r\n });\r\n jQuery('.is-invalid', d).removeClass('is-invalid');\r\n overlay.addClass('show').show();\r\n // unsubscribe from previous Dialog.show in case new dialog is shown without d.submit of previous\r\n var left = e.clientX;\r\n var top = e.clientY;\r\n if (d.width() + doublepadding + left > window.innerWidth) {\r\n left -= d.width() + doublepadding;\r\n left = Math.max(10, left);\r\n }\r\n if (d.height() + doublepadding + top > window.innerHeight) {\r\n top -= d.height() + doublepadding;\r\n top = Math.max(10, top);\r\n }\r\n d.css({\r\n left: left,\r\n top: top\r\n });\r\n this.populateProcedures(jQuery('.procedures0', d), 0);\r\n this.populateProcedures(jQuery('.procedures1', d), 1);\r\n this.populateProcedures(jQuery('.procedures2', d), 2);\r\n if (dt == 'shape') {\r\n // no need to limit to 2000 because it's done somewhere else\r\n const max = {\r\n w: Math.max(data.width, data.projectSize.w),\r\n h: Math.max(data.height, data.projectSize.h),\r\n };\r\n const widthElem = jQuery('#shapewidth', d);\r\n widthElem.next().text(`1..${max.w}`);\r\n const heightElem = jQuery('#shapeheight', d);\r\n heightElem.next().text(`1..${max.h}`);\r\n const scaleElem = jQuery('#shapescale', d);\r\n const scaleMarker = jQuery('.marker-col', d);\r\n if (data.scale)\r\n scaleMarker.show();\r\n else\r\n scaleMarker.hide();\r\n jQuery('#shapewidth, #shapeheight').on('input', function (e) {\r\n const id = e.target.id;\r\n // don't stop if the edited field is invalid - we want to update the second field\r\n Dialog.validSize(id, 1, id == 'shapewidth' ? max.w : max.h);\r\n if (scaleElem.is(':checked')) {\r\n let v = parseInt(jQuery(e.target).val());\r\n if (id == 'shapewidth') {\r\n const newH = Math.trunc(v / data.ratio);\r\n heightElem.val(isNaN(newH) ? '' : newH);\r\n Dialog.validSize('shapeheight', 1, max.h);\r\n }\r\n else {\r\n const newW = Math.trunc(v * data.ratio);\r\n widthElem.val(isNaN(newW) ? '' : newW);\r\n Dialog.validSize('shapewidth', 1, max.w);\r\n }\r\n }\r\n });\r\n scaleElem.on('change', function () {\r\n if (scaleElem.is(':checked'))\r\n scaleMarker.show();\r\n else\r\n scaleMarker.hide();\r\n });\r\n }\r\n var editable = {};\r\n for (let prop in data) {\r\n var jqElem = jQuery('#' + dt + prop, d);\r\n var elem = jqElem[0];\r\n if (!elem)\r\n continue;\r\n editable[prop] = data[prop];\r\n if (elem['type'] == 'checkbox')\r\n elem['checked'] = data[prop];\r\n else if (-1 < ['onClickCor', 'onMessageCor', 'onTouchingCor', 'onColorCor'].indexOf(prop)) {\r\n elem['value'] = editable[prop] = this.setProcedure(jqElem, data[prop]);\r\n }\r\n else\r\n elem['value'] = data[prop];\r\n }\r\n function close() {\r\n overlay.removeClass('show').fadeOut();\r\n d.off('submit');\r\n dismiss.off('click');\r\n delButton.off('click');\r\n jQuery('#shapewidth, #shapeheight').off('input');\r\n jQuery('#shapedegrees').off('input');\r\n jQuery('#shapescale').off('change');\r\n pause(false);\r\n }\r\n d.submit(function () {\r\n jQuery('.is-invalid', d).removeClass('is-invalid');\r\n let dirty = false;\r\n for (var prop in editable) {\r\n var elem = jQuery('#' + dt + prop, d)[0];\r\n if (elem['type'] == 'checkbox')\r\n editable[prop] = elem['checked'];\r\n else\r\n editable[prop] = elem['value'];\r\n dirty = dirty || (data[prop] !== editable[prop]);\r\n }\r\n let err = data.checkApply(editable);\r\n if (err) {\r\n jQuery(err.map((x) => '#' + dt + x).join(','), d).addClass('is-invalid');\r\n return false;\r\n }\r\n data.apply(editable);\r\n close();\r\n if (dirty)\r\n window['needSave']();\r\n return false;\r\n });\r\n dismiss.click(close);\r\n jQuery('input[type=text]:not(.form-control-plaintext)', d).first().focus();\r\n return false;\r\n }\r\n showFilePicker(title, fileType, callback, createLabel, stay) {\r\n const url = jQuery('#url');\r\n var d = jQuery('#pickfile');\r\n Dialog.setSaveAlert(this.msg);\r\n this.msg = undefined;\r\n Dialog.setSaveProgress(true, 0);\r\n jQuery('#modalTitle').text(Dialog.localisableContent(title));\r\n jQuery(\"#create\").html(Dialog.localisableContent(createLabel || 'locCreateButton'));\r\n d.removeClass(\"progressonly\");\r\n var dismiss = jQuery('#pickfile [data-dismiss=modal]');\r\n url.val('');\r\n url.prop('placeholder', 'URL');\r\n jQuery(\"label[for=url]\").text('URL');\r\n let file = jQuery('#file');\r\n file.val('');\r\n file.prop('accept', mapAccept[fileType]);\r\n if (fileType === 'images') {\r\n file.change(function () {\r\n if (!this.files.length)\r\n return;\r\n // https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications\r\n url.val(wurl.createObjectURL(this.files[0]));\r\n });\r\n }\r\n else {\r\n file.change(function () {\r\n if (this.files.length)\r\n setUrl(this.files[0].name, undefined, this.files[0]);\r\n });\r\n }\r\n Dialog.disableButtons(false);\r\n function close() {\r\n dismiss.off('click');\r\n d.removeClass('show').fadeOut();\r\n Dialog.cancelCloudClicks(d);\r\n jQuery('#create').off('click');\r\n createButton.off('click');\r\n file.off('change');\r\n Dialog.setSaveProgress(true, 0);\r\n Dialog.setSaveAlert('');\r\n }\r\n function setUrl(name, value, file) {\r\n formData = undefined;\r\n if (file) {\r\n value = wurl.createObjectURL(file);\r\n formData = new FormData();\r\n formData.append('file', file, name);\r\n }\r\n url.val(value);\r\n updatedFileName = name;\r\n }\r\n dismiss.click(close);\r\n var createButton = jQuery('#create');\r\n var updatedFileName;\r\n this.setupCloudClicks(d, fileType, setUrl);\r\n let formData;\r\n createButton.click(function () {\r\n let v = url.val().trim();\r\n if (v == '') {\r\n url.focus();\r\n return;\r\n }\r\n callback(v, updatedFileName, formData, close);\r\n if (!stay)\r\n close();\r\n });\r\n d.addClass('show').fadeIn();\r\n return this;\r\n }\r\n setupCloudClicks(parent, fileType, success) {\r\n jQuery('.dropboxchooser', parent).click(function () {\r\n Dropbox.choose({\r\n // Required. Called when a user selects an item in the Chooser.\r\n success: function (files) {\r\n success(files[0].name, files[0].link);\r\n },\r\n // Optional. Called when the user closes the dialog without selecting a file\r\n // and does not include any parameters.\r\n cancel: function () {\r\n },\r\n // Optional. \"preview\" (default) is a preview link to the document for sharing,\r\n // \"direct\" is an expiring link to download the contents of the file. For more\r\n // information about link types, see Link types below.\r\n linkType: \"direct\",\r\n // Optional. This is a list of file extensions. If specified, the user will\r\n // only be able to select files with these extensions. You may also specify\r\n // file types, such as \"video\" or \"images\" in the list. For more information,\r\n // see File types below. By default, all extensions are allowed.\r\n extensions: [fileType],\r\n // Optional. A value of false (default) limits selection to files,\r\n // while true allows the user to select both folders and files.\r\n // You cannot specify `linkType: \"direct\"` when using `folderselect: true`.\r\n folderselect: false,\r\n });\r\n });\r\n jQuery('.onedrivechooser', parent).click(function () {\r\n OneDrive.open({\r\n clientId: \"64b509e0-f2f4-426a-90f1-388b587086b7\",\r\n action: \"download\",\r\n multiSelect: false,\r\n advanced: {\r\n filter: mapOneDrive[fileType],\r\n redirectUri: \"https://lynxcoding.club/onedrive.html\",\r\n },\r\n success: function (files) {\r\n success(files.value[0].name, files.value[0][\"@microsoft.graph.downloadUrl\"]);\r\n },\r\n cancel: function () { },\r\n error: function (e) { }\r\n });\r\n });\r\n jQuery('.googledrive', parent).click(() => {\r\n this.openGooglePicker(mapGoogle[fileType], download);\r\n });\r\n function download(doc) {\r\n var xhr = new XMLHttpRequest();\r\n var url = \"https://www.googleapis.com/drive/v3/files/\" + doc.id + \"?alt=media\";\r\n xhr.open('GET', url);\r\n xhr.setRequestHeader('Authorization', 'Bearer ' + Dialog.googleToken);\r\n xhr.responseType = \"blob\";\r\n xhr.addEventListener('load', function (e) {\r\n success(doc.name, undefined, this.response);\r\n });\r\n xhr.send();\r\n }\r\n }\r\n static cancelCloudClicks(parent) {\r\n jQuery('.dropboxchooser, .onedrivechooser, googledrive', parent).off('click');\r\n }\r\n showFileSaver(title) {\r\n Dialog.setSaveProgress(true, 0, false);\r\n Dialog.setError('');\r\n jQuery('#modalTitle').text(Dialog.localisableContent(title));\r\n var d = jQuery('#pickfile');\r\n var dismiss = jQuery('#pickfile [data-dismiss=modal]');\r\n d.addClass(\"save progressonly\");\r\n Dialog.disableButtons(true);\r\n dismiss.click(Dialog.closeFileSaver);\r\n d.addClass('show').fadeIn();\r\n return this;\r\n }\r\n static closeFileSaver(e) {\r\n if (e && e.currentTarget.className.indexOf('disabled') != -1)\r\n return;\r\n Dialog.resetProgress('#pickfile');\r\n }\r\n static resetProgress(id) {\r\n jQuery(id).removeClass('show').fadeOut('', function () {\r\n Dialog.disableButtons(false);\r\n Dialog.setSaveProgress(true, 0, false);\r\n Dialog.setError('');\r\n });\r\n jQuery(id + ' [data-dismiss=modal]').off('click');\r\n }\r\n static setError(msg) {\r\n let a = jQuery('.alert', '#pickfile').html(Dialog.localisableContent(msg));\r\n if (msg)\r\n a.show();\r\n else\r\n a.hide();\r\n }\r\n showFileSharer() {\r\n const BACKUP = 'backup';\r\n var d = jQuery('#shareproject');\r\n var dismiss = jQuery('[data-dismiss=modal]', d);\r\n Dialog.setSaveProgress(true, 0);\r\n if (window['projectData'].id == \"0\") {\r\n jQuery('.needs-save', d).show();\r\n jQuery('.nav-tabs, .tab-content', d).hide();\r\n }\r\n else {\r\n jQuery('.needs-save', d).hide();\r\n jQuery('.nav-tabs, .tab-content', d).show();\r\n }\r\n jQuery('#profile-tab, #profile').removeClass('active');\r\n jQuery('#home-tab, #home').addClass('active');\r\n jQuery('#sharePicture').val('');\r\n let shareDesc = jQuery('#description');\r\n let data = shareDesc.val();\r\n shareDesc.data(BACKUP, data).val(data);\r\n let shareName = jQuery('#name');\r\n data = jQuery('div.prjname span:nth-child(1)').first().text();\r\n shareName.data(BACKUP, data).val(data);\r\n jQuery('#name, #description').blur(function (e) {\r\n if (this.value === jQuery(this).data(BACKUP))\r\n return;\r\n sendMeta(this.id, this.value).then(r => {\r\n if (r) {\r\n jQuery(this).data(BACKUP, this.value);\r\n Dialog.setProjectTitle(shareName.data(BACKUP));\r\n jQuery('.prjdesc').html(shareDesc.data(BACKUP));\r\n }\r\n else\r\n jQuery(this).focus();\r\n });\r\n });\r\n jQuery('#private').change(function () {\r\n sendMeta(this.id, this.checked).then(r => {\r\n if (this.checked)\r\n jQuery('.private').show();\r\n else\r\n jQuery('.private').hide();\r\n });\r\n });\r\n jQuery('input[type=\"file\"]', d).change(function () {\r\n if (this.files.length)\r\n setUrl(this.files[0].name, undefined, this.files[0]);\r\n this.value = '';\r\n });\r\n jQuery('#sharePreview')[0].onpaste = function paste(e) {\r\n let items = e.clipboardData.items;\r\n if (items.length &&\r\n items[0].kind == 'file' &&\r\n items[0].type.indexOf('image/') !== -1) {\r\n let blob = items[0].getAsFile();\r\n setUrl('paste', undefined, blob);\r\n }\r\n };\r\n addRemoveLink.click(function () {\r\n if (this.disabled)\r\n return;\r\n let remove = this.className.indexOf('off') > -1;\r\n sendMeta('share_token', remove ? 'remove' : 'add');\r\n });\r\n Dialog.setShareLinks();\r\n function close() {\r\n Dialog.resetProgress('#shareproject');\r\n htmlElem.removeClass('wait');\r\n Dialog.cancelCloudClicks(d);\r\n dismiss.off('click');\r\n addRemoveLink.off('click');\r\n jQuery('input[type=\"file\"], #private', d).off('change');\r\n jQuery('#twitter, #facebook, #googleplus, #email, #embedCopy').off('click');\r\n jQuery('#name, #description').off('blur');\r\n }\r\n function sendMeta(name, value) {\r\n let extra = { partial: true };\r\n extra[name] = value;\r\n Dialog.setSaveProgress(true, 100, true);\r\n return window['sendToServer'](window['projectData'].root + '/meta', '', extra).then((xhr) => {\r\n let success = xhr.status == 200;\r\n Dialog.setSaveProgress(success, 100);\r\n if (success) {\r\n let data = JSON.parse(xhr.response);\r\n Dialog.setShareLinks(data.share);\r\n }\r\n return success;\r\n });\r\n }\r\n function setUrl(name, value, file) {\r\n function statusReport(xhr) {\r\n let success = xhr.status == 200;\r\n Dialog.setSaveProgress(success, success ? 100 : undefined);\r\n if (success) {\r\n try {\r\n let preview = JSON.parse(xhr.response).preview;\r\n jQuery('#sharePreview')[0].style.backgroundImage = `url(${[preview]})`;\r\n jQuery('.prjpreview').attr('src', preview);\r\n }\r\n catch (e) {\r\n Dialog.setSaveProgress(false);\r\n }\r\n }\r\n Dialog.disableButtons(false);\r\n }\r\n function progressReport(e) {\r\n let progress = Math.min(100, e.loaded / e.total * 100 + 1);\r\n if (95 < progress)\r\n progress = 100;\r\n Dialog.setSaveProgress(true, progress, 100 == progress);\r\n }\r\n Dialog.disableButtons(true);\r\n let formData = undefined;\r\n if (file) {\r\n value = wurl.createObjectURL(file);\r\n formData = new FormData();\r\n formData.append('image_file', file, name);\r\n formData.append('partial', true);\r\n }\r\n else\r\n formData = { image_url: value, partial: true };\r\n jQuery('#sharePicture').val(value);\r\n window['sendToServer'](window['projectData'].root + '/meta', '', formData, progressReport).then(statusReport);\r\n }\r\n dismiss.click(close);\r\n jQuery('#googleplus, #embedCopy').click(function () {\r\n jQuery(this.dataset.target).focus().select();\r\n document.execCommand('copy');\r\n window.showToast(Dialog.localisableContent('locLinkCopied'));\r\n return false;\r\n });\r\n this.setupCloudClicks(d, 'images', setUrl);\r\n d.addClass('show').fadeIn();\r\n return this;\r\n }\r\n static setShareLinks(url) {\r\n let plainUrl = jQuery('#shareUrl');\r\n if (url !== undefined)\r\n plainUrl.val(url);\r\n url = plainUrl.val();\r\n if (!url) {\r\n jQuery('#shareCode').val('');\r\n jQuery('.sharing.on').hide();\r\n jQuery('.sharing.off').show();\r\n jQuery('#shareproject .buttons .btn').addClass('disabled');\r\n return;\r\n }\r\n jQuery('#shareproject .buttons .btn').removeClass('disabled');\r\n let sharedUrl = encodeURIComponent(url);\r\n jQuery('#facebook').attr('href', 'https://www.facebook.com/sharer/sharer.php?u=' + sharedUrl);\r\n let title = jQuery('#name').val();\r\n jQuery('#twitter').attr('href', 'https://twitter.com/home?status=' + encodeURIComponent(title + ' ' + url));\r\n jQuery('#email').attr('href', 'mailto:?body=' + sharedUrl + '&subject=' + encodeURIComponent(title));\r\n jQuery('#googleplus, #embedCopy').attr('href', '#');\r\n let projectSize = window['projectData'].projectsize;\r\n jQuery('#shareCode').val(``);\r\n jQuery('.sharing.off').hide();\r\n jQuery('.sharing.on').show();\r\n }\r\n static prompt(callbacks, title, prompt, requireVal = false, transparent = false) {\r\n var overlay = jQuery('#prompt');\r\n if (transparent)\r\n overlay.addClass('transparent');\r\n else\r\n overlay.removeClass('transparent');\r\n var d = jQuery('.modal-dialog', overlay);\r\n if (title) {\r\n jQuery('.modal-header', d).show();\r\n jQuery('#promptTitle').text(title);\r\n }\r\n else\r\n jQuery('.modal-header').hide();\r\n if (prompt) {\r\n jQuery('.modal-prompt', d).show();\r\n jQuery('#promptText').html(prompt);\r\n }\r\n else\r\n jQuery('.modal-prompt').hide();\r\n let answer = jQuery('#answer');\r\n if (requireVal)\r\n answer.val('').show();\r\n else\r\n answer.hide();\r\n let buttons = [];\r\n for (let i = 0; i < 3; i++) {\r\n let b = jQuery('#button' + i);\r\n if (callbacks[i]) {\r\n b.val(callbacks[i][0]).click(function () {\r\n close();\r\n callbacks[i][1](answer.val());\r\n return false; // prevents the form to be submitted\r\n }).show();\r\n buttons.push(b);\r\n }\r\n else\r\n b.hide();\r\n }\r\n function close() {\r\n overlay.removeClass('show').hide();\r\n buttons.forEach(x => x.off('click'));\r\n d.css({\r\n left: 'initial',\r\n top: 'initial'\r\n });\r\n }\r\n overlay.addClass('show').show();\r\n // only reposition transparent - aka announce/question - dialogs\r\n if (transparent) {\r\n let r = jQuery('#editor > div')[0].getBoundingClientRect();\r\n let left = r.left + (r.width - d.width()) / 2;\r\n let top = r.top + (r.height - d.height()) / 2 - 24;\r\n d.css({\r\n left: left,\r\n top: top\r\n });\r\n }\r\n jQuery('input', d).first().focus();\r\n }\r\n static disableButtons(disabled, nowait) {\r\n if (disabled) {\r\n if (!nowait)\r\n htmlElem.addClass('wait');\r\n jQuery('.close, .disable-on-wait .btn, .addRemoveLink').prop('disabled', true).addClass('disabled');\r\n }\r\n else {\r\n htmlElem.removeClass('wait');\r\n jQuery('.close, .disable-on-wait .btn, .addRemoveLink').prop('disabled', false).removeClass('disabled');\r\n }\r\n }\r\n static setSaveProgress(success, value, animate) {\r\n let progress = jQuery('.saveprogress div');\r\n if (success)\r\n progress.removeClass('bg-danger');\r\n else {\r\n progress.addClass('bg-danger');\r\n progress.removeClass('progress-bar-striped progress-bar-animated');\r\n }\r\n if (value != undefined) {\r\n if (animate)\r\n progress.addClass('progress-bar-striped progress-bar-animated');\r\n else\r\n progress.removeClass('progress-bar-striped progress-bar-animated');\r\n progress.width(value + \"%\");\r\n }\r\n }\r\n static setSaveAlert(msg) {\r\n if (msg)\r\n jQuery('#pickfile .alert').text(Dialog.localisableContent(msg)).show();\r\n else\r\n jQuery('#pickfile .alert').hide();\r\n }\r\n // Create and render a Picker object for picking user Photos.\r\n createPicker(callback, mime) {\r\n this.googlePicker = new google.picker.PickerBuilder().\r\n // addView(google.picker.ViewId.PHOTOS).\r\n // addView(new google.picker.DocsView().setSelectFolderEnabled(true)).\r\n // addView(new google.picker.DocsUploadView().setIncludeFolders(true)).\r\n addView(this.googleView).\r\n setOAuthToken(Dialog.googleToken).\r\n setDeveloperKey(developerKey).\r\n setAppId(appId).\r\n setCallback(pickerCallback).\r\n setLocale(Dialog.locale).\r\n setTitle(Dialog.localisableContent(mime ? 'locSelectFile' : 'locSelectFolder')).\r\n build();\r\n this.googlePicker.setVisible(true);\r\n function pickerCallback(data) {\r\n if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {\r\n var doc = data[google.picker.Response.DOCUMENTS][0];\r\n callback(doc);\r\n this.dispose();\r\n }\r\n else if (data[google.picker.Response.ACTION] == google.picker.Action.CANCEL)\r\n this.dispose();\r\n }\r\n }\r\n openGooglePicker(mime, callback) {\r\n this.googleView = mime ?\r\n new google.picker.DocsView(google.picker.ViewId.DOCS)\r\n .setMimeTypes(mime)\r\n .setIncludeFolders(true)\r\n : new google.picker.DocsView(google.picker.ViewId.FOLDERS)\r\n .setSelectFolderEnabled(true);\r\n this.googleCallback = callback;\r\n if (!Dialog.googleToken) {\r\n gapi.auth2.authorize({\r\n client_id: clientId,\r\n scope: scope\r\n }, (x) => {\r\n if (x.access_token) {\r\n Dialog.googleToken = x.access_token;\r\n this.createPicker(callback, mime);\r\n }\r\n });\r\n return;\r\n }\r\n this.createPicker(callback, mime);\r\n }\r\n}\r\nDialog.locale = 'en';\r\nwindow.pagePrompt = Dialog.prompt;\r\n","import { Dialog } from \"./dialog\";\r\nimport { Shapes } from \"./shapes\";\r\nimport '../jswebplayer/assets/options.js';\r\nimport '../jswebplayer/vendor/debugout.js';\r\n// the following imports are not really required, but don't want to change jswebplayer source\r\nimport '../jswebplayer/assets/linkicon.png';\r\nimport '../jswebplayer/assets/soundicon.png';\r\nimport '../jswebplayer/assets/soundicon_pressed.png';\r\nimport tutorial from './tutorial.html';\r\nif (window['tutorial'])\r\n jQuery('.editor div.wrapper').append(tutorial);\r\nimport modals from './modals.html';\r\njQuery('.editor div.wrapper').append(modals);\r\nif (!window['tutorial']) {\r\n jQuery('.tutorial-button-action').remove();\r\n jQuery('[data-hint-order=\"10\"]').attr('data-hint-actions', 'next or done never');\r\n}\r\nDialog.setProjectTitle(jQuery('meta[property=\"og:title\"]').attr('content'));\r\nfunction trackEvent(name) {\r\n var _a;\r\n (_a = window['appInsights']) === null || _a === void 0 ? void 0 : _a.trackEvent({ name });\r\n}\r\nwindow['trackEvent'] = trackEvent;\r\nconst PROJECT_ROOT = '/projects/';\r\nvar autoCompleteCookie = true;\r\nvar autoSaveTimer;\r\nconst needSaveIndicator = jQuery('.need-save');\r\nvar needSave;\r\nconst languageShortCode = {\r\n 'English': 'en',\r\n 'French': 'fr',\r\n 'Russian': 'ru',\r\n 'Ojibwe': 'oj',\r\n 'Mikmaw': 'mic',\r\n 'Mohawk': 'moh',\r\n 'Oji-Cree': 'ojs',\r\n 'Inuktitut': 'iu',\r\n};\r\nfunction setupEditors(app) {\r\n var userproc = app.getProject().getGlobals().userproc;\r\n const Tooltip = window.ace.require('ace/tooltip').Tooltip;\r\n const lang = window.ace.require(\"ace/ext/language_tools\");\r\n var configureEditor = function (editorId) {\r\n var hostEditor = window.ace.edit(editorId);\r\n hostEditor.setTheme(\"ace/theme/tomorrow\");\r\n lang.setCompleters([lang.keyWordCompleter]);\r\n hostEditor.setOptions({\r\n enableLiveAutocompletion: autoCompleteCookie,\r\n });\r\n hostEditor.session.setMode(\"ace/mode/logo\");\r\n hostEditor.session.setOptions({\r\n wrap: true,\r\n useSoftTabs: true,\r\n tabSize: 2\r\n });\r\n hostEditor.tokenTooltip = new Tooltip(hostEditor.container);\r\n function hideTooltip() {\r\n hostEditor.tokenTooltip.hide();\r\n hostEditor.tokenTooltip.lastTokenTipped = null;\r\n clearTimeout(hostEditor.tokenTimeout);\r\n }\r\n document.getElementById(editorId).onmouseout = function () {\r\n if (!hostEditor.tokenTooltip.getElement().matches(':hover'))\r\n hideTooltip();\r\n };\r\n hostEditor.on('changeSelection', hideTooltip);\r\n hostEditor.on(\"mousemove\", function (e) {\r\n clearTimeout(hostEditor.tokenTimeout);\r\n var position = e.getDocumentPosition();\r\n if (position && window.primtips.tips) {\r\n var t = hostEditor.tokenTooltip;\r\n var token = hostEditor.getSession().getTokenAt(position.row, position.column);\r\n if (token && (token.type == \"support.function\" || token.type == \"identifier\")) {\r\n var last = t.lastTokenTipped || { type: undefined, value: undefined };\r\n if (token.type != last.type && token.value != last.value) {\r\n hideTooltip();\r\n var text;\r\n if (token.type == \"support.function\")\r\n text = window.primtips.tips[token.value.toLowerCase()];\r\n else if (token.type == \"identifier\") {\r\n text = userproc.get(token.value);\r\n if (text)\r\n text = text.procProperties.doc;\r\n }\r\n if (!text) {\r\n return;\r\n }\r\n t.lastTokenTip = {\r\n text,\r\n screen: hostEditor.renderer.textToScreenCoordinates(position.row, token.start),\r\n };\r\n }\r\n hostEditor.tokenTimeout = setTimeout(function () {\r\n t.show(t.lastTokenTip.text);\r\n $(\".ace_tooltip\").append('
');\r\n prepareVoiceTip(token.value.toLowerCase());\r\n var screen = t.lastTokenTip.screen;\r\n var x = t.lastTokenTip.screen.pageX;\r\n var y = screen.pageY - t.getHeight();\r\n if (x + t.getWidth() > window.innerWidth)\r\n x = window.innerWidth - t.getWidth();\r\n if (y < 0)\r\n y = screen.pageY + hostEditor.renderer.lineHeight;\r\n t.setPosition(x, y);\r\n }, 500);\r\n }\r\n else {\r\n hideTooltip();\r\n }\r\n t.lastTokenTipped = token;\r\n }\r\n });\r\n hostEditor.disabled = function (b) {\r\n hostEditor.setReadOnly(b);\r\n if (b)\r\n jQuery('#' + editorId).addClass('disabled-editor');\r\n else\r\n jQuery('#' + editorId).removeClass('disabled-editor');\r\n };\r\n hostEditor.commands.bindKey('Option+Z', function () {\r\n let newValue = hostEditor.session.getOption('wrap') == 'off';\r\n hostEditor.session.setOption('wrap', newValue);\r\n });\r\n return hostEditor;\r\n };\r\n var prepareVoiceTip = function prepareVoiceTip(prim, lang = 'en') {\r\n function showPlayButton() {\r\n $(\".voice-tip\").append(`${lang} `);\r\n }\r\n const name = `/tips/${lang}/${prim}.wav`;\r\n const projectLanguage = languageShortCode[window['projectData'].compiler_lang];\r\n if (voiceCache[name] != undefined) {\r\n if (voiceCache[name] != '')\r\n showPlayButton();\r\n if (projectLanguage != lang)\r\n prepareVoiceTip(prim, projectLanguage);\r\n return;\r\n }\r\n var voice = window['samplesRoot'] + name;\r\n fetch(voice, {\r\n method: 'HEAD',\r\n cache: 'default',\r\n })\r\n .then(resp => {\r\n if (resp.ok) {\r\n voiceCache[name] = name; // don't create Audio just yet\r\n showPlayButton();\r\n }\r\n else\r\n voiceCache[name] = '';\r\n if (projectLanguage != lang)\r\n prepareVoiceTip(prim, projectLanguage);\r\n });\r\n };\r\n var compileProcs = function () {\r\n if (userproc.dirty)\r\n cc.commandcentre.sendProcs(procs.getValue());\r\n };\r\n var procs = configureEditor(\"procedures\");\r\n procs.on(\"change\", function () {\r\n userproc.dirty = true;\r\n markDirty();\r\n });\r\n procs.on(\"blur\", compileProcs);\r\n procs.on(\"guttermousedown\", function (e) {\r\n var target = e.domEvent.target;\r\n if (target.className.indexOf(\"ace_gutter-cell\") == -1) {\r\n return;\r\n }\r\n if (e.clientX > 25 + target.getBoundingClientRect().left) {\r\n return;\r\n }\r\n let tab = userproc.raw[userproc.active].id;\r\n var row = e.getDocumentPosition().row + 1;\r\n if (Debugger.isProcBreakpoint(tab, row)) {\r\n Debugger.removeProcBreakpoint(tab, row);\r\n e.editor.session.clearBreakpoint(row - 1);\r\n e.stop();\r\n return;\r\n }\r\n compileProcs();\r\n if (!Debugger.getProcByLine(tab, row))\r\n return;\r\n Debugger.addProcBreakpoint(tab, row);\r\n e.editor.session.setBreakpoint(row - 1);\r\n e.stop();\r\n });\r\n window.appendProc = function (text) {\r\n markDirty();\r\n var session = procs.session;\r\n session.insert({\r\n row: session.getLength(),\r\n column: 0\r\n }, text);\r\n procs.scrollToRow(session.getLength());\r\n compileProcs();\r\n };\r\n const proctabs = jQuery('#proctabs');\r\n const deleteProcTab = jQuery('.deleteproctab', proctabs);\r\n const unavailableClass = 'unavailable';\r\n function setupProcedures() {\r\n function procIndexFromId(id) {\r\n return userproc.raw.findIndex(x => x.id == id);\r\n }\r\n function switchTo(e) {\r\n let id = e.currentTarget.id;\r\n proctabs.data('active', id);\r\n let name = jQuery('#' + id).text();\r\n jQuery('div.procname', proctabs).text(name);\r\n let activeTab = userproc.raw[userproc.active];\r\n activeTab.selection = procs.getSelectionRange();\r\n activeTab.breakpoints = [];\r\n for (let b in procs.session.getBreakpoints())\r\n activeTab.breakpoints.push(b);\r\n let seqNum = procIndexFromId(id);\r\n userproc.active = seqNum;\r\n activeTab = userproc.raw[userproc.active];\r\n procs.setValue(activeTab.text);\r\n let range = activeTab.selection || { start: { row: 0, column: 0 }, end: { row: 0, column: 0 } };\r\n procs.selection.setRange(range);\r\n procs.session.setBreakpoints(activeTab.breakpoints || []);\r\n if (id == 'procs0')\r\n deleteProcTab.addClass(unavailableClass);\r\n else\r\n deleteProcTab.removeClass(unavailableClass);\r\n }\r\n jQuery('div.procname').click(function () {\r\n jQuery('div.procname').removeClass('visible');\r\n jQuery('input.procname').val(jQuery('div.procname').text()).addClass('visible').focus();\r\n });\r\n jQuery('input.procname').blur(function () {\r\n let input = jQuery('input.procname');\r\n let div = jQuery('div.procname');\r\n let oldName = div.text();\r\n let name = input.val() || oldName;\r\n if (oldName != name)\r\n markDirty();\r\n input.removeClass('visible');\r\n div.text(name).addClass('visible');\r\n userproc.raw[userproc.active].name = name;\r\n let active = proctabs.data('active');\r\n jQuery('#' + active, proctabs).text(name);\r\n });\r\n const defaultProcName = Dialog.localisableContent('locDefaultProcs');\r\n function newProcTab(text, name, seqNum) {\r\n let tabsMenu = jQuery('.menu', proctabs);\r\n if (!name)\r\n seqNum = jQuery('.menuitem', tabsMenu).length - 1;\r\n let id = 'procs' + seqNum;\r\n let untitled = name || defaultProcName + ' ' + seqNum;\r\n jQuery('.newproctab', tabsMenu).before('
' + untitled + '
');\r\n jQuery('#' + id, proctabs).click(switchTo);\r\n if (name)\r\n userproc.raw[seqNum].id = id;\r\n else\r\n userproc.raw.push({ id: id, name: untitled, text: text });\r\n return id;\r\n }\r\n jQuery('.newproctab').click(function () {\r\n let id = newProcTab('');\r\n switchTo({ currentTarget: { id: id } });\r\n jQuery('div.procname', proctabs).click();\r\n deleteProcTab.removeClass(unavailableClass);\r\n });\r\n deleteProcTab.click(function (e) {\r\n let text = userproc.raw[userproc.active].text;\r\n let id = proctabs.data('active');\r\n if (!text.trim()) {\r\n deleteActive('', false);\r\n return;\r\n }\r\n let name = jQuery('#' + id).text();\r\n Dialog.prompt([\r\n [Dialog.localisableContent('locNo'), function () { }],\r\n [Dialog.localisableContent('locYes'), deleteActive],\r\n [Dialog.localisableContent('locCopyAndDelete'), copyAndDeleteActive],\r\n ], name + Dialog.localisableContent('locProceduresAreNotEmpty'), Dialog.localisableContent('locSureToDelete'));\r\n function deleteActive(v, compile = true) {\r\n Debugger.removeProcBreakpoint(id);\r\n jQuery('#' + id).remove();\r\n // if there is only \"Procedures\" in the menu, hide it\r\n let tabsMenu = jQuery('.menu', proctabs);\r\n if (1 == tabsMenu.children('.menuitem').length)\r\n tabsMenu.addClass(unavailableClass);\r\n switchTo({ currentTarget: { id: 'procs0' } });\r\n userproc.raw.splice(procIndexFromId(id), 1);\r\n if (compile)\r\n cc.commandcentre.sendProcs();\r\n }\r\n function copyAndDeleteActive() {\r\n deleteActive('', false);\r\n window.appendProc('\\n; ' + name + '\\n' + text);\r\n }\r\n });\r\n userproc.raw.forEach((x, i) => {\r\n newProcTab(x.text, x.name, i);\r\n x.breakpoints = [];\r\n });\r\n jQuery('div.procname').text(userproc.raw[0].name);\r\n }\r\n setupProcedures();\r\n let debugcc = configureCommandCentre(\"debugcc\");\r\n debugcc.commands.bindKey(\"Enter\", handleLine);\r\n Debugger.setProcBpCallback(breakpointCallback);\r\n let vars = jQuery('#variables');\r\n jQuery('#continue').click(function () {\r\n Debugger.continueExecution();\r\n });\r\n function continueExecution() {\r\n vars.empty();\r\n vars.append('');\r\n jQuery('#continue').hide();\r\n // it's not obvious when the scope is lost, but\r\n // sometimes an error kills it\r\n if (debugcc.commandcentre.scope) {\r\n debugcc.commandcentre.scope.refresh = undefined;\r\n debugcc.commandcentre.scope = undefined;\r\n debugcc.commandcentre.logoContext = undefined;\r\n }\r\n }\r\n function refreshVars(scope) {\r\n vars.empty();\r\n vars.append(scope.displayHeader);\r\n if (scope.globalDictionary.size) {\r\n vars.append('
');\r\n let even = '';\r\n scope.globalDictionary.forEach(function (v, k) {\r\n vars.append(`
` + k + '
' + v + '
');\r\n even = even ? '' : 'even';\r\n });\r\n }\r\n if (scope.localDictionary.size) {\r\n vars.append('
');\r\n let even = '';\r\n scope.localDictionary.forEach(function (v, k) {\r\n vars.append(`
` + k + '
' + v + '
');\r\n even = even ? '' : 'even';\r\n });\r\n }\r\n }\r\n function breakpointCallback(val, coroutine) {\r\n if (!val) {\r\n continueExecution();\r\n window.location.hash = '#commandcentre';\r\n return;\r\n }\r\n window.location.hash = '#debug';\r\n jQuery('#continue').show();\r\n let proc = coroutine.currentProc;\r\n let procText = '';\r\n if (proc) {\r\n procText = `${proc}`;\r\n }\r\n let scope = coroutine.lcu.getScope();\r\n let line = app.getProject().getGlobals().getTabName(val.tab, val.line);\r\n scope.displayHeader = `
${line}${procText}
`;\r\n scope.refresh = refreshVars;\r\n refreshVars(scope);\r\n debugcc.commandcentre.scope = scope;\r\n debugcc.commandcentre.logoContext = coroutine.context.logoContext;\r\n }\r\n var cc = configureCommandCentre(\"commandcentre\");\r\n function configureCommandCentre(editorId) {\r\n let cc = configureEditor(editorId);\r\n cc.setOptions({\r\n highlightActiveLine: false\r\n });\r\n cc.renderer.setOptions({\r\n showGutter: false,\r\n showPrintMargin: false,\r\n displayIndentGuides: false\r\n });\r\n cc.commandcentre = app[editorId];\r\n cc.commandcentre.editor = cc;\r\n // https://stackoverflow.com/questions/32320574/detect-a-right-click-on-ace-editor\r\n cc.on(\"mousedown\", app[editorId].stopCommandCentre, true);\r\n // TODO: once CC loading is fixed, uncomment // cc.on(\"change\", markDirty);\r\n return cc;\r\n }\r\n cc.cleanup = null;\r\n // https://stackoverflow.com/questions/32315244/single-line-ace-editor\r\n cc.commands.bindKey(\"Enter\", handleLine);\r\n function handleLine(editor) {\r\n var sel = editor.getSelection();\r\n var row = sel.getRange().start.row;\r\n var toExecute = editor.session.getLine(row);\r\n editor.navigateTo(row, toExecute.length);\r\n editor.cleanup = sel.getRange();\r\n editor.insert(\"•\");\r\n // r.row is 0-based\r\n if (row === editor.session.getLength() - 1)\r\n editor.insert(\"\\n\");\r\n editor.navigateRight();\r\n editor.setReadOnly(true);\r\n editor.commandcentre.send(toExecute);\r\n // true cancels the insertion\r\n return true;\r\n }\r\n window.cleanupLine = function (editor) {\r\n if (null !== editor.cleanup) {\r\n if (editor.cleanup.end) {\r\n // https://stackoverflow.com/questions/26555492/ace-editor-find-text-select-row-and-replace-text\r\n editor.cleanup.end.column += 1;\r\n editor.session.replace(editor.cleanup, \"\");\r\n }\r\n editor.setReadOnly(false);\r\n editor.cleanup = null;\r\n }\r\n };\r\n window.showLine = function (hostEditor, x, highlight) {\r\n hostEditor = hostEditor || cc;\r\n if (highlight && hostEditor.lastHighlight && hostEditor.lastHighlight.isEqual(hostEditor.getSelectionRange())) {\r\n hostEditor.navigateRight(); // removes selected, to the end of the line\r\n hostEditor.navigateRight(); // moves to the next line\r\n }\r\n var start = hostEditor.getSelection().getRange().start;\r\n hostEditor.insert(x);\r\n var end = hostEditor.getSelection().getRange().end;\r\n hostEditor.insert(\"\\n\");\r\n hostEditor.renderer.scrollToRow(end.row);\r\n if (highlight) {\r\n hostEditor.getSelection().setRange({ start: start, end: end });\r\n hostEditor.lastHighlight = hostEditor.getSelectionRange();\r\n }\r\n else\r\n hostEditor.lastHighlight = undefined;\r\n };\r\n window.clearCC = function () {\r\n cc.cleanup = {};\r\n cc.lastHighlight = undefined;\r\n cc.setValue('');\r\n };\r\n function newSound(url, filename, formData, close) {\r\n function statusReport(xhr) {\r\n Dialog.disableButtons(false);\r\n if (xhr.status == 200) {\r\n let r = JSON.parse(xhr.response);\r\n if (r.error == -1)\r\n Dialog.setSaveAlert('locCannotDownloadSound');\r\n else if (r.error == -2)\r\n Dialog.setSaveAlert('locWrongFileType');\r\n else {\r\n if (!filename) {\r\n // user entered a URL\r\n let dir = dirname(url);\r\n filename = url.substr(dir.length ? dir.length + 1 : dir.length);\r\n }\r\n // TODO: remove duplication of folder name between here and UploadProjectMagic\r\n player.newSound(r.message, filename.substr(0, filename.lastIndexOf('.')));\r\n close();\r\n return;\r\n }\r\n }\r\n Dialog.setSaveProgress(false, 100);\r\n }\r\n function progressReport(e) {\r\n let progress = Math.min(100, e.loaded / e.total * 100 + 1);\r\n if (95 < progress)\r\n progress = 100;\r\n Dialog.setSaveProgress(true, progress, 100 == progress);\r\n }\r\n Dialog.disableButtons(true);\r\n let urlArg = '';\r\n if (!formData)\r\n urlArg = '&url=' + encodeURIComponent(url);\r\n window['sendToServer']('/storefile/' + window.projectData.id, 'suffix=.wav' + urlArg, formData, progressReport).then(statusReport);\r\n }\r\n let player = window.jswebplayer;\r\n addClick(() => player.newTurtle(), \"newturtle\");\r\n addClick(() => player.newTextbox(), \"newtextbox\");\r\n addClick(() => player.newButton(), \"newbutton\");\r\n addClick(() => player.newSlider(), \"newslider\");\r\n addClick(() => player.newHyperlink(), \"newhyperlink\");\r\n addClick(() => player.newPage(), \"newpage\");\r\n addClick(() => { new Dialog().showFilePicker('locImportSound', 'audio', newSound, 'locCreateButton', true); }, \"newsound\");\r\n function sendChunk(text, callback, start = 0, id = window.projectData.id, auto = '') {\r\n const chunkSize = 1000000;\r\n callback(start / text.length);\r\n jQuery.ajax('/upload/' + id + '/' + start + '/' + text.length + auto, {\r\n type: 'POST',\r\n data: { text: text.substr(start, chunkSize), title: projNameInput.val(), copyof: window.projectData.id },\r\n timeout: 2 * 60 * 1000,\r\n }).done(function (data) {\r\n if (data.id)\r\n callback(true, data);\r\n else\r\n sendChunk(text, callback, start + chunkSize, data.name, auto);\r\n }).fail(function (xhr) {\r\n callback(xhr.responseJSON ? xhr.responseJSON.message : '');\r\n });\r\n }\r\n var saveStatusReport;\r\n function saveReport(status, data) {\r\n saveStatusReport(status, data);\r\n }\r\n function fullSaveReport(status, data) {\r\n if (typeof status == \"number\") {\r\n Dialog.setSaveProgress(true, Math.min(100, status * 100 + 1), true);\r\n return;\r\n }\r\n autoSaveTimer = 0;\r\n if (typeof status == \"string\") {\r\n Dialog.setSaveProgress(false);\r\n Dialog.disableButtons(false);\r\n Dialog.setError(status || 'An error occurred. Please try again.');\r\n }\r\n else {\r\n if (data.auth) {\r\n Dialog.setSaveProgress(true, 100);\r\n Dialog.disableButtons(false);\r\n Dialog.setError(data.auth);\r\n return;\r\n }\r\n Dialog.setSaveProgress(true, 100, true);\r\n updateProjectName(data.id, data.href, fullSaveReport, data.cloudUndo);\r\n }\r\n }\r\n function autoSaveReport(status, data) {\r\n if (typeof status == \"number\") {\r\n console.debug(`auto-save progress: ${status}`);\r\n return;\r\n }\r\n saveStatusReport = undefined;\r\n autoSaveTimer = 0;\r\n if (typeof status == \"string\") {\r\n console.error(`auto-save error: ${status}`);\r\n autoSaveTimer = setTimeout(autoSave, 5 * 60 * 1000);\r\n }\r\n else if (data.auth)\r\n console.warn(`auto-save: auth required`);\r\n }\r\n function fileSave(e) {\r\n let editorElems = $('.ql-editor');\r\n editorElems.trigger(\"before-save-editor\");\r\n donePopover();\r\n new Dialog().showFileSaver(\"locSaveTitle\");\r\n clearTimeout(autoSaveTimer);\r\n autoSaveTimer = 0;\r\n if (saveStatusReport == autoSaveReport) {\r\n saveStatusReport = fullSaveReport;\r\n return;\r\n }\r\n saveStatusReport = undefined;\r\n let d;\r\n try {\r\n d = JSON.stringify(app.getProject().save());\r\n sendChunk(d, fullSaveReport, 0, (e === null || e === void 0 ? void 0 : e.altKey) ? 0 : undefined);\r\n editorElems.trigger(\"after-save-editor\");\r\n }\r\n catch (oops) {\r\n fullSaveReport(`Error generating project data: ${oops.message}. Please try again.`);\r\n }\r\n }\r\n window['fileSave'] = fileSave;\r\n function autoSave() {\r\n let d;\r\n try {\r\n d = JSON.stringify(app.getProject().save());\r\n saveStatusReport = autoSaveReport;\r\n sendChunk(d, saveReport, 0, window['projectData'].id, '?auto');\r\n }\r\n catch (oops) {\r\n autoSaveReport(`Error generating project data: ${oops.message}. Please try again.`);\r\n autoSaveTimer = setTimeout(autoSave, 5 * 60 * 1000);\r\n }\r\n }\r\n function markDirty(state = true) {\r\n needSave = state;\r\n if (state) {\r\n needSaveIndicator.show();\r\n if (!autoSaveTimer && window['projectData'].id != \"0\")\r\n autoSaveTimer = setTimeout(autoSave, 15 * 60 * 1000);\r\n }\r\n else {\r\n needSaveIndicator.hide();\r\n clearTimeout(autoSaveTimer);\r\n autoSaveTimer = 0;\r\n }\r\n }\r\n window['needSave'] = markDirty;\r\n window['isDirty'] = function () { return needSave; };\r\n addClick(fileSave, \"filesave\");\r\n $(document).keydown(function (e) {\r\n if (e.metaKey || e.ctrlKey) {\r\n switch (e.key) {\r\n case 's':\r\n procs.blur();\r\n projNameInput.blur();\r\n fileSave(e);\r\n break;\r\n default:\r\n return;\r\n }\r\n e.preventDefault();\r\n }\r\n });\r\n $('#projecttree').keydown(function (e) {\r\n if (e.metaKey || e.ctrlKey) {\r\n switch (e.key) {\r\n case 'c':\r\n copyLogoObject();\r\n break;\r\n default:\r\n return;\r\n }\r\n e.preventDefault();\r\n }\r\n });\r\n function toggleAutoComplete() {\r\n let newValue = !cc.getOption('enableLiveAutocompletion');\r\n cc.setOption('enableLiveAutocompletion', newValue);\r\n procs.setOption('enableLiveAutocompletion', newValue);\r\n toggleClass(this.getElementsByTagName('i'), 'fa-toggle-on');\r\n let expires = newValue ? ';expires=Fri, 01 Feb 1901 00:00:00 GMT' : ';expires=Mon, 01 Feb 2100 00:00:00 GMT';\r\n document.cookie = 'autocomplete=false;path=/' + expires;\r\n }\r\n addClick(toggleAutoComplete, 'changeautocomplete');\r\n app.dialog = new Dialog(app);\r\n app.shapeEditor = new Shapes();\r\n jQuery(document).bind('paste', function (e) {\r\n if (e.isDefaultPrevented())\r\n return;\r\n app.shapeEditor.paste(e);\r\n if (e.isDefaultPrevented())\r\n return;\r\n treePaste(e);\r\n });\r\n function scaleEditor(ev) {\r\n window.location.hash = '';\r\n let w = app.getProject().getWidth();\r\n let h = app.getProject().getHeight();\r\n if (window.innerWidth < 768 && (window.innerWidth < w || window.innerHeight < h)) {\r\n // -15 is to account for scrollbars\r\n scaleScreenDiv({\r\n width: window.innerWidth - 15, height: window.innerHeight - 15,\r\n w, h\r\n });\r\n }\r\n else\r\n scaleScreenDiv();\r\n }\r\n if (window.innerWidth < 768) {\r\n screenDiv.css({ transform: 'scale(.1)' }); // remove initial scrollbars\r\n setTimeout(scaleEditor, 50); // let the window redraw before re-scaling\r\n }\r\n window.onresize = scaleEditor;\r\n jQuery('#root-div').on('contextmenu', (e) => {\r\n var data = app.contextMenuTurtle;\r\n if (window.innerWidth < 768) {\r\n fileShare();\r\n return false;\r\n }\r\n if (!data) {\r\n return;\r\n }\r\n app.contextMenuTurtle = null;\r\n app.dialog.show(e, data);\r\n return false;\r\n });\r\n const treeNodePrefix = 'node-';\r\n function buildTreeNode(o) {\r\n var _a;\r\n return { text: (_a = o.label) !== null && _a !== void 0 ? _a : o.name, id: treeNodePrefix + o.id, type: o.type, children: [] };\r\n }\r\n function buildProjectTree(obj, cb) {\r\n let data = [];\r\n let pages = app.getProject().getPages();\r\n for (const p of pages) {\r\n let pnode = buildTreeNode(p);\r\n data.push(pnode);\r\n for (const o of p.getLogoObjects())\r\n pnode.children.push(buildTreeNode(o));\r\n }\r\n cb.call(this, data);\r\n }\r\n jQuery('#tree')['jstree']({\r\n core: {\r\n check_callback: true,\r\n data: buildProjectTree,\r\n },\r\n plugins: [\r\n 'wholerow',\r\n 'types',\r\n ],\r\n types: {\r\n page: { icon: 'fas fas-sm fa-file' },\r\n turtle: { icon: 'fas fas-sm fa-paw' },\r\n text: { icon: 'fas fas-sm fa-chalkboard' },\r\n button: { icon: 'fas fas-sm fa-code' },\r\n slider: { icon: 'fas fas-sm fa-sliders-h' },\r\n hyperlink: { icon: 'fas fas-sm fa-download' },\r\n audio: { icon: 'fas fas-sm fa-headphones' },\r\n midi: { icon: 'fas fas-sm fa-headphones' },\r\n },\r\n }).on('changed.jstree', function (e, data) {\r\n jQuery('#edittree').prop('disabled', data.selected.length != 1);\r\n jQuery('#deletetree').prop('disabled', data.selected.length == 0);\r\n });\r\n let tree = jQuery['jstree'].reference('#tree');\r\n jQuery('#deletetree').click(function () {\r\n let selid = tree.get_selected();\r\n let selobj = [];\r\n for (const o of selid) {\r\n let par = tree.get_parent(o);\r\n if (par == '#') // page\r\n selobj.unshift({ page: o });\r\n else\r\n selobj.push({ page: par, id: o });\r\n }\r\n for (const o of selobj) {\r\n let obj = app.getProject().getPages().find(p => treeNodePrefix + p.id == o.page);\r\n if (!obj)\r\n continue;\r\n // 5 is treeNodePrefix.length\r\n if (o.id)\r\n obj = obj.getLogoObjects().find(function (x) { return treeNodePrefix + x.id == o.id; });\r\n obj.remove();\r\n }\r\n });\r\n jQuery('#edittree').click(function (e) {\r\n let obj = getSelectedObject(true);\r\n app.dialog.show(e, obj);\r\n });\r\n jQuery('#tree').bind('copy', function (e) {\r\n copyLogoObject();\r\n });\r\n function getSelectedObject(needLeaf) {\r\n const selection = tree.get_selected();\r\n if (!selection.length)\r\n return;\r\n let selid = selection[0];\r\n let par = tree.get_parent(selid);\r\n let obj = app.getProject().getPages().find(p => treeNodePrefix + p.id == (par == '#' ? selid : par));\r\n if (needLeaf && par != '#')\r\n obj = obj.getLogoObjects().find(function (x) { return treeNodePrefix + x.id == selid; });\r\n return obj;\r\n }\r\n function copyLogoObject() {\r\n const collected = [];\r\n const projectsize = [app.getProject().getWidth(), app.getProject().getHeight()];\r\n const selection = tree.get_selected();\r\n for (const item of selection) {\r\n const par = tree.get_parent(item);\r\n let o;\r\n if (par == '#') {\r\n o = app.getProject().getPageList().find(p => treeNodePrefix + p.id == item);\r\n }\r\n else {\r\n const page = app.getProject().getPageList().find(p => treeNodePrefix + p.id == par);\r\n o = page.getLogoObjects().find(x => treeNodePrefix + x.id == item);\r\n }\r\n if (o && o.save) {\r\n let obj = o.save();\r\n obj.projectsize = projectsize;\r\n collected.push(obj);\r\n }\r\n }\r\n if (collected.length)\r\n navigator.clipboard.writeText(JSON.stringify(collected))\r\n .then(() => {\r\n showToast('Copied');\r\n })\r\n .catch(err => {\r\n showToast('Something went wrong' + err, 2000);\r\n });\r\n }\r\n function treePaste(event) {\r\n if (!event.target.classList.contains('jstree-anchor') && // project tree was clicked first, then an item\r\n !document.activeElement.classList.contains('jstree-anchor')) // item was clicked directly\r\n return;\r\n var p = getSelectedObject(false);\r\n if (!p)\r\n return;\r\n let player = window.jswebplayer;\r\n let project = app.getProject();\r\n let width = project.getWidth();\r\n let height = project.getHeight();\r\n var items = (event.clipboardData || event.originalEvent.clipboardData).items;\r\n for (const item of items) {\r\n item.getAsString(text => {\r\n let pasted = JSON.parse(text);\r\n if (!Array.isArray(pasted))\r\n pasted = [pasted];\r\n const skip = [];\r\n for (const o of pasted) {\r\n if (o.type == \"page\") {\r\n skip.push(o);\r\n let temp = [];\r\n project.loader.AddPageData({ width: width, height: height, }, temp, o);\r\n if (temp.length)\r\n player.newPage(o.name, temp[0]);\r\n else\r\n showToast(\"Can't paste a page of a different size\", 2000);\r\n }\r\n }\r\n // the last pasted page is set by LogoObjectCreator\r\n if (skip.length != pasted.length)\r\n project.setPage(p);\r\n for (const o of pasted) {\r\n if (skip.indexOf(o) > -1)\r\n continue;\r\n if (o.type == \"t\") {\r\n player.newTurtle(undefined, project.loader.parseTurtle(width, height, o));\r\n }\r\n else if (o.type == \"button\") {\r\n player.newButton(undefined, project.loader.parseButton(width, height, o));\r\n }\r\n else if (o.type == \"text\") {\r\n player.newTextbox(undefined, undefined, undefined, project.loader.parseTextbox(width, height, o));\r\n }\r\n else if (o.type == \"record\" || o.type == \"music\") {\r\n player.newSound(undefined, undefined, project.loader.parseAudio(width, height, o));\r\n }\r\n else if (o.type == \"melody\") {\r\n player.newMelody(project.loader.parseMelody(width, height, o));\r\n }\r\n else if (o.type == \"slider\") {\r\n player.newSlider(undefined, undefined, undefined, project.loader.parseSlider(width, height, o));\r\n }\r\n else if (o.type == \"hyperlink\") {\r\n player.newHyperlink(project.loader.parseHyperlink(width, height, o));\r\n }\r\n }\r\n });\r\n }\r\n }\r\n window['renameNode'] = function (id, name, pos) {\r\n id = treeNodePrefix + id;\r\n tree.rename_node(id, name);\r\n if (pos != undefined) {\r\n tree.move_node(id, '#', pos);\r\n }\r\n };\r\n window['createNode'] = function (o, par) {\r\n let node = buildTreeNode(o);\r\n let pos = 'last';\r\n if (par.map) {\r\n pos = par.indexOf(o.name, par);\r\n par = '#';\r\n }\r\n else\r\n par = treeNodePrefix + par;\r\n tree.create_node(par, node, pos);\r\n };\r\n window['removeNode'] = function (id) {\r\n tree.delete_node(treeNodePrefix + id);\r\n };\r\n setupPlayerButtons(app);\r\n // this doesn't work in Safari if the user answered \"Leave\" on this page\r\n window.addEventListener('beforeunload', function (e) {\r\n if (needSave) {\r\n // Cancel the event\r\n e.preventDefault(); // If you prevent default behavior in Mozilla Firefox prompt will always be shown\r\n // Chrome requires returnValue to be set\r\n e.returnValue = 'Do you want to save changes to your project?';\r\n return e.returnValue;\r\n }\r\n });\r\n jQuery('a[data-confirm]').click(function (e) {\r\n if (!needSave)\r\n return;\r\n e.preventDefault();\r\n let href = e.currentTarget.getAttribute('href');\r\n Dialog.prompt([\r\n [Dialog.localisableContent('locNo'), function () { }],\r\n [Dialog.localisableContent('locYes'), function () { needSave = false; window.location.href = href; }],\r\n ], Dialog.localisableContent('locUnsavedChanges'), Dialog.localisableContent('locSureToLeave'));\r\n });\r\n}\r\nfunction setupPlayerButtons(app) {\r\n function pageByOffset(next) {\r\n app.getProject().setPageByOffset(next);\r\n }\r\n addClick(() => pageByOffset(-1), \"pageprev\");\r\n addClick(() => pageByOffset(1), \"pagenext\");\r\n jQuery('#stopall').click(function () {\r\n app.stopAll();\r\n });\r\n jQuery('.full-screen').click(function () {\r\n let doc = document;\r\n if (doc.fullscreenElement) {\r\n doc.exitFullscreen();\r\n return;\r\n }\r\n else if (doc.webkitFullscreenElement) {\r\n doc.webkitExitFullscreen();\r\n return;\r\n }\r\n let wr = jQuery('.wrapper')[0];\r\n if (wr.requestFullscreen)\r\n wr.requestFullscreen();\r\n else\r\n wr.webkitRequestFullscreen();\r\n });\r\n}\r\nlet screenDiv = jQuery('#screen-div');\r\nfunction scaleScreenDiv(size) {\r\n if (size) {\r\n // -15 is to account for scrollbars\r\n let scaleX = size.width / size.w;\r\n let scaleY = size.height / size.h;\r\n let scale = Math.min(scaleX, scaleY);\r\n screenDiv.css({\r\n transform: 'scale(' + scale + ')',\r\n margin: (1 - scale) * -100 + '%',\r\n });\r\n }\r\n else\r\n screenDiv.css({\r\n transform: 'unset',\r\n margin: 'unset',\r\n });\r\n}\r\nfunction toggleTheme() {\r\n let element = document.getElementsByTagName('html')[0];\r\n let v = element.className;\r\n let newTheme = v.indexOf('dark') == -1 ? 'dark' : '';\r\n toggleClass([element], 'dark');\r\n toggleClass(this.getElementsByTagName('i'), 'fa-toggle-on');\r\n document.cookie = 'theme=' + newTheme + ';path=/;expires=Mon, 01 Feb 2100 00:00:00 GMT';\r\n}\r\nfunction toggleFont(e) {\r\n let newFontSize = 'string' == typeof e ? e : this.id;\r\n jQuery('html').removeClass('font-default font-large font-huge').addClass(newFontSize);\r\n jQuery('.changefont i').removeClass('fa-check');\r\n jQuery(`#${newFontSize} i`).addClass('fa-check');\r\n document.cookie = 'font=' + newFontSize + ';path=/;expires=Mon, 01 Feb 2100 00:00:00 GMT';\r\n}\r\nfunction toggleLearner(learner) {\r\n let elem = jQuery('.changelearner');\r\n if (!elem.length)\r\n return;\r\n let i = jQuery('i', elem);\r\n if ('boolean' != typeof learner) {\r\n learner = i[0].className.indexOf('fa-toggle-on') == -1;\r\n i.toggleClass('fa-toggle-on');\r\n }\r\n else if (learner)\r\n i.addClass('fa-toggle-on');\r\n document.cookie = 'learner=' + (learner ? 'true' : '') + ';path=/;expires=Mon, 01 Feb 2100 00:00:00 GMT';\r\n window['learnerMode'] = learner;\r\n}\r\nconst samples = {};\r\nfunction replaceSamples(menuId, itemCallback) {\r\n let holder = samples[menuId];\r\n if (!holder || !holder[Dialog.locale])\r\n return true;\r\n let menu = jQuery(menuId); // #samplesMenu\r\n menu.empty();\r\n holder[Dialog.locale].forEach(function (x) {\r\n if (x.file)\r\n menu.append(itemCallback(x));\r\n else\r\n menu.append(`${x.name}`);\r\n });\r\n}\r\nfunction downloadSamples(menuId, suffix, formatCallback) {\r\n if (replaceSamples(menuId, formatCallback))\r\n if (!window['samplesRoot']) // Play Project doesn't need either Samples or Clipart\r\n return;\r\n window['sendToServer'](`${window['samplesRoot']}/${Dialog.locale}.${suffix}.js`).then(function (xhr) {\r\n samples[menuId] = {};\r\n if (xhr.status == 200)\r\n samples[menuId][Dialog.locale] = JSON.parse(xhr.response);\r\n replaceSamples(menuId, formatCallback);\r\n });\r\n}\r\nfunction changeSamples() {\r\n downloadSamples('#samplesMenu', 'samples', function formatSample(x) {\r\n return `${x.name}`;\r\n });\r\n}\r\nfunction changeClipart() {\r\n downloadSamples('#clipartMenu', 'clipart', function (x) {\r\n let images = JSON.stringify(x.file);\r\n return `${x.name}`;\r\n });\r\n}\r\nfunction changeLanguage(e) {\r\n let lang = 'string' == typeof e ? e : this.id;\r\n if (lang)\r\n jQuery('html').attr('lang', lang);\r\n else\r\n lang = jQuery('html').attr('lang');\r\n Dialog.setLocale(lang);\r\n changeSamples();\r\n changeClipart();\r\n}\r\nfunction fileShare() {\r\n donePopover();\r\n jQuery('.menu.open').removeClass('open');\r\n jQuery(menuOverlay).removeClass(\"active\");\r\n new Dialog().showFileSharer();\r\n}\r\naddClick(toggleTheme, \"changetheme\");\r\naddClick(changeLanguage, \"changelanguage\");\r\naddClick(toggleFont, \"changefont\");\r\naddClick(toggleLearner, \"changelearner\");\r\naddClick(Dialog.showNewProject, \"filenewproject\");\r\nfunction help() {\r\n trackEvent('Help');\r\n window.open('https://data.lynxcoding.org/help/' + Dialog.locale + '/help' + (window['learnerMode'] ? 'learner' : 'full') + '/index.htm', 'HelpWindow', 'width=700,height=700', true);\r\n return false;\r\n}\r\naddClick(help, \"help\");\r\nwindow.setupEditors = window.ace ? setupEditors : setupPlayerButtons;\r\nwindow['sendToServer'] = function (url, queryString, data = undefined, progressCallback) {\r\n return new Promise((resolve, reject) => {\r\n let xhr = new XMLHttpRequest();\r\n xhr.open(data ? \"POST\" : \"GET\", url + \"?\" + queryString, true);\r\n // xhr.open(\"POST\", \"http://duckoteka.pythonanywhere.com/api/translate\", true);\r\n //xhr.open(\"POST\", \"https://hurl.it\", true);\r\n if (progressCallback)\r\n xhr.upload.onprogress = progressCallback;\r\n if (data) {\r\n let token = jQuery('meta[name=\"csrf-token\"]').attr('content');\r\n if (data.append)\r\n data.append('_token', token);\r\n else {\r\n data['_token'] = token;\r\n data = JSON.stringify(data);\r\n xhr.setRequestHeader(\"Content-type\", \"application/json\");\r\n }\r\n }\r\n /*xhr.onreadystatechange = function() {\r\n if(xhr.readyState == 4 && xhr.status == 200) {\r\n let answer = xhr.responseText();\r\n resolve(\r\n }\r\n }*/\r\n xhr.onload = () => resolve(xhr);\r\n xhr.onerror = reject;\r\n xhr.send(data);\r\n });\r\n};\r\nfunction addClick(func, className) {\r\n let t = document.getElementsByClassName(className);\r\n Array.prototype.forEach.call(t, function (element) {\r\n element.onclick = func;\r\n });\r\n}\r\nfunction addClass(arr, className) {\r\n Array.prototype.forEach.call(arr, element => {\r\n let v = element.className;\r\n if (v.indexOf(className) == -1)\r\n element.setAttribute(\"class\", v + \" \" + className);\r\n });\r\n}\r\nfunction removeClass(arr, className) {\r\n Array.prototype.forEach.call(arr, element => {\r\n let v = element.className;\r\n element.setAttribute(\"class\", v.replace(className, \"\"));\r\n });\r\n}\r\nfunction toggleClass(arr, className) {\r\n Array.prototype.forEach.call(arr, element => {\r\n let v = element.className;\r\n if (v.indexOf(className) == -1)\r\n element.setAttribute(\"class\", v + \" \" + className);\r\n else\r\n element.setAttribute(\"class\", v.replace(className, \"\"));\r\n });\r\n}\r\nconst dlg = new Dialog();\r\nfunction fileLoad(url, filename, formData) {\r\n function openUrl(url) {\r\n let suffix = '';\r\n if (filename)\r\n suffix = '&name=' + encodeURIComponent(filename);\r\n window.location.replace('/?' + url + suffix);\r\n }\r\n function statusReport(xhr) {\r\n Dialog.disableButtons(false);\r\n if (xhr.status == 200)\r\n openUrl('users/' + encodeURIComponent(xhr.responseText));\r\n else\r\n Dialog.setSaveProgress(false);\r\n }\r\n function progressReport(e) {\r\n let progress = Math.min(100, e.loaded / e.total * 100 + 1);\r\n if (95 < progress)\r\n progress = 100;\r\n Dialog.setSaveProgress(true, progress, 100 == progress);\r\n }\r\n // user didn't choose a file, just go to the url\r\n if (!formData) {\r\n openUrl(url);\r\n return;\r\n }\r\n Dialog.disableButtons(true);\r\n window['sendToServer']('logo.text.translate', 'suffix=.js', formData, progressReport).then(statusReport);\r\n}\r\nfunction handleSidebarClick(e) {\r\n let thisHash = this.location;\r\n if (thisHash && thisHash.hash.startsWith('#open')) {\r\n new Dialog(undefined, thisHash.hash.substr(5)).showFilePicker('locLoadTitle', '.js', fileLoad, \"locLoadButton\");\r\n window.location.hash = '';\r\n return;\r\n }\r\n const mq = window.matchMedia(\"(max-width: 1024px)\");\r\n if (mq.matches) {\r\n if (!thisHash) {\r\n // overlay clicked\r\n window.location.hash = '';\r\n return;\r\n }\r\n if (thisHash.hash) {\r\n if (thisHash.hash != \"#commandcentre\" && thisHash.hash != \"#debug\")\r\n jQuery('#sidebar, #overlay').addClass('active');\r\n }\r\n else\r\n jQuery('#sidebar, #overlay').removeClass('active');\r\n }\r\n thisHash = thisHash.hash;\r\n if (thisHash && jQuery(thisHash).length) {\r\n trackEvent('Toggle' + thisHash);\r\n let parent = jQuery(thisHash).hasClass('flex') ? '#editor' : '#sidebar'; // depending on flex class will bite us\r\n jQuery('.active', parent).removeClass('active');\r\n jQuery(thisHash).addClass('active');\r\n jQuery('textarea', thisHash).focus();\r\n jQuery('a[href=\\'' + thisHash + '\\'] i', parent).addClass('active');\r\n }\r\n}\r\n// http://planetozh.com/blog/2008/04/javascript-basename-and-dirname/ except\r\n// the leading slash is optional to handle dirname('file.ext')\r\nfunction dirname(path) {\r\n return path.replace(/\\\\/g, '/').replace(/\\/?[^\\/]*$/, '');\r\n}\r\njQuery(window).on('hashchange', handleSidebarClick);\r\njQuery(window).trigger('hashchange');\r\njQuery('#overlay').click(handleSidebarClick);\r\njQuery('.sidebarCollapse').click(function () {\r\n if (this.getAttribute('href') == window.location.hash) {\r\n window.location.hash = '';\r\n return false;\r\n }\r\n});\r\nconst menuOverlay = document.getElementById(\"menuoverlay\");\r\nconst menuTargets = document.getElementsByClassName(\"menu\");\r\nconst submenuTargets = document.getElementsByClassName(\"submenu\");\r\nArray.prototype.forEach.call(menuTargets, function (element) {\r\n element.onclick = function (e) {\r\n e.stopPropagation();\r\n if (e.target.className.indexOf(\"separator\") > -1)\r\n return;\r\n donePopover();\r\n let v = element.className;\r\n if (v.indexOf(\"submenu\") > -1)\r\n removeClass(submenuTargets, \"open\");\r\n else {\r\n removeClass(menuTargets, \"open\");\r\n removeClass([menuOverlay], \"active\");\r\n }\r\n if (v.indexOf(\"open\") == -1) {\r\n addClass([element], \"open\");\r\n addClass([menuOverlay], \"active\");\r\n }\r\n };\r\n});\r\n// has to overwrite the default click on menuTargets\r\naddClick(fileShare, \"fileshare\");\r\nif (menuOverlay)\r\n menuOverlay.onclick = function () {\r\n removeClass(menuTargets, \"open\");\r\n removeClass([menuOverlay], \"active\");\r\n };\r\nconst projNameText = jQuery('div.prjname');\r\nconst projNameInput = jQuery('input.prjname');\r\nprojNameText.click(function () {\r\n projNameText.hide();\r\n projNameInput.show().focus();\r\n});\r\nprojNameInput.blur(function () {\r\n let oldName = jQuery('span:nth-child(1)', projNameText).text();\r\n if (oldName != projNameInput.val())\r\n window['needSave'](true);\r\n projNameInput.hide();\r\n projNameText.show();\r\n Dialog.setProjectTitle(projNameInput.val() || oldName);\r\n});\r\nfunction showToast(text, timeout = 400) {\r\n jQuery('.toast-body').text(text);\r\n jQuery('.toast').fadeToggle(timeout, function () {\r\n jQuery(this).fadeToggle('slow');\r\n });\r\n}\r\nconst hintActions = {\r\n 'next': '',\r\n 'or': '',\r\n 'done': '',\r\n 'last': '',\r\n 'never': '
',\r\n};\r\nvar disablePopover;\r\nfunction handleActionClick(e) {\r\n if (e) {\r\n if (e.isDefaultPrevented())\r\n return;\r\n e.preventDefault();\r\n }\r\n let act = this.dataset.hintAction;\r\n if (!act)\r\n return;\r\n donePopover();\r\n if (act == 'done')\r\n return;\r\n if (act == 'never') {\r\n setCookie('never-show-popover', 'true');\r\n const tut = jQuery('#tutorial');\r\n if (tut.length) // if we're hiding hints, while tutorial is shown (new users)\r\n try {\r\n const statusTutorial = JSON.parse(getCookie('tutorial_status'));\r\n // preserve the shown status of the tutorial\r\n statusTutorial.show = tut.hasClass('expand');\r\n setCookie('tutorial_status', JSON.stringify(statusTutorial), 604800); // copy from saveStatusTutorial in tutorial.js\r\n }\r\n catch (_a) {\r\n // looks like the cookie got corrupted, see load() in tutorial.js\r\n setCookie('tutorial_status', JSON.stringify({ show: tut.hasClass('expand'), sections: {}, current: -1 }), 604800);\r\n }\r\n return;\r\n }\r\n showPopover(1);\r\n}\r\n// copy is in Dialog\r\nfunction donePopover() {\r\n jQuery(`[data-hint-order=${window['hintCounter']}]`)['popover']('dispose');\r\n}\r\nfunction showPopover(inc = 0) {\r\n if (disablePopover)\r\n return;\r\n window['hintCounter'] = window['hintCounter'] + inc;\r\n let next = jQuery(`[data-hint-order=${window['hintCounter']}]`);\r\n if (!next.length) {\r\n // probably Tutorial button is removed, try the next one\r\n window['hintCounter'] += 1;\r\n next = jQuery(`[data-hint-order=${window['hintCounter']}]`);\r\n }\r\n let content = Dialog.localisableContent(next.data('content')) + '
';\r\n let actions = (next.data('hint-actions') || 'next').split(' ');\r\n for (const a of actions)\r\n content += hintActions[a];\r\n next.attr('data-content', content); // popover doesn't use \"data\", it uses the attr\r\n let offset = next.data('hint-offset');\r\n let alias = next.data('hint-alias');\r\n if (alias) {\r\n next = jQuery(alias)['popover']({\r\n content: content,\r\n placement: next.data('placement'),\r\n html: next.data('html'),\r\n trigger: 'manual',\r\n }).attr('data-hint-order', next.data('hint-order'));\r\n }\r\n else\r\n next = next['popover']({\r\n trigger: 'manual',\r\n });\r\n next.one('shown.bs.popover', function () {\r\n if (offset)\r\n jQuery('.popover .arrow').css({ left: offset });\r\n jQuery('.popover .popover-body a').one('click', handleActionClick);\r\n // shown popover adds \"title\", which prevents\r\n // parent's \"title\" to be used in a tooltip\r\n next.removeAttr(\"title\");\r\n });\r\n next['popover']('show');\r\n}\r\nfunction continueLoading() {\r\n window.loadProject();\r\n if (window.matchMedia(\"(min-width: 768px)\").matches && window.matchMedia(\"(min-height: 525px)\").matches)\r\n showPopover();\r\n}\r\nfunction loadTips() {\r\n var x = document.createElement(\"script\");\r\n // Play Project doesn't need tooltips\r\n x.onload = !window['samplesRoot'] ? continueLoading : () => {\r\n var y = document.createElement(\"script\");\r\n y.onload = continueLoading;\r\n y.onerror = continueLoading; // even if we could not load tips, keep loading the project\r\n y.src = window['samplesRoot'] + '/' + window['projectData'].compiler_lang + '.' + (window['projectData'].project_type || 'mwx') + '.tips.js?6';\r\n document.body.appendChild(y);\r\n };\r\n x.src = '/player/' + window['projectData'].compiler_lang + \"/primtips.js?v=10\";\r\n document.body.appendChild(x);\r\n}\r\nwindow.showToast = showToast;\r\nwindow.setProjectTitle = function (page) {\r\n Dialog.setProjectTitle(undefined, page);\r\n showToast(page);\r\n};\r\nwindow['auth'] = function (id, temp) {\r\n var url = `/upload/auth/${id}?popup&file=${encodeURIComponent(temp)}&title=${encodeURIComponent(projNameInput.val())}`;\r\n window['loginwindow'] = window.open(url, 'loginwindow', 'width=700,height=700', true);\r\n return false;\r\n};\r\nfunction updateProjectName(id, href, callback = (msg) => { }, cloudUndo = undefined) {\r\n let extra = {\r\n partial: true,\r\n name: jQuery('div.prjname span:nth-child(1)').text(),\r\n };\r\n window['projectData'].id = id;\r\n window['projectData'].root = PROJECT_ROOT + id;\r\n window['sendToServer'](`${window['projectData'].root}/meta`, '', extra).then(() => {\r\n window['needSave'](false);\r\n Dialog.setSaveProgress(true, 100);\r\n Dialog.closeFileSaver();\r\n if (href)\r\n if (href.startsWith('http'))\r\n window.location = href;\r\n else {\r\n history.replaceState(null, null, href);\r\n try {\r\n window['cloudUndo'] = JSON.parse(cloudUndo);\r\n }\r\n catch (e) {\r\n console.error(e);\r\n window['cloudUndo'] = undefined;\r\n }\r\n window['App'].getProject().initCloudUndo();\r\n }\r\n }, () => callback('Project data is saved. Non-criticial error occurred. Please try again.'));\r\n}\r\nwindow['continueSave'] = function (id, href) {\r\n if (window['loginwindow'])\r\n window['loginwindow'].close();\r\n if (href.indexOf('http') == 0) {\r\n window['needSave'](false);\r\n Dialog.setSaveProgress(true, 100);\r\n Dialog.closeFileSaver();\r\n window.location = href;\r\n }\r\n else {\r\n updateProjectName(id, href);\r\n }\r\n};\r\nlet name, projectsize = [800, 450];\r\nlet lang = '';\r\nlet searchParts = window.location.search.split(/[&?]/);\r\nfor (let i = 0; i < searchParts.length; i++) {\r\n let keyValue = searchParts[i].split('=');\r\n switch (keyValue[0]) {\r\n case '':\r\n break;\r\n case 'lang':\r\n lang = keyValue[1];\r\n break;\r\n case 'theme':\r\n case 'lang':\r\n case 'autocomplete':\r\n case 'font':\r\n case 'never-show-popover':\r\n document.cookie = keyValue[0] + '=' + keyValue[1] + ';path=/;expires=Mon, 01 Feb 2100 00:00:00 GMT';\r\n break;\r\n case 'name':\r\n name = decodeURIComponent(keyValue[1]);\r\n break;\r\n case 'projectsize':\r\n projectsize = JSON.parse(decodeURIComponent(keyValue[1]));\r\n break;\r\n default:\r\n continue;\r\n }\r\n searchParts.splice(i--, 1);\r\n}\r\nlet cookies = document.cookie.split('; ');\r\nlet learner = true;\r\nfor (let c of cookies) {\r\n let keyValue = c.split('=');\r\n if (keyValue[0] == 'theme' && keyValue[1].toUpperCase() == 'DARK') {\r\n jQuery('html').addClass('dark');\r\n jQuery('.changetheme i').addClass('fa-toggle-on');\r\n }\r\n else if (keyValue[0] == 'autocomplete') {\r\n autoCompleteCookie = false;\r\n jQuery('.changeautocomplete i').removeClass('fa-toggle-on');\r\n }\r\n else if (keyValue[0] == 'font') {\r\n toggleFont(keyValue[1]);\r\n }\r\n else if (keyValue[0] == 'learner') {\r\n learner = !!keyValue[1];\r\n }\r\n else if (keyValue[0] == 'never-show-popover')\r\n disablePopover = keyValue[1] == \"true\"; // see handleActionClick for hard-coded value\r\n}\r\njQuery(function () {\r\n let xhr = new XMLHttpRequest();\r\n xhr.open(\"GET\", window['projectUrl'], true);\r\n xhr.onprogress = function (e) {\r\n if (e.lengthComputable)\r\n jQuery('div.prjname span:nth-child(2)').text(Math.round(e.loaded / e.total * 100) + '%');\r\n };\r\n xhr.onload = function () {\r\n jQuery('div.prjname span:nth-child(2)').text('...');\r\n let data = JSON.parse(xhr.response);\r\n if (!data.projectsize) {\r\n data.projectsize = projectsize;\r\n let obj = data.pages[1].Object[0];\r\n if (obj) {\r\n obj.xpos = projectsize[0] / 2;\r\n obj.ypos = projectsize[1] / 2;\r\n }\r\n }\r\n data.id = window['projectId'];\r\n data.root = PROJECT_ROOT + data.id;\r\n window['projectData'] = data;\r\n loadTips();\r\n toggleLearner(learner);\r\n changeLanguage(lang);\r\n };\r\n xhr.onerror = function () {\r\n window.location.hash = 'open-notfound';\r\n };\r\n xhr.send();\r\n});\r\nconst voiceCache = {};\r\nwindow['playTip'] = function (path) {\r\n var audio = voiceCache[path];\r\n if (audio == path)\r\n voiceCache[path] = audio = new Audio(window['samplesRoot'] + path);\r\n audio.play();\r\n};\r\n","module.exports = \" \\r\\n \\r\\n\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
    \\r\\n
  • \\r\\n \\r\\n
  • \\r\\n
  • \\r\\n \\r\\n
  • \\r\\n
  • \\r\\n \\r\\n
  • \\r\\n
  • \\r\\n \\r\\n
  • \\r\\n
  • \\r\\n \\r\\n
  • \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
1 - 400
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
1 - 400
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n °\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
Modal title
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
 
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\"","import { Dialog } from \"./dialog\";\r\nexport class Shapes {\r\n constructor() {\r\n let shapes = document.getElementById(\"clipart\");\r\n for (let i = 1; i <= 128; i++) {\r\n let elem = document.createElement(\"div\");\r\n elem.setAttribute(\"class\", \"shape\");\r\n elem.setAttribute(\"id\", \"shape\" + i);\r\n elem.setAttribute(\"title\", \"\" + i);\r\n // https://stackoverflow.com/a/3656524\r\n elem.setAttribute(\"tabindex\", \"-1\");\r\n let del = document.createElement(\"i\");\r\n del.setAttribute(\"class\", \"delete fas fas-marker fa-trash-marker\");\r\n del.onclick = (e) => this.clearList(e);\r\n elem.appendChild(del);\r\n let ins = document.createElement(\"i\");\r\n ins.setAttribute(\"class\", \"insert fas fas-marker fa-plus-marker\");\r\n ins.onclick = this.insert;\r\n elem.appendChild(ins);\r\n let n = document.createElement(\"div\");\r\n n.setAttribute(\"class\", \"number\");\r\n n.innerText = \"\" + i;\r\n elem.appendChild(n);\r\n elem.oncontextmenu = (e) => this.editShape(e);\r\n let shp = window.App.getGlobalShapes().findByNumber(i);\r\n if (undefined !== shp)\r\n Shapes.displayShape(elem, shp.bitmap.dataURL);\r\n shapes.appendChild(elem);\r\n }\r\n jQuery(document).click(Shapes.clickShape);\r\n window.releaseShape = Shapes.clickShape;\r\n shapes.addEventListener('selectstart', function (e) { e.preventDefault(); });\r\n }\r\n loadSamples(data) {\r\n window.needSave(true);\r\n jQuery('.menu.open').removeClass('open');\r\n window.location.hash = 'clipart';\r\n jQuery('.shape:not(.exists)').each(function (i, elem) {\r\n let url = data[i];\r\n window.jswebplayer.setShapeByURL(url, Shapes.getShapeNumber(elem)).then((shape) => {\r\n Shapes.displayShape(elem, shape.url);\r\n }, () => {\r\n // the first argument indicates an error, but we can't do much about it\r\n });\r\n return i < data.length - 1;\r\n });\r\n }\r\n displayShape(elem, src) {\r\n Shapes.displayShape(elem, src);\r\n }\r\n paste(event) {\r\n let elem = document.activeElement;\r\n if (!elem.classList.contains('shape'))\r\n return;\r\n var items = (event.clipboardData || event.originalEvent.clipboardData).items;\r\n if (elem.id.match(/^shape[0-9]+$/)) {\r\n let shapeNumber = Shapes.getShapeNumber(elem);\r\n for (let i = 0; i < items.length; ++i) {\r\n if (items[i].kind == 'file' && items[i].type.indexOf('image/') !== -1) {\r\n event.preventDefault();\r\n let blob = items[i].getAsFile();\r\n window.URL = window.URL || window.webkitURL;\r\n let blobUrl = window.URL.createObjectURL(blob);\r\n window.jswebplayer.setShapeByURL(blobUrl, shapeNumber++).then(() => Shapes.displayShape(elem, blobUrl));\r\n window.needSave(true);\r\n }\r\n }\r\n }\r\n }\r\n clearList(e, elem) {\r\n let list;\r\n if (window.selectedShape) {\r\n list = window.selectedShape;\r\n if (list.length > 1) {\r\n Dialog.prompt([\r\n [Dialog.localisableContent('locNo'), function () { }],\r\n [Dialog.localisableContent('locYes'), deleteSelectedList],\r\n ], Dialog.localisableContent('locSureToDeleteClipart'));\r\n }\r\n else {\r\n this.clear(e, elem);\r\n }\r\n }\r\n else {\r\n this.clear(e, elem);\r\n }\r\n function deleteSelectedList() {\r\n let counter = 0;\r\n for (var i = 0; i < list.length; i++) {\r\n var elem = document.getElementById('shape' + list[i]);\r\n elem.setAttribute(\"class\", \"shape\");\r\n let old = elem.getElementsByTagName(\"img\");\r\n if (old.length)\r\n elem.removeChild(old[0]);\r\n counter += window.App.getGlobalShapes().clearShape(elem, Shapes.getShapeNumber(elem), counter == 0);\r\n }\r\n window.selectedShape = null;\r\n Shapes.clickShape(new Event('empty'));\r\n }\r\n }\r\n clear(e, elem) {\r\n if (!elem)\r\n elem = e.currentTarget.parentElement;\r\n elem.setAttribute(\"class\", \"shape\");\r\n let old = elem.getElementsByTagName(\"img\");\r\n if (old.length)\r\n elem.removeChild(old[0]);\r\n window.App.getGlobalShapes().clearShape(elem, Shapes.getShapeNumber(elem), e != undefined);\r\n Shapes.clickShape(new Event('empty'));\r\n }\r\n insert(e) {\r\n let elem = e.currentTarget;\r\n if (elem.id == '')\r\n elem = elem.parentElement;\r\n new Dialog().showFilePicker('locImportPicture', 'images', (url, ignore1, ignore2, close) => {\r\n Dialog.setSaveProgress(true, 100, true);\r\n window.jswebplayer.setShapeByURL(url, Shapes.getShapeNumber(elem)).then((shape) => {\r\n Shapes.displayShape(elem, shape.url);\r\n close();\r\n window.needSave(true);\r\n }).catch(err => {\r\n Dialog.setSaveAlert('locCannotImportPicture');\r\n Dialog.setSaveProgress(false, 100);\r\n });\r\n }, undefined, true);\r\n }\r\n editShape(e) {\r\n let elem = e.currentTarget;\r\n let glbshp = window.App.getGlobalShapes();\r\n let number = Shapes.getShapeNumber(elem);\r\n let shp = glbshp.findByNumber(number);\r\n if (shp === undefined)\r\n this.insert(e);\r\n else {\r\n const projectSize = { w: window.App.getProject().getWidth(), h: window.App.getProject().getHeight() };\r\n new Dialog(window.App).show(e, {\r\n type: 'shape',\r\n scale: true,\r\n width: shp.bitmap.width,\r\n height: shp.bitmap.height,\r\n ratio: shp.bitmap.width / shp.bitmap.height,\r\n projectSize,\r\n degrees: 0,\r\n name: shp.name,\r\n number: Dialog.localisableContent('locNumberSign') + shp.number,\r\n remove: () => this.clear(undefined, elem),\r\n apply: function (d) {\r\n glbshp.rename(shp, d.name);\r\n Shapes.displayShape(elem, glbshp.transform(shp, parseInt(d.width), parseInt(d.height), parseInt(d.degrees)));\r\n window.needSave(true);\r\n },\r\n checkApply: function (d) {\r\n const errors = [];\r\n if (parseFloat(d.name) || parseInt(d.name))\r\n errors.push('name');\r\n else if (shp.name != d.name && glbshp.findByName(d.name))\r\n errors.push('name');\r\n if (!Dialog.validSize('shapewidth', 1, Math.max(shp.bitmap.width, projectSize.w)))\r\n errors.push('width');\r\n if (!Dialog.validSize('shapeheight', 1, Math.max(shp.bitmap.height, projectSize.h)))\r\n errors.push('height');\r\n if (!Dialog.validSize('shapedegrees', -360, 360))\r\n errors.push('degrees');\r\n return errors.length ? errors : undefined;\r\n },\r\n });\r\n }\r\n return false;\r\n }\r\n static getShapeNumber(elem) {\r\n // 5 is the length of \"shape\" (see setAttribute(\"id\", ...) in the constructor)\r\n return +(elem === null || elem === void 0 ? void 0 : elem.id.substring(5));\r\n }\r\n static displayShape(elem, src) {\r\n if (\"undefined\" == typeof src)\r\n return;\r\n elem.setAttribute(\"class\", \"shape exists\");\r\n let old = elem.getElementsByTagName(\"img\");\r\n if (old.length)\r\n elem.removeChild(old[0]);\r\n let img = document.createElement(\"img\");\r\n img.src = src;\r\n if (src.substr(0, 5) == \"blob:\")\r\n img.onload = function () {\r\n window.URL.revokeObjectURL(img.src);\r\n };\r\n elem.insertBefore(img, elem.firstChild);\r\n }\r\n static clickShape(e) {\r\n let elem = e.target;\r\n if ((elem === null || elem === void 0 ? void 0 : elem.id) == 'overlay')\r\n return;\r\n let ctrlKey = e.ctrlKey || false;\r\n let shiftlKey = e.shiftKey || false;\r\n var v = Shapes.getShapeNumber(elem);\r\n if (!v) {\r\n // in case the image itself was clicked\r\n elem = elem === null || elem === void 0 ? void 0 : elem.parentElement;\r\n v = Shapes.getShapeNumber(elem);\r\n }\r\n if (window.selectedShape) {\r\n // if (ctrlKey) {\r\n // if ( typeof window.selectedShape == 'object' ) {\r\n // window.selectedShape.push(v);\r\n // }\r\n // else {\r\n // window.selectedShape = [window.selectedShape, v];\r\n // }\r\n // }\r\n if (shiftlKey) {\r\n if (typeof window.selectedShape == 'object') {\r\n if (window.selectedShape[0] > v) {\r\n for (let i = window.selectedShape[0] - 1; i >= v; i--)\r\n window.selectedShape.unshift(i);\r\n }\r\n else if (window.selectedShape[window.selectedShape.length - 1] < v) {\r\n for (let i = window.selectedShape[window.selectedShape.length - 1] + 1; i <= v; i++)\r\n window.selectedShape.push(i);\r\n }\r\n else {\r\n }\r\n }\r\n else {\r\n var v0 = window.selectedShape;\r\n window.selectedShape = [];\r\n if (v0 < v) {\r\n for (let i = v0; i <= v; i++)\r\n window.selectedShape.push(i);\r\n }\r\n else {\r\n for (let i = v; i <= v0; i++)\r\n window.selectedShape.push(i);\r\n }\r\n }\r\n }\r\n else {\r\n window.selectedShape = v;\r\n }\r\n }\r\n else {\r\n window.selectedShape = v;\r\n }\r\n $('#clipart').find('div.shape').each(function (index, elem) {\r\n var v = $(elem).attr('title');\r\n if (_find(v))\r\n $(elem).find('i.delete').show();\r\n else\r\n $(elem).find('i.delete').hide();\r\n });\r\n // \"exists\" is required because \"garbage bin\" has the \"right\" parent\r\n if (window.selectedShape && elem.classList.contains('exists')) {\r\n jQuery('body').css({ cursor: 'grabbing' });\r\n return;\r\n }\r\n window.selectedShape = 0; // in case the garbage bin was clicked\r\n jQuery('body').css({ cursor: 'unset' });\r\n function _find(v) {\r\n if (!window.selectedShape)\r\n return false;\r\n if (typeof window.selectedShape == 'object') {\r\n for (let j = 0; j < window.selectedShape.length; j++)\r\n if (window.selectedShape[j] == v)\r\n return true;\r\n return false;\r\n }\r\n else {\r\n return window.selectedShape == v;\r\n }\r\n }\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n Loading...\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
Attemt
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n\""],"sourceRoot":""}