', {text: text}); }
+ }
+ },
+
+ functionAttributes: ['beforeOpen', 'afterOpen', 'beforeContent', 'afterContent', 'beforeClose', 'afterClose'],
+
+ /*** class methods ***/
+ /* read element's attributes starting with data-featherlight- */
+ readElementConfig: function(element, namespace) {
+ var Klass = this,
+ regexp = new RegExp('^data-' + namespace + '-(.*)'),
+ config = {};
+ if (element && element.attributes) {
+ $.each(element.attributes, function(){
+ var match = this.name.match(regexp);
+ if (match) {
+ var val = this.value,
+ name = $.camelCase(match[1]);
+ if ($.inArray(name, Klass.functionAttributes) >= 0) { /* jshint -W054 */
+ val = new Function(val); /* jshint +W054 */
+ } else {
+ try { val = JSON.parse(val); }
+ catch(e) {}
+ }
+ config[name] = val;
+ }
+ });
+ }
+ return config;
+ },
+
+ /* Used to create a Featherlight extension
+ [Warning: guru-level]
+ Creates the extension's prototype that in turn
+ inherits Featherlight's prototype.
+ Could be used to extend an extension too...
+ This is pretty high level wizardy, it comes pretty much straight
+ from CoffeeScript and won't teach you anything about Featherlight
+ as it's not really specific to this library.
+ My suggestion: move along and keep your sanity.
+ */
+ extend: function(child, defaults) {
+ /* Setup class hierarchy, adapted from CoffeeScript */
+ var Ctor = function(){ this.constructor = child; };
+ Ctor.prototype = this.prototype;
+ child.prototype = new Ctor();
+ child.__super__ = this.prototype;
+ /* Copy class methods & attributes */
+ $.extend(child, this, defaults);
+ child.defaults = child.prototype;
+ return child;
+ },
+
+ attach: function($source, $content, config) {
+ var Klass = this;
+ if (typeof $content === 'object' && $content instanceof $ === false && !config) {
+ config = $content;
+ $content = undefined;
+ }
+ /* make a copy */
+ config = $.extend({}, config);
+
+ /* Only for openTrigger, filter & namespace... */
+ var namespace = config.namespace || Klass.defaults.namespace,
+ tempConfig = $.extend({}, Klass.defaults, Klass.readElementConfig($source[0], namespace), config),
+ sharedPersist;
+ var handler = function(event) {
+ var $target = $(event.currentTarget);
+ /* ... since we might as well compute the config on the actual target */
+ var elemConfig = $.extend(
+ {$source: $source, $currentTarget: $target},
+ Klass.readElementConfig($source[0], tempConfig.namespace),
+ Klass.readElementConfig(event.currentTarget, tempConfig.namespace),
+ config);
+ var fl = sharedPersist || $target.data('featherlight-persisted') || new Klass($content, elemConfig);
+ if(fl.persist === 'shared') {
+ sharedPersist = fl;
+ } else if(fl.persist !== false) {
+ $target.data('featherlight-persisted', fl);
+ }
+ if (elemConfig.$currentTarget.blur) {
+ elemConfig.$currentTarget.blur(); // Otherwise 'enter' key might trigger the dialog again
+ }
+ fl.open(event);
+ };
+
+ $source.on(tempConfig.openTrigger+'.'+tempConfig.namespace, tempConfig.filter, handler);
+
+ return {filter: tempConfig.filter, handler: handler};
+ },
+
+ current: function() {
+ var all = this.opened();
+ return all[all.length - 1] || null;
+ },
+
+ opened: function() {
+ var klass = this;
+ pruneOpened();
+ return $.grep(opened, function(fl) { return fl instanceof klass; } );
+ },
+
+ close: function(event) {
+ var cur = this.current();
+ if(cur) { return cur.close(event); }
+ },
+
+ /* Does the auto binding on startup.
+ Meant only to be used by Featherlight and its extensions
+ */
+ _onReady: function() {
+ var Klass = this;
+ if(Klass.autoBind){
+ var $autobound = $(Klass.autoBind);
+ /* Bind existing elements */
+ $autobound.each(function(){
+ Klass.attach($(this));
+ });
+ /* If a click propagates to the document level, then we have an item that was added later on */
+ $(document).on('click', Klass.autoBind, function(evt) {
+ if (evt.isDefaultPrevented()) {
+ return;
+ }
+ var $cur = $(evt.currentTarget);
+ var len = $autobound.length;
+ $autobound = $autobound.add($cur);
+ if(len === $autobound.length) {
+ return; /* already bound */
+ }
+ /* Bind featherlight */
+ var data = Klass.attach($cur);
+ /* Dispatch event directly */
+ if (!data.filter || $(evt.target).parentsUntil($cur, data.filter).length > 0) {
+ data.handler(evt);
+ }
+ });
+ }
+ },
+
+ /* Featherlight uses the onKeyUp callback to intercept the escape key.
+ Private to Featherlight.
+ */
+ _callbackChain: {
+ onKeyUp: function(_super, event){
+ if(27 === event.keyCode) {
+ if (this.closeOnEsc) {
+ $.featherlight.close(event);
+ }
+ return false;
+ } else {
+ return _super(event);
+ }
+ },
+
+ beforeOpen: function(_super, event) {
+ // Used to disable scrolling
+ $(document.documentElement).addClass('with-featherlight');
+
+ // Remember focus:
+ this._previouslyActive = document.activeElement;
+
+ // Disable tabbing:
+ // See http://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus
+ this._$previouslyTabbable = $("a, input, select, textarea, iframe, button, iframe, [contentEditable=true]")
+ .not('[tabindex]')
+ .not(this.$instance.find('button'));
+
+ this._$previouslyWithTabIndex = $('[tabindex]').not('[tabindex="-1"]');
+ this._previousWithTabIndices = this._$previouslyWithTabIndex.map(function(_i, elem) {
+ return $(elem).attr('tabindex');
+ });
+
+ this._$previouslyWithTabIndex.add(this._$previouslyTabbable).attr('tabindex', -1);
+
+ if (document.activeElement.blur) {
+ document.activeElement.blur();
+ }
+ return _super(event);
+ },
+
+ afterClose: function(_super, event) {
+ var r = _super(event);
+ // Restore focus
+ var self = this;
+ this._$previouslyTabbable.removeAttr('tabindex');
+ this._$previouslyWithTabIndex.each(function(i, elem) {
+ $(elem).attr('tabindex', self._previousWithTabIndices[i]);
+ });
+ this._previouslyActive.focus();
+ // Restore scroll
+ if(Featherlight.opened().length === 0) {
+ $(document.documentElement).removeClass('with-featherlight');
+ }
+ return r;
+ },
+
+ onResize: function(_super, event){
+ this.resize(this.$content.naturalWidth, this.$content.naturalHeight);
+ return _super(event);
+ },
+
+ afterContent: function(_super, event){
+ var r = _super(event);
+ this.$instance.find('[autofocus]:not([disabled])').focus();
+ this.onResize(event);
+ return r;
+ }
+ }
+ });
+
+ $.featherlight = Featherlight;
+
+ /* bind jQuery elements to trigger featherlight */
+ $.fn.featherlight = function($content, config) {
+ Featherlight.attach(this, $content, config);
+ return this;
+ };
+
+ /* bind featherlight on ready if config autoBind is set */
+ $(document).ready(function(){ Featherlight._onReady(); });
+});
\ No newline at end of file
diff --git a/js/gcodeprocessing.js b/js/gcodeprocessing.js
new file mode 100644
index 0000000..4f7d4b1
--- /dev/null
+++ b/js/gcodeprocessing.js
@@ -0,0 +1,60 @@
+function downloadFile(filename, contents) {
+ var blob = new Blob([contents], {type: 'text/plain'});
+ if (window.navigator && window.navigator.msSaveOrOpenBlob) {
+ window.navigator.msSaveOrOpenBlob(blob, filename);
+ } else{
+ var e = document.createEvent('MouseEvents'),
+ a = document.createElement('a');
+ a.download = filename;
+ a.href = window.URL.createObjectURL(blob);
+ a.dataset.downloadurl = ['text/plain', a.download, a.href].join(':');
+ e.initEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ a.dispatchEvent(e);
+ }
+}
+
+function processBaseline(){
+ var hotendTemp = document.baselineForm.hotendtemp.value;
+ var bedTemp = document.baselineForm.bedtemp.value;
+ var bedX = Math.round((document.baselineForm.bedx.value-100)/2);
+ var bedY = Math.round((document.baselineForm.bedy.value-100)/2);
+ var retDist = document.baselineForm.retdist.value;
+ var retSpeed = document.baselineForm.retspeed.value*60;
+ var abl = document.baselineForm.abl.value;
+ var baseline = originalBaseline;
+ if(abl == 1){
+ baseline = baseline.replace(/;G29 ; probe ABL/, "G29 ; probe ABL");
+ }
+ if(abl == 2){
+ baseline = baseline.replace(/;M420 S1 ; restore ABL mesh/, "M420 S1 ; restore ABL mesh");
+ }
+ baseline = baseline.replace(/M140 S60/g, "M140 S"+bedTemp);
+ baseline = baseline.replace(/M190 S60/g, "M140 S"+bedTemp);
+ baseline = baseline.replace(/M104 S210/g, "M104 S"+hotendTemp);
+ baseline = baseline.replace(/M109 S210/g, "M109 S"+hotendTemp);
+ baseline = baseline.replace(/G1 E-5.0000 F2400/g, "G1 E-"+retDist+" F"+retSpeed);
+ baseline = baseline.replace(/G1 E0.0000 F2400/g, "G1 E0.0000 F"+retSpeed);
+
+ if(bedX > 0){
+ var baselineArray = baseline.split(/\n/g);
+ baselineArray.forEach(function(index, item){
+ if(baselineArray[item].search(/X/) > -1){
+ var value = parseInt(baselineArray[item].match(/X\d+/)[0].substring(1)) + bedX
+ baselineArray[item] = baselineArray[item].replace(/X\d+/, "X"+String(value));
+ }
+ });
+ baseline = baselineArray.join("\n");
+ }
+ if(bedY > 0){
+ var baselineArray = baseline.split(/\n/g);
+ baselineArray.forEach(function(index, item){
+ if(baselineArray[item].search(/Y/) > -1){
+ var value = parseInt(baselineArray[item].match(/Y\d+/)[0].substring(1)) + bedY
+ baselineArray[item] = baselineArray[item].replace(/Y\d+/, "Y"+String(value))
+ }
+ });
+ baseline = baselineArray.join("\n");
+ }
+ downloadFile('baseline.gcode', baseline);
+}
+
diff --git a/js/jquery.responsiveTabs.js b/js/jquery.responsiveTabs.js
new file mode 100644
index 0000000..e807f74
--- /dev/null
+++ b/js/jquery.responsiveTabs.js
@@ -0,0 +1,704 @@
+;(function ( $, window, undefined ) {
+
+ /** Default settings */
+ var defaults = {
+ active: null,
+ event: 'click',
+ disabled: [],
+ collapsible: 'accordion',
+ startCollapsed: false,
+ rotate: false,
+ setHash: false,
+ animation: 'default',
+ animationQueue: false,
+ duration: 500,
+ fluidHeight: true,
+ scrollToAccordion: false,
+ scrollToAccordionOnLoad: true,
+ scrollToAccordionOffset: 0,
+ accordionTabElement: '
',
+ navigationContainer: '',
+ click: function(){},
+ activate: function(){},
+ deactivate: function(){},
+ load: function(){},
+ activateState: function(){},
+ classes: {
+ stateDefault: 'r-tabs-state-default',
+ stateActive: 'r-tabs-state-active',
+ stateDisabled: 'r-tabs-state-disabled',
+ stateExcluded: 'r-tabs-state-excluded',
+ container: 'r-tabs',
+ ul: 'r-tabs-nav',
+ tab: 'r-tabs-tab',
+ anchor: 'r-tabs-anchor',
+ panel: 'r-tabs-panel',
+ accordionTitle: 'r-tabs-accordion-title'
+ }
+ };
+
+ /**
+ * Responsive Tabs
+ * @constructor
+ * @param {object} element - The HTML element the validator should be bound to
+ * @param {object} options - An option map
+ */
+ function ResponsiveTabs(element, options) {
+ this.element = element; // Selected DOM element
+ this.$element = $(element); // Selected jQuery element
+
+ this.tabs = []; // Create tabs array
+ this.state = ''; // Define the plugin state (tabs/accordion)
+ this.rotateInterval = 0; // Define rotate interval
+ this.$queue = $({});
+
+ // Extend the defaults with the passed options
+ this.options = $.extend( {}, defaults, options);
+
+ this.init();
+ }
+
+
+ /**
+ * This function initializes the tab plugin
+ */
+ ResponsiveTabs.prototype.init = function () {
+ var _this = this;
+
+ // Load all the elements
+ this.tabs = this._loadElements();
+ this._loadClasses();
+ this._loadEvents();
+
+ // Window resize bind to check state
+ $(window).on('resize', function(e) {
+ _this._setState(e);
+ if(_this.options.fluidHeight !== true) {
+ _this._equaliseHeights();
+ }
+ });
+
+ // Hashchange event
+ $(window).on('hashchange', function(e) {
+ var tabRef = _this._getTabRefBySelector(window.location.hash);
+ var oTab = _this._getTab(tabRef);
+
+ // Check if a tab is found that matches the hash
+ if(tabRef >= 0 && !oTab._ignoreHashChange && !oTab.disabled) {
+ // If so, open the tab and auto close the current one
+ _this._openTab(e, _this._getTab(tabRef), true);
+ }
+ });
+
+ // Start rotate event if rotate option is defined
+ if(this.options.rotate !== false) {
+ this.startRotation();
+ }
+
+ // Set fluid height
+ if(this.options.fluidHeight !== true) {
+ _this._equaliseHeights();
+ }
+
+ // --------------------
+ // Define plugin events
+ //
+
+ // Activate: this event is called when a tab is selected
+ this.$element.bind('tabs-click', function(e, oTab) {
+ _this.options.click.call(this, e, oTab);
+ });
+
+ // Activate: this event is called when a tab is selected
+ this.$element.bind('tabs-activate', function(e, oTab) {
+ _this.options.activate.call(this, e, oTab);
+ });
+ // Deactivate: this event is called when a tab is closed
+ this.$element.bind('tabs-deactivate', function(e, oTab) {
+ _this.options.deactivate.call(this, e, oTab);
+ });
+ // Activate State: this event is called when the plugin switches states
+ this.$element.bind('tabs-activate-state', function(e, state) {
+ _this.options.activateState.call(this, e, state);
+ });
+
+ // Load: this event is called when the plugin has been loaded
+ this.$element.bind('tabs-load', function(e) {
+ var startTab;
+
+ _this._setState(e); // Set state
+
+ // Check if the panel should be collaped on load
+ if(_this.options.startCollapsed !== true && !(_this.options.startCollapsed === 'accordion' && _this.state === 'accordion')) {
+
+ startTab = _this._getStartTab();
+
+ // Open the initial tab
+ _this._openTab(e, startTab); // Open first tab
+
+ // Call the callback function
+ _this.options.load.call(this, e, startTab); // Call the load callback
+ }
+ });
+ // Trigger loaded event
+ this.$element.trigger('tabs-load');
+ };
+
+ //
+ // PRIVATE FUNCTIONS
+ //
+
+ /**
+ * This function loads the tab elements and stores them in an array
+ * @returns {Array} Array of tab elements
+ */
+ ResponsiveTabs.prototype._loadElements = function() {
+ var _this = this;
+ var $ul = (_this.options.navigationContainer === '') ? this.$element.children('ul:first') : this.$element.find(_this.options.navigationContainer).children('ul:first');
+ var tabs = [];
+ var id = 0;
+
+ // Add the classes to the basic html elements
+ this.$element.addClass(_this.options.classes.container); // Tab container
+ $ul.addClass(_this.options.classes.ul); // List container
+
+ // Get tab buttons and store their data in an array
+ $('li', $ul).each(function() {
+ var $tab = $(this);
+ var isExcluded = $tab.hasClass(_this.options.classes.stateExcluded);
+ var $anchor, $panel, $accordionTab, $accordionAnchor, panelSelector;
+
+ // Check if the tab should be excluded
+ if(!isExcluded) {
+
+ $anchor = $('a', $tab);
+ panelSelector = $anchor.attr('href');
+ $panel = $(panelSelector);
+ $accordionTab = $(_this.options.accordionTabElement).insertBefore($panel);
+ $accordionAnchor = $('
').attr('href', panelSelector).html($anchor.html()).appendTo($accordionTab);
+
+ var oTab = {
+ _ignoreHashChange: false,
+ id: id,
+ disabled: ($.inArray(id, _this.options.disabled) !== -1),
+ tab: $(this),
+ anchor: $('a', $tab),
+ panel: $panel,
+ selector: panelSelector,
+ accordionTab: $accordionTab,
+ accordionAnchor: $accordionAnchor,
+ active: false
+ };
+
+ // 1up the ID
+ id++;
+ // Add to tab array
+ tabs.push(oTab);
+ }
+ });
+ return tabs;
+ };
+
+
+ /**
+ * This function adds classes to the tab elements based on the options
+ */
+ ResponsiveTabs.prototype._loadClasses = function() {
+ for (var i=0; i
= 0 && !this._getTab(tabRef).disabled) {
+ // If so, set the current tab to the linked tab
+ startTab = this._getTab(tabRef);
+ } else if(this.options.active > 0 && !this._getTab(this.options.active).disabled) {
+ startTab = this._getTab(this.options.active);
+ } else {
+ // If not, just get the first one
+ startTab = this._getTab(0);
+ }
+
+ return startTab;
+ };
+
+ /**
+ * This function sets the current state of the plugin
+ * @param {Event} e - The event that triggers the state change
+ */
+ ResponsiveTabs.prototype._setState = function(e) {
+ var $ul = $('ul:first', this.$element);
+ var oldState = this.state;
+ var startCollapsedIsState = (typeof this.options.startCollapsed === 'string');
+ var startTab;
+
+ // The state is based on the visibility of the tabs list
+ if($ul.is(':visible')){
+ // Tab list is visible, so the state is 'tabs'
+ this.state = 'tabs';
+ } else {
+ // Tab list is invisible, so the state is 'accordion'
+ this.state = 'accordion';
+ }
+
+ // If the new state is different from the old state
+ if(this.state !== oldState) {
+ // If so, the state activate trigger must be called
+ this.$element.trigger('tabs-activate-state', {oldState: oldState, newState: this.state});
+
+ // Check if the state switch should open a tab
+ if(oldState && startCollapsedIsState && this.options.startCollapsed !== this.state && this._getCurrentTab() === undefined) {
+ // Get initial tab
+ startTab = this._getStartTab(e);
+ // Open the initial tab
+ this._openTab(e, startTab); // Open first tab
+ }
+ }
+ };
+
+ /**
+ * This function opens a tab
+ * @param {Event} e - The event that triggers the tab opening
+ * @param {Object} oTab - The tab object that should be opened
+ * @param {Boolean} closeCurrent - Defines if the current tab should be closed
+ * @param {Boolean} stopRotation - Defines if the tab rotation loop should be stopped
+ */
+ ResponsiveTabs.prototype._openTab = function(e, oTab, closeCurrent, stopRotation) {
+ var _this = this;
+ var scrollOffset;
+
+ // Check if the current tab has to be closed
+ if(closeCurrent) {
+ this._closeTab(e, this._getCurrentTab());
+ }
+
+ // Check if the rotation has to be stopped when activated
+ if(stopRotation && this.rotateInterval > 0) {
+ this.stopRotation();
+ }
+
+ // Set this tab to active
+ oTab.active = true;
+ // Set active classes to the tab button and accordion tab button
+ oTab.tab.removeClass(_this.options.classes.stateDefault).addClass(_this.options.classes.stateActive);
+ oTab.accordionTab.removeClass(_this.options.classes.stateDefault).addClass(_this.options.classes.stateActive);
+
+ // Run panel transiton
+ _this._doTransition(oTab.panel, _this.options.animation, 'open', function() {
+ var scrollOnLoad = (e.type !== 'tabs-load' || _this.options.scrollToAccordionOnLoad);
+
+ // When finished, set active class to the panel
+ oTab.panel.removeClass(_this.options.classes.stateDefault).addClass(_this.options.classes.stateActive);
+
+ // And if enabled and state is accordion, scroll to the accordion tab
+ if(_this.getState() === 'accordion' && _this.options.scrollToAccordion && (!_this._isInView(oTab.accordionTab) || _this.options.animation !== 'default') && scrollOnLoad) {
+
+ // Add offset element's height to scroll position
+ scrollOffset = oTab.accordionTab.offset().top - _this.options.scrollToAccordionOffset;
+
+ // Check if the animation option is enabled, and if the duration isn't 0
+ if(_this.options.animation !== 'default' && _this.options.duration > 0) {
+ // If so, set scrollTop with animate and use the 'animation' duration
+ $('html, body').animate({
+ scrollTop: scrollOffset
+ }, _this.options.duration);
+ } else {
+ // If not, just set scrollTop
+ $('html, body').scrollTop(scrollOffset);
+ }
+ }
+ });
+
+ this.$element.trigger('tabs-activate', oTab);
+ };
+
+ /**
+ * This function closes a tab
+ * @param {Event} e - The event that is triggered when a tab is closed
+ * @param {Object} oTab - The tab object that should be closed
+ */
+ ResponsiveTabs.prototype._closeTab = function(e, oTab) {
+ var _this = this;
+ var doQueueOnState = typeof _this.options.animationQueue === 'string';
+ var doQueue;
+
+ if(oTab !== undefined) {
+ if(doQueueOnState && _this.getState() === _this.options.animationQueue) {
+ doQueue = true;
+ } else if(doQueueOnState) {
+ doQueue = false;
+ } else {
+ doQueue = _this.options.animationQueue;
+ }
+
+ // Deactivate tab
+ oTab.active = false;
+ // Set default class to the tab button
+ oTab.tab.removeClass(_this.options.classes.stateActive).addClass(_this.options.classes.stateDefault);
+
+ // Run panel transition
+ _this._doTransition(oTab.panel, _this.options.animation, 'close', function() {
+ // Set default class to the accordion tab button and tab panel
+ oTab.accordionTab.removeClass(_this.options.classes.stateActive).addClass(_this.options.classes.stateDefault);
+ oTab.panel.removeClass(_this.options.classes.stateActive).addClass(_this.options.classes.stateDefault);
+ }, !doQueue);
+
+ this.$element.trigger('tabs-deactivate', oTab);
+ }
+ };
+
+ /**
+ * This function runs an effect on a panel
+ * @param {Element} panel - The HTML element of the tab panel
+ * @param {String} method - The transition method reference
+ * @param {String} state - The state (open/closed) that the panel should transition to
+ * @param {Function} callback - The callback function that is called after the transition
+ * @param {Boolean} dequeue - Defines if the event queue should be dequeued after the transition
+ */
+ ResponsiveTabs.prototype._doTransition = function(panel, method, state, callback, dequeue) {
+ var effect;
+ var _this = this;
+
+ // Get effect based on method
+ switch(method) {
+ case 'slide':
+ effect = (state === 'open') ? 'slideDown' : 'slideUp';
+ break;
+ case 'fade':
+ effect = (state === 'open') ? 'fadeIn' : 'fadeOut';
+ break;
+ default:
+ effect = (state === 'open') ? 'show' : 'hide';
+ // When default is used, set the duration to 0
+ _this.options.duration = 0;
+ break;
+ }
+
+ // Add the transition to a custom queue
+ this.$queue.queue('responsive-tabs',function(next){
+ // Run the transition on the panel
+ panel[effect]({
+ duration: _this.options.duration,
+ complete: function() {
+ // Call the callback function
+ callback.call(panel, method, state);
+ // Run the next function in the queue
+ next();
+ }
+ });
+ });
+
+ // When the panel is openend, dequeue everything so the animation starts
+ if(state === 'open' || dequeue) {
+ this.$queue.dequeue('responsive-tabs');
+ }
+
+ };
+
+ /**
+ * This function returns the collapsibility of the tab in this state
+ * @returns {Boolean} The collapsibility of the tab
+ */
+ ResponsiveTabs.prototype._isCollapisble = function() {
+ return (typeof this.options.collapsible === 'boolean' && this.options.collapsible) || (typeof this.options.collapsible === 'string' && this.options.collapsible === this.getState());
+ };
+
+ /**
+ * This function returns a tab by numeric reference
+ * @param {Integer} numRef - Numeric tab reference
+ * @returns {Object} Tab object
+ */
+ ResponsiveTabs.prototype._getTab = function(numRef) {
+ return this.tabs[numRef];
+ };
+
+ /**
+ * This function returns the numeric tab reference based on a hash selector
+ * @param {String} selector - Hash selector
+ * @returns {Integer} Numeric tab reference
+ */
+ ResponsiveTabs.prototype._getTabRefBySelector = function(selector) {
+ // Loop all tabs
+ for (var i=0; i= docViewTop));
+ };
+
+ //
+ // PUBLIC FUNCTIONS
+ //
+
+ /**
+ * This function activates a tab
+ * @param {Integer} tabRef - Numeric tab reference
+ * @param {Boolean} stopRotation - Defines if the tab rotation should stop after activation
+ */
+ ResponsiveTabs.prototype.activate = function(tabRef, stopRotation) {
+ var e = jQuery.Event('tabs-activate');
+ var oTab = this._getTab(tabRef);
+ if(!oTab.disabled) {
+ this._openTab(e, oTab, true, stopRotation || true);
+ }
+ };
+
+ /**
+ * This function deactivates a tab
+ * @param {Integer} tabRef - Numeric tab reference
+ */
+ ResponsiveTabs.prototype.deactivate = function(tabRef) {
+ var e = jQuery.Event('tabs-dectivate');
+ var oTab = this._getTab(tabRef);
+ if(!oTab.disabled) {
+ this._closeTab(e, oTab);
+ }
+ };
+
+ /**
+ * This function enables a tab
+ * @param {Integer} tabRef - Numeric tab reference
+ */
+ ResponsiveTabs.prototype.enable = function(tabRef) {
+ var oTab = this._getTab(tabRef);
+ if(oTab){
+ oTab.disabled = false;
+ oTab.tab.addClass(this.options.classes.stateDefault).removeClass(this.options.classes.stateDisabled);
+ oTab.accordionTab.addClass(this.options.classes.stateDefault).removeClass(this.options.classes.stateDisabled);
+ }
+ };
+
+ /**
+ * This function disable a tab
+ * @param {Integer} tabRef - Numeric tab reference
+ */
+ ResponsiveTabs.prototype.disable = function(tabRef) {
+ var oTab = this._getTab(tabRef);
+ if(oTab){
+ oTab.disabled = true;
+ oTab.tab.removeClass(this.options.classes.stateDefault).addClass(this.options.classes.stateDisabled);
+ oTab.accordionTab.removeClass(this.options.classes.stateDefault).addClass(this.options.classes.stateDisabled);
+ }
+ };
+
+ /**
+ * This function gets the current state of the plugin
+ * @returns {String} State of the plugin
+ */
+ ResponsiveTabs.prototype.getState = function() {
+ return this.state;
+ };
+
+ /**
+ * This function starts the rotation of the tabs
+ * @param {Integer} speed - The speed of the rotation
+ */
+ ResponsiveTabs.prototype.startRotation = function(speed) {
+ var _this = this;
+ // Make sure not all tabs are disabled
+ if(this.tabs.length > this.options.disabled.length) {
+ this.rotateInterval = setInterval(function(){
+ var e = jQuery.Event('rotate');
+ _this._openTab(e, _this._getTab(_this._getNextTabRef()), true);
+ }, speed || (($.isNumeric(_this.options.rotate)) ? _this.options.rotate : 4000) );
+ } else {
+ throw new Error("Rotation is not possible if all tabs are disabled");
+ }
+ };
+
+ /**
+ * This function stops the rotation of the tabs
+ */
+ ResponsiveTabs.prototype.stopRotation = function() {
+ window.clearInterval(this.rotateInterval);
+ this.rotateInterval = 0;
+ };
+
+ /**
+ * This function can be used to get/set options
+ * @return {any} Option value
+ */
+ ResponsiveTabs.prototype.option = function(key, value) {
+ if(value) {
+ this.options[key] = value;
+ }
+ return this.options[key];
+ };
+
+ /** jQuery wrapper */
+ $.fn.responsiveTabs = function ( options ) {
+ var args = arguments;
+ var instance;
+
+ if (options === undefined || typeof options === 'object') {
+ return this.each(function () {
+ if (!$.data(this, 'responsivetabs')) {
+ $.data(this, 'responsivetabs', new ResponsiveTabs( this, options ));
+ }
+ });
+ } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
+ instance = $.data(this[0], 'responsivetabs');
+
+ // Allow instances to be destroyed via the 'destroy' method
+ if (options === 'destroy') {
+ // TODO: destroy instance classes, etc
+ $.data(this, 'responsivetabs', null);
+ }
+
+ if (instance instanceof ResponsiveTabs && typeof instance[options] === 'function') {
+ return instance[options].apply( instance, Array.prototype.slice.call( args, 1 ) );
+ } else {
+ return this;
+ }
+ }
+ };
+
+}(jQuery, window));
\ No newline at end of file
diff --git a/js/videobox.js b/js/videobox.js
new file mode 100644
index 0000000..43679a8
--- /dev/null
+++ b/js/videobox.js
@@ -0,0 +1,172 @@
+/*
+ * VideoBox
+ * Example and Documentation: https://github.com/tedktedk/videobox/blob/master/README.md
+ *
+ * Version: 1.1
+ *
+ * Copyright (c) 2016 Ted k'
+ * http://tedk.com.br/
+ *
+ * Dual licensed under the MIT or GPL Version 2 licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ */
+ (function($){
+ $.fn.extend({
+ videoBox: function(options){
+ var obj = $(this);
+ var tag_v = document.createElement("script");
+ var firstScriptTag = document.getElementsByTagName("script")[0];
+
+ var defaults_yt = {
+ autohide: 2,
+ autoplay: 0,
+ cc_load_policy: 1,
+ color: "",
+ controls: 1,
+ disablekb: 0,
+ enablejsapi: 0,
+ fs: 1,
+ hl: "",
+ iv_load_policy: 1,
+ loop: 0,
+ modestbranding: 1,
+ showinfo: 1,
+ height: 390,
+ width: 640
+ };
+
+ var defaults_vm = {
+ width: 640,
+ height: 360,
+ loop: false,
+ autoplay: false,
+ byline: true,
+ color: "00adef",
+ maxheight: "",
+ maxwidth: "",
+ portrait: true,
+ title: ""
+ };
+
+ var defaults_k = {
+ partner_id: "243342",
+ uiconf_id: "12905712",
+ entry_id: "0_uka1msg4",
+ width: 640,
+ height: 360,
+ switchOnResize: false,
+ simpleFormat: true,
+ displayMode: "sizebitrate",
+ inlineScript: false,
+ hideSource: null,
+ autoPlay: false
+ };
+
+ var options_yt = $.extend(defaults_yt, options);
+ var options_vm = $.extend(defaults_vm, options);
+ var options_k = $.extend(defaults_k, options);
+
+ $.each( obj, function( key, value ){
+ var _this = $(value);
+
+ if (_this.attr("data-youtube")){
+ tag_v.id = "VIDEOBOX_createTag_y";
+ if (!document.getElementById("VIDEOBOX_createTag_y")){
+ tag_v.src = "https://www.youtube.com/iframe_api";
+ firstScriptTag.parentNode.insertBefore(tag_v, firstScriptTag);
+ }
+ }
+ else if (_this.attr("data-vimeo")){
+ var randomID = "VIDEOBOX_" + Math.floor(Math.random() * 100) + key;
+ var returnID = _this.attr("data-vimeo").match(/https?:\/\/(?:www\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|)(\d+)(?:$|\/|\?)/);
+
+ tag_v.id = "VIDEOBOX_createTag_v";
+ _this.attr("id", randomID);
+
+ if (!document.getElementById("VIDEOBOX_createTag_v")){
+ tag_v.src = "https://player.vimeo.com/api/player.js";
+ firstScriptTag.parentNode.insertBefore(tag_v, firstScriptTag);
+ }
+
+ tag_v.addEventListener("load", function(e){
+ options_vm.id = returnID[3];
+ return new Vimeo.Player(document.getElementById(randomID), options_vm);
+ }, false);
+ }
+ else if (_this.attr("data-kaltura")){
+ var randomID = "VIDEOBOX_k_" + Math.floor(Math.random() * 100) + key;
+
+ tag_v.id = "VIDEOBOX_createTag_k";
+ _this.attr("id", randomID);
+ _this.attr("itemprop", "video");
+ _this.attr("itemscope", true);
+ _this.attr("itemtype", "http://schema.org/VideoObject");
+ _this.css({ "width": options_k.width + "px", "height": options_k.height + "px" });
+
+ if (!document.getElementById("VIDEOBOX_createTag_k")){
+ tag_v.src = "https://cdnapisec.kaltura.com/p/" + options_k.partner_id + "/sp/" + options_k.partner_id + "00/embedIframeJs/uiconf_id/" + options_k.uiconf_id + "/partner_id/" + options_k.partner_id + "";
+ firstScriptTag.parentNode.insertBefore(tag_v, firstScriptTag);
+ }
+
+ tag_v.addEventListener("load", function(e){
+ kWidget.embed({
+ targetId: randomID,
+ wid: "_" + options_k.partner_id,
+ uiconf_id: options_k.uiconf_id,
+ entry_id: options_k.entry_id,
+ flashvars: {
+ "sourceSelector": {
+ "plugin": true,
+ "switchOnResize": options_k.switchOnResize,
+ "simpleFormat": options_k.simpleFormat,
+ "displayMode": options_k.displayMode,
+ "hideSource": options_k.hideSource
+ },
+ "mediaProxy.preferedFlavorBR": "1600",
+ "autoPlay": options_k.autoPlay,
+ "inlineScript": options_k.inlineScript
+ }
+ });
+ }, false);
+ }
+ });
+
+ window.onYouTubeIframeAPIReady = function(){
+ $.each( obj, function( key, value ){
+ var _this = $(value);
+ var randomID = "VIDEOBOX_" + Math.floor(Math.random() * 100) + key;
+
+ if (_this.attr("data-youtube")){
+ _this.attr("id", randomID);
+ var returnID = _this.attr("data-youtube").match(/(?:https?:\/{2})?(?:w{3}\.)?youtu(?:be)?\.(?:com|be)(?:\/watch\?v=|\/)([^\s&]+)/);
+
+ return new YT.Player(randomID, {
+ height: options_yt.height,
+ width: options_yt.width,
+ videoId: returnID[1],
+ playerVars: {
+ "autohide": options_yt.autohide,
+ "autoplay": options_yt.autoplay,
+ "cc_load_policy": options_yt.cc_load_policy,
+ "color": options_yt.color,
+ "controls": options_yt.controls,
+ "disablekb": options_yt.disablekb,
+ "enablejsapi": options_yt.enablejsapi,
+ "fs": options_yt.fs,
+ "hl": options_yt.hl,
+ "iv_load_policy": options_yt.iv_load_policy,
+ "loop": options_yt.loop,
+ "modestbranding": options_yt.modestbranding,
+ "showinfo": options_yt.showinfo,
+ "height": options_yt.height,
+ "width": options_yt.width
+ }
+ });
+ }
+ });
+ };
+ }
+ });
+
+})(jQuery);