diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..f6a1414a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,26 @@ +As with all Open Source software, contributions to Exerciser are welcome. + +An excellent way to contribute is testing and trying Exerciser to find some issues. If you find one, don't be shy; submit your issue [here](https://github.com/llaske/Exerciser/issues) by giving the maximum information on it and precisely detailed steps to reproduce it. We will check your issue and ask you for more information if needed. + +If you're a developer, the best way is to first [setup Exerciser](https://github.com/llaske/ExerciserReact#steps-to-run-project) and then also [setup Sugarizer](https://github.com/llaske/sugarizer/blob/dev/docs/tutorial/VanillaJS/step0.md). Testing the functionality requires using Sugarizer features like `Sharing the Exercise,` `Using Journals,` and many more need Exerciser to be deployed on Sugarizer. + +When you think you're ready, you could try to fix some current issues [here](https://github.com/llaske/Exerciser/issues). If you find a fix, send a Pull Request, and we will be pleased to review it. + + +So to send your Pull Request: + +* [ ] Clone this repository, +* [ ] Fork the **master** branch of your new repository, +* [ ] Update this new branch with your contribution and commit your changes, +* [ ] Send a pull request from your new branch to the dev branch of this repository. + +Few rules to respect when you fix an issue: + +* [ ] Ensure your pull request contains only updates related to the fix, +* [ ] Respect indentation of the original file, +* [ ] Mention the issue number in the pull request but not in the commit message + + +Please note there is no need to ask permission to work on an issue. You should check for pull requests linked to an issue you are addressing; if there are none, assume nobody has done anything. Begin to fix the problem, test, make your commits, push your commits, then make a pull request. These practices allow the competition of ideas and give priority to meritocracy. + +Thanks in advance for your contribution, and become a member of the Exerciser community! \ No newline at end of file diff --git a/LICENSE b/LICENSE index 261eeb9e..d6456956 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,4 @@ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000..657b7a24 --- /dev/null +++ b/NOTICE @@ -0,0 +1,13 @@ +Copyright 2018 Mankirat Singh and Avinash Agarwal + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/config-overrides.js b/config-overrides.js new file mode 100644 index 00000000..df49ff64 --- /dev/null +++ b/config-overrides.js @@ -0,0 +1,18 @@ +const CopyWebpackPlugin = require('copy-webpack-plugin'); + +module.exports = function override(config, env) { + let resolvePlugin = (config.resolveLoader ? config.resolveLoader : {}); + resolvePlugin['alias'] = { + 'text': 'text-loader' + }; + config['resolveLoader'] = resolvePlugin; + + let resolvePath = config.resolve.alias; + resolvePath['webL10n'] = 'lib/webL10n'; + resolvePath['sugar-web'] = 'lib/sugar-web'; + resolvePath['mustache'] = 'lib/mustache'; + resolvePath['picoModal'] = 'lib/picoModal'; + config.resolve.alias = resolvePath; + + return config; +} \ No newline at end of file diff --git a/lib/humane.js b/lib/humane.js new file mode 100644 index 00000000..0764b4a4 --- /dev/null +++ b/lib/humane.js @@ -0,0 +1,240 @@ +/** + * humane.js + * Humanized Messages for Notifications + * @author Marc Harter (@wavded) + * @example + * humane.log('hello world'); + * @license MIT + * See more usage examples at: http://wavded.github.com/humane-js/ + */ + +;!function (name, context, definition) { + // HACK: Force loading with define to avoid loading issue in Electron + //if (typeof module !== 'undefined') module.exports = definition(name, context) + //else if (typeof define === 'function' && typeof define.amd === 'object') define(definition) + //else context[name] = definition(name, context) + define(definition); +}('humane', this, function (name, context) { + var win = window + var doc = document + + var ENV = { + on: function (el, type, cb) { + 'addEventListener' in win ? el.addEventListener(type,cb,false) : el.attachEvent('on'+type,cb) + }, + off: function (el, type, cb) { + 'removeEventListener' in win ? el.removeEventListener(type,cb,false) : el.detachEvent('on'+type,cb) + }, + bind: function (fn, ctx) { + return function () { fn.apply(ctx,arguments) } + }, + isArray: Array.isArray || function (obj) { return Object.prototype.toString.call(obj) === '[object Array]' }, + config: function (preferred, fallback) { + return preferred != null ? preferred : fallback + }, + transSupport: false, + useFilter: /msie [678]/i.test(navigator.userAgent), // sniff, sniff + _checkTransition: function () { + var el = doc.createElement('div') + var vendors = { webkit: 'webkit', Moz: '', O: 'o', ms: 'MS' } + + for (var vendor in vendors) + if (vendor + 'Transition' in el.style) { + this.vendorPrefix = vendors[vendor] + this.transSupport = true + } + } + } + ENV._checkTransition() + + var Humane = function (o) { + o || (o = {}) + this.queue = [] + this.baseCls = o.baseCls || 'humane' + this.addnCls = o.addnCls || '' + this.timeout = 'timeout' in o ? o.timeout : 2500 + this.waitForMove = o.waitForMove || false + this.clickToClose = o.clickToClose || false + this.timeoutAfterMove = o.timeoutAfterMove || false + this.container = o.container + + try { this._setupEl() } // attempt to setup elements + catch (e) { + ENV.on(win,'load',ENV.bind(this._setupEl, this)) // dom wasn't ready, wait till ready + } + } + + Humane.prototype = { + constructor: Humane, + _setupEl: function () { + var el = doc.createElement('div') + el.style.display = 'none' + if (!this.container){ + if(doc.body) this.container = doc.body; + else throw 'document.body is null' + } + this.container.appendChild(el) + this.el = el + this.removeEvent = ENV.bind(function(){ + var timeoutAfterMove = ENV.config(this.currentMsg.timeoutAfterMove,this.timeoutAfterMove) + if (!timeoutAfterMove){ + this.remove() + } else { + setTimeout(ENV.bind(this.remove,this),timeoutAfterMove) + } + },this) + + this.transEvent = ENV.bind(this._afterAnimation,this) + this._run() + }, + _afterTimeout: function () { + if (!ENV.config(this.currentMsg.waitForMove,this.waitForMove)) this.remove() + + else if (!this.removeEventsSet) { + ENV.on(doc.body,'mousemove',this.removeEvent) + ENV.on(doc.body,'click',this.removeEvent) + ENV.on(doc.body,'keypress',this.removeEvent) + ENV.on(doc.body,'touchstart',this.removeEvent) + this.removeEventsSet = true + } + }, + _run: function () { + if (this._animating || !this.queue.length || !this.el) return + + this._animating = true + if (this.currentTimer) { + clearTimeout(this.currentTimer) + this.currentTimer = null + } + + var msg = this.queue.shift() + var clickToClose = ENV.config(msg.clickToClose,this.clickToClose) + + if (clickToClose) { + ENV.on(this.el,'click',this.removeEvent) + ENV.on(this.el,'touchstart',this.removeEvent) + } + + var timeout = ENV.config(msg.timeout,this.timeout) + + if (timeout > 0) + this.currentTimer = setTimeout(ENV.bind(this._afterTimeout,this), timeout) + + if (ENV.isArray(msg.html)) msg.html = '' + + this.el.innerHTML = msg.html + this.currentMsg = msg + this.el.className = this.baseCls + if (ENV.transSupport) { + this.el.style.display = 'block' + setTimeout(ENV.bind(this._showMsg,this),50) + } else { + this._showMsg() + } + + }, + _setOpacity: function (opacity) { + if (ENV.useFilter){ + try{ + this.el.filters.item('DXImageTransform.Microsoft.Alpha').Opacity = opacity*100 + } catch(err){} + } else { + this.el.style.opacity = String(opacity) + } + }, + _showMsg: function () { + var addnCls = ENV.config(this.currentMsg.addnCls,this.addnCls) + if (ENV.transSupport) { + this.el.className = this.baseCls+' '+addnCls+' '+this.baseCls+'-animate' + } + else { + var opacity = 0 + this.el.className = this.baseCls+' '+addnCls+' '+this.baseCls+'-js-animate' + this._setOpacity(0) // reset value so hover states work + this.el.style.display = 'block' + + var self = this + var interval = setInterval(function(){ + if (opacity < 1) { + opacity += 0.1 + if (opacity > 1) opacity = 1 + self._setOpacity(opacity) + } + else clearInterval(interval) + }, 30) + } + }, + _hideMsg: function () { + var addnCls = ENV.config(this.currentMsg.addnCls,this.addnCls) + if (ENV.transSupport) { + this.el.className = this.baseCls+' '+addnCls + ENV.on(this.el,ENV.vendorPrefix ? ENV.vendorPrefix+'TransitionEnd' : 'transitionend',this.transEvent) + } + else { + var opacity = 1 + var self = this + var interval = setInterval(function(){ + if(opacity > 0) { + opacity -= 0.1 + if (opacity < 0) opacity = 0 + self._setOpacity(opacity); + } + else { + self.el.className = self.baseCls+' '+addnCls + clearInterval(interval) + self._afterAnimation() + } + }, 30) + } + }, + _afterAnimation: function () { + if (ENV.transSupport) ENV.off(this.el,ENV.vendorPrefix ? ENV.vendorPrefix+'TransitionEnd' : 'transitionend',this.transEvent) + + if (this.currentMsg.cb) this.currentMsg.cb() + this.el.style.display = 'none' + + this._animating = false + this._run() + }, + remove: function (e) { + var cb = typeof e == 'function' ? e : null + + ENV.off(doc.body,'mousemove',this.removeEvent) + ENV.off(doc.body,'click',this.removeEvent) + ENV.off(doc.body,'keypress',this.removeEvent) + ENV.off(doc.body,'touchstart',this.removeEvent) + ENV.off(this.el,'click',this.removeEvent) + ENV.off(this.el,'touchstart',this.removeEvent) + this.removeEventsSet = false + + if (cb && this.currentMsg) this.currentMsg.cb = cb + if (this._animating) this._hideMsg() + else if (cb) cb() + }, + log: function (html, o, cb, defaults) { + var msg = {} + if (defaults) + for (var opt in defaults) + msg[opt] = defaults[opt] + + if (typeof o == 'function') cb = o + else if (o) + for (var opt in o) msg[opt] = o[opt] + + msg.html = html + if (cb) msg.cb = cb + this.queue.push(msg) + this._run() + return this + }, + spawn: function (defaults) { + var self = this + return function (html, o, cb) { + self.log.call(self,html,o,cb,defaults) + return self + } + }, + create: function (o) { return new Humane(o) } + } + return new Humane() +}); diff --git a/lib/mustache.js b/lib/mustache.js new file mode 100644 index 00000000..932052b4 --- /dev/null +++ b/lib/mustache.js @@ -0,0 +1,610 @@ +/*! + * mustache.js - Logic-less {{mustache}} templates with JavaScript + * http://github.com/janl/mustache.js + */ + +/*global define: false*/ + +(function (root, factory) { + if (typeof exports === "object" && exports) { + module.exports = factory; // CommonJS + } else if (typeof define === "function" && define.amd) { + define(factory); // AMD + } else { + root.Mustache = factory; //