\
Thank you for using Moduino,
\
Designed and written by Christopher Andrews, Copyright 2014
\
https://arduino.land/Moduino/. \
/*!
Moduino, A modification system for the Arduino.cc forums.
Copyright (C) 2014 Christopher Andrews
https://arduino.land/Moduino/
*/
/***
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
tags from end of quote. ***/
'colours' : [
'#e4e4e4', /** Quote header background. **/
'rgba(250, 242, 0, 0.28)', /** Quote content background. **/
'rgb(245, 215, 120)' /** Quote border. **/
]
},
'sizeableCode' : {
'enabled' : true, /** Can be set to false if using highlighting. (value is used). **/
'value' : 220 /** Maximum starting height for long code boxes **/
},
'hideIP' : true, /** No need to know everyone's IP has been logged. **/
'shrinkPost' : true, /** Minor padding & margin fixes. **/
'combineKarma' : true, /** Combine the '[Add Karma]' link with the karma count **/
'hideProfileLink' : true, /** Currently a users post profile can show two web links **/
'movePostOptions' : true, /** Move the options like quote/edit/report to the post header **/
'blurbToToolTip' : true, /** Remove the 'blurb' from the post profile and add as tooltip to avatar picture. **/
'hideQuickReply' : true, /** Hides the quick reply box & adds a toggle button **/
'gravatarAvatar' : { /** Show a unique avatar for members with no avatar set. **/
'enabled' : true,
'salt' : '_pepper_', /** A little bit of salt **/
'style' : 'wavatar', /** Valid styles: identicon, monsterid, wavatar, retro **/
},
'codeHighlighting' : {
'enabled' : true,
'lineNumbers' : true, /** Allow syntax highlighter to insert line numbers. **/
'pathToJS' : 'https://arduino.land/JS/SyntaxHighlighter/', /** Location of repo for JS files. **/
'pathToCSS' : 'https://arduino.land/CSS/SyntaxHighlighter/', /** Location of repo for CSS files. **/
'core' : 'Moduino', /** Theme core. **/
'brushes' : [ 'Cpp' ], /** Array of brushes to use ( different languages ). **/
'theme' : 'Moduino', /** Theme CSS. **/
'cssExt' : 'scss' /** CSS source file extension. **/
},
'disableQuickReplyQuote' : true
},
/***
Debugging configuration data.
There are no modifications controlled with these settings.
***/
'debug' : {
'enabled' : true, /** Not currently used. **/
},
/***
Internal configuration data.
There are no modifications controlled with these settings.
Adding an enable = false does nothing.
***/
'internal' : {
'idPrefix' : '__MODUINO__', /** ID prefix for page elements inserted by Moduino. **/
'version' : {
'components':{'major':0,'minor':1,'revision':7}, /** Version data for this copy of Moduino. **/
'versionCheckJSON' : 'https://arduino.land/Moduino/Version', /** URI returning the latest version number JSON. **/
'checkFrequency' : 1800, /** Time in seconds between checking for updates (default: 30 mins). **/
},
'fontAwesome' : 'https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css', /** Path to font awesome, default is Twitters Bootstrap CDN **/
'jQueryUI' : 'https://code.jquery.com/ui/1.11.2/jquery-ui.min.js',
'jQueryUITheme' : 'https://code.jquery.com/ui/1.11.2/themes/start/jquery-ui.min.css',
'contextmenu' : 'https://cdnjs.cloudflare.com/ajax/libs/jquery.ui-contextmenu/1.8.1/jquery.ui-contextmenu.min.js',
'crypto-js' : {
'Core' : 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core-min.js',
'MD5' : 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/md5-min.js',
'ready' : function(){
return ( typeof CryptoJS !== 'undefined' ) && ( typeof CryptoJS.MD5 !== 'undefined');
}
},
'sourceRepository' : 'https://arduino.land/Moduino/Source/', /** Location of the Moduino core JS files. **/
},
},
mode : {
GLOBAL: 0,
INDEX : {
ROOT : 1,
FORUM : 2
},
THREAD: 3,
REPLY: 4,
LASTPOSTS:5
},
'themes' : {
'list' : [],
'add' : function( theme ){
Moduino.themes.list.push( theme );
}
},
/** Debugging constants for use with the Moduino.dbg() function. Use these values as they may change ( from an integer to a function! ). **/
'debug' : {
'notification' : 0,
'warning' : 1,
'error' : 2,
'mod' : 3
},
'capFirst' : function( s ){
return s.charAt(0).toUpperCase() + s.slice(1);
},
'resizeEvents' : {
'events' : [],
'add' : function(ev){
Moduino.resizeEvents.events.push(ev);
ev(); //Call it once to do initial size.
}
},
'resize' : function (){
/** Modification based resizing. **/
$( Moduino.resizeEvents.events ).each(function(i,e){ e(); });
/** Moduino device resize events **/
var pfx = Moduino.config.internal.idPrefix;
$( '#' + pfx + 'title-box' ).position({
of: $( '#' + pfx + 'footer' ),
my: 'center center',
at: 'center center',
});
$( '#' + pfx + 'settings-btn' )
.css( 'margin-left', '0px' )
.position({
of: $( '#' + pfx + 'footer' ),
my: 'right center',
at: 'right center',
collision: 'none'
}).css( 'margin-left', '-5px' );//.css( 'left', $( '#' + pfx + 'settings-btn' ).css( 'left' ) );
$( '#' + pfx + 'version-box' ).position({
of: $( '#' + pfx + 'footer' ),
my: 'left center',
at: 'left center',
collision: 'none'
});
},
/** Images need their dimensions so jQueryUI can position elements correctly. **/
'DisplayAndSize' : function ( img, dest ){
img
.appendTo( dest )
.attr( 'width', img.width() + 'px' )
.attr( 'height', img.height() + 'px' );
return img;
},
/** A timestamp in seconds since the epoch **/
'unixTime' : function (){ return Math.round(new Date().getTime() / 1000); },
/***
cookie object.
Customizes hQuery cookie plugin for Moduino
***/
'cookie' : {
'get' : function ( name, def ){
var result = $.cookie( Moduino.config.internal.idPrefix + name );
return ( result === undefined ) ? (def || null) : result;
},
'set' : function ( name, value ){ return $.cookie( Moduino.config.internal.idPrefix + name, value ); },
'remove' : function ( name ){ return $.removeCookie( Moduino.config.internal.idPrefix + name ); },
},
/***
setting object.
This wraps the functionality of the cookie object.
It allows all settings to be stored in a single cookie rather than one per setting.
***/
'setting' : {
'id': 'settings',
'set' : function ( name, value, update ){
var settings = Moduino.cookie.get( this.id, {} );
if( update && (settings[ name ] !== undefined) ) if( settings[ name ] === value ){ return; }
settings[ name ] = value;
Moduino.cookie.set( this.id, settings );
},
'get' : function ( name, def ){
var settings = Moduino.cookie.get( this.id, {} );
if( settings[ name ] === undefined ) return def || null;
return settings[ name ];
},
'remove' : function ( name ){
var settings = Moduino.cookie.get( this.id, {} );
if(settings[ name ] === undefined) return;
delete settings[ name ];
Moduino.cookie.set( this.id, settings );
},
'update' : function ( name, value ){ this.set( name, value, true ); },
'removeAll' : function (){ return Moduino.cookie.set( this.id, {} ); }
},
'checkVersion' : function (){
if( this.initialized ){
var config = this.config.internal;
var pfx = config.idPrefix;
var cv = config.version;
var ver = cv.components;
var updateTime = this.unixTime() - cv.checkFrequency;
var setImg = function( colour, alt ){
$( '' )
.load( function (){
$( '#' + pfx + 'version-badge' ).off().remove();
Mo.DisplayAndSize( $(this), '#' + pfx + 'version-box' )
.css({ 'margin-left' : '5px', 'cursor' : 'pointer' })
.on( 'click', function (){
Mo.setting.remove( 'last-check' );
Mo.setting.remove( 'latest-version' );
$(this).off();
Mo.checkVersion();
});
Mo.resize();
});
};
var setState = function ( nv ){
var nvc = nv.components,
info = [ [ 'red', 'Moduino is out of date. Latest: ' + nv.version ], [ 'green', 'Moduino is up to date!' ] ],
idx = ( nvc.revision > ver.revision || nvc.minor > ver.minor || nvc.major > ver.major ) ? 0 : 1;
Mo.setting.update( 'get-update', !!!idx );
setImg( info[idx][0], info[idx][1] );
};
//Use cookie if recently checked.
if( this.setting.get( 'last-check', updateTime ) <= updateTime ){
setImg( 'lightgrey', 'Checking for updates...' );
this.setting.remove( 'latest-version' );
$.getJSON( cv.versionCheckJSON, function( data ){
setState( data );
Mo.setting.update( 'last-check', Mo.unixTime() );
Mo.setting.update( 'latest-version', data );
}).fail( function (){ setImg( 'orange', 'Unable to check for updates at this time.' ); });
}else{
var data = this.setting.get( 'latest-version' );
if( data == null ){
this.setting.remove( 'last-check' );
this.checkVersion(); //Re-run to grab a fresh copy.
}else setState( data );
}
}
},
'initialized' : false,
'init' : function( autoRun ){
//Create console bar and thank you note.
var cint = this.config.internal;
var footer = $( 'div#pagefooter.pagefooter' );
var dbg = cint.idPrefix + 'footer';
var ver = cint.version.components;
var pfx = cint.idPrefix;
var delayedInit = function(){
$.cookie.json = true;
$.cookie.defaults.path = '/';
//Add footer to page once loaded.
//$(window).load(function() {
//$(window).bind("load", function() {
var loadGUI = function(){
var htm = '\
\
Thank you for using Moduino,
\
Designed and written by Christopher Andrews, Copyright 2014
\
https://arduino.land/Moduino/. \
\
\
\
Got ideas for improvements or new features? Drop a line on GitHub or post in the forum: \
\
Want to help support the project? You can do this safely using PayPal. \
\
Settings tabs
\Settings tabs
\ tags wrapped in tags. The
correct method requires the contents of the tags to be wrapped in a
tags instead.
***/
$( 'code.bbc_code' )
.each( function(i,e){
if( $(e).parent()[0].tagName === 'PRE' )
$(e).insertBefore( $(e).parent() )
.next().remove(); /** Kill empty pre otherwise SyntaxHighlighter will try and parse its contents. **/
//Remove tab spans:
$(e).children('span')
.each(function(){
$(this).replaceWith(this.childNodes);
});
}).css({ 'padding' : '0px', 'max-height' : 'none', 'border' : '1px solid #cfcfcf', 'position' : 'relative' })
.wrapInner( '' )
.children()
.each( function ( i, e ){
e.innerHTML = e.innerHTML.replace(/\<br\>/gi,"\n").replace( /
/g,'\n' );
});
SyntaxHighlighter.defaults.gutter = chl.lineNumbers;
SyntaxHighlighter.defaults.toolbar = false;
SyntaxHighlighter.highlight();
if( config.code.hoverSelect )
addHoverSelect( '.bbc_code', "$(this).parent().find( 'div.container' )[0]" );
//Fix code box height, as highlighted code is smaller than the standard SMF code.
$( '.bbc_code' ).each( function( i, e ){
$(e).css( 'height', ( $(e).find( '.syntaxhighlighter' )[0].scrollHeight > config.sizeableCode.value ? config.sizeableCode.value + 'px' : 'auto' ) )
.children('div')
.css({ 'display' : 'inline-block', 'width' : 'auto', 'min-width' : '100%' })
.children()
.css({ 'overflow':'hidden', 'display' : 'inline-block'});
});
}},
failHandler = function (s){
Mo.dbg( txt + 'AJAX Failed', Mo.debug.error );
};
//Insert syntax highlighter CSS
$('head')
.append('')
.append('')
.append('');
//Grab JavaScript.
$.cachedScript( chl.pathToJS + 'shCore.js' )
.fail( failHandler )
.success( function( s ){
$.each( chl.brushes, function ( i, e ){
$.cachedScript( chl.pathToJS + 'shBrush' + e + '.js' )
.fail( failHandler )
.success( successHandler );
});
successHandler( s );
});
}
/*** Move code '[Select]' function to hover over ***/
if( config.code.hoverSelect ){
Mo.dbgm( 'code.hoverSelect' );
$( '.codeheader' ).hide();
if( !config.codeHighlighting.enabled )
addHoverSelect( '.bbc_code' );
}
/*** Quote modifications. ***/
if( config.quote.enabled ){
Mo.dbgm( 'quote' );
/*** Hide the header if empty, or shrink it. ***/
$( '.quoteheader' ).each(function ( i, e ){
if( config.quote.hideEmptyHead && $(e).children().text() === 'Quote' )
$(e).hide();
else
$(e).css( 'padding', '0 4px' );
});
/*** Add the ability to select a quotes text. ***/
if( config.quote.hoverSelect ){
Mo.dbgm( 'quote.hoverSelect' );
$( '.bbc_standard_quote' )
.wrapInner( '' )
.children('div')
.css('display','inline');
addHoverSelect( '.bbc_standard_quote', "$(this).parent().find('div').first()[0]" )
.css( 'padding', '4px 4px' );
}
/*** Allow custom colours used with quotes. (like old forum) ***/
if( config.quote.colours != false ){
Mo.dbgm( 'quote.colours' );
$( '.bbc_standard_quote' ).css({
'background-color' : config.quote.colours[ 1 ],
'border' : '1px solid ' + config.quote.colours[ 2 ],
});
$( '.quoteheader' ).css({
'background-color' : config.quote.colours[ 0 ],
'border' : '1px solid ' + config.quote.colours[ 2 ],
'margin-bottom' : '-1px'
});
}
/*** Remove excess
tags from end of quote. ***/
if( config.quote.trimBreaks ){
Mo.dbgm( 'quote.trimBreaks' );
$( 'blockquote.bbc_standard_quote' ).each( function( i, e ){
$(e).children( 'div' ).html( $(e).children( 'div' ).html().replace( /(
\s*)+$/, '' ) );
});
}
if( config.disableQuickReplyQuote ){
Mo.dbgm( 'disableQuickReplyQuote' );
if( QuickReply.prototype.quote != undefined ) QuickReply.prototype.quote = null;
}
if( config.movePostOptions ){
Mo.dbgm( 'movePostOptions' );
$('.post_wrapper')
.each(function(){
var pn = $(this).find('.page_number');
var qb = $(this).find('ul.quickbuttons');
qb.insertAfter( pn )
.addClass( 'floatright' )
.css({
'clear' : 'none',
'margin' : -((qb.outerHeight(true) - pn.outerHeight(true))/4) + 'px 0px 0px 0px'
}).prepend( $(this).find('li.report_link') );
}).find('.postarea .post')
.css('overflow','visible');
$('.under_message').hide();
}
if( config.blurbToToolTip ){
Mo.dbgm( 'blurbToToolTip' );
$('.post_wrapper').each(function(){
var blurb = $(this).find('li.blurb');
$(this)
.find('img.avatar')
.attr('title',blurb.text());
blurb.remove();
});
}
if( config.hideQuickReply ){
Mo.dbgm( 'hideQuickReply' );
formatButton(
$('Toggle Quick Reply')
.appendTo( $('#quickreplybox h3') )
.on( 'click', function(){
$('#quickReplyOptions').toggle();
}));
$('#quickReplyOptions').toggle();
}
if( config.gravatarAvatar.enabled ){
Mo.dbgm( 'gravatarAvatar' );
var gravInterval = setInterval( function(){
if( Mo.config.internal['crypto-js'].ready() ){
clearInterval( gravInterval );
$('ul.user_info > .avatar > a > img').each(function(){
if( $(this).attr('src').indexOf('avatars/default.png') != -1 ){
var profileURI = $(this).parent().attr('href').split(';');
if( profileURI.length ){
$(this).attr('src', GenerateGravatar(profileURI[ profileURI.length - 1 ].split('=')[1]) )
.css( 'border','1px solid #bfbfbf' );
}
}
});
}
}, 100 );
}
}
}
function GenerateGravatar( id ){
var ga = Mo.config.thread.gravatarAvatar;
var salt = ga.salt.repeat( 3 );
var hash = CryptoJS.MD5( salt + String(id).repeat(2) + salt );
var domain = ('https:' == document.location.protocol ? 'https://secure.gravatar.com/' : 'http://www.gravatar.com/');
return domain + 'avatar/' + hash + '?f=y&d=' + ga.style;
}
/***
ReplyMods function.
***/
function ReplyMods(){
Mo.dbg( 'Found reply' );
}
/*****************************************************************************************
Themes
*****************************************************************************************/
function ReHash( step ){
switch( Number(step) ){
case Mo.mode.GLOBAL:
$('head').append('');
$('#headerbread').addClass('nav_grad');
$('[name="q"]')
.addClass('rehash-search-bar')
.css({'background-color' : '#FDFEDD', 'color' : 'black'})
.attr('placeholder','Google the forum...');
//Install gravatar image for default avatars.
var fURL = '//forum.arduino.cc/index.php?action=';
var menu = {
'View My...' : {
'Last Posts' : fURL + 'profile;area=showposts',
'Topics' : fURL + 'profile;area=showposts;sa=topics',
'Attachments' : fURL + 'profile;area=showposts;sa=attach',
'Unwatched Topics' : fURL + 'profile;area=showposts;sa=unwatchedtopics',
'Sep7' : null,
'Alerts' : fURL + 'profile;area=showalerts',
'Drafts' : fURL + 'profile;area=showdrafts',
'Messages' : fURL + 'pm',
'Sep4' : null,
'Forum Profile' : fURL + 'profile',
'Site Profile' : 'https://id.arduino.cc/',
'Statistics' : fURL + 'profile;area=statistics'
},
'Sep6' : null,
'SMF' : {
'Whos online' : fURL + 'who',
'Forum groups' : fURL + 'groups',
'Sep1' : null,
'Statistics' : fURL + 'stats',
'Clock' : {
'BCD' : fURL + 'clock',
'Binary' : fURL + 'clock;rb'
},
'Calendar' : fURL + 'calendar',
'Sep2' : null,
'Help' : fURL + 'help',
'Credits' : fURL + 'credits',
'Sep3' : null,
'about:unknown' : fURL + 'about:unknown'
},
'Moduino' : {
'Configuration': '',
'Sep5' : null,
'Homepage' : 'https://arduino.land/Moduino/',
'GitHub' : 'https://github.com/Chris--A/Moduino'
},
'Sep8' : null,
'Logout' : 'https://id.arduino.cc/auth/logout/?returnurl=http%3A%2F%2Fforum.arduino.cc'
};
var menuInterval = setInterval(function(){
if(jQuery && jQuery.ui && jQuery.fn.contextmenu){
clearInterval( menuInterval );
$(Mo.JSONMenu(menu, 'mo-menu'))
.appendTo( $('body') )
.css( 'display','none' );
$('.userPic')
.attr('id','mo-menu-target')
.parent()
.attr('id','mo-menu-context');
setTimeout( function(){
$("#mo-menu-context").contextmenu({
delegate: "#mo-menu-target",
menu: '.mo-menu',
select: function(event, ui) {
var cmd = ui.item.attr('cmd');
if( /#|(https?)?\/?\//.test(cmd) ){
window.location.href = cmd;
}
}
});
$('.userPic').removeClass('has-dropdown not-click');
},1234 );
}
},25);
$('#headerbread').css('border', '1px solid #00979C')
.pcss( 'border-bottom-left-radius','6px' )
.pcss( 'border-bottom-right-radius','6px' );
$('#description_board,.cat_bar').pcss('border-radius','6px');
Rehash_stylizeWhiteBtns( 'input[type="submit"]:not([name="btnG"]),input[type="button"],button[type="submit"]' );
break;
case Mo.mode.INDEX.FORUM:
$('.windowbg.clearfix').css({ 'border' : '1px solid #DFDFDF', 'border-top' : '0px', 'background-color' : '#eee' })
.pcss( 'box-shadow', 'inset 0px 0px 3px 1px rgba(235,235,235,1)' )
.filter(':odd')
.css('background-color','#f7f7f7');
$('#topic_container').css({ 'border-top' : '1px solid #DFDFDF', 'margin' : '3px 1px 0 1px' });
$('div.info,div.stats').css( 'height', 'auto' );
$('.windowbg.clearfix>*').css('padding-bottom', '4px');
/** Thread info sizing **/
$('.info>p').css({ 'font-size' : '0.89em', 'margin-left' : '11px' })
.next('small')
.each(function(){
if( $(this).prev()[0].tagName === 'P' ){ $(this).appendTo($(this).prev()); }
});
$('span.new_posts').css({ 'background' : '#69ABBF', 'color' : '#FFF695', 'border' : '1px solid #777', 'margin' : 0 })
.pcss( 'border-radius', '11px' )
.pcss( 'text-shadow', '1px 1px #105557' );
//break; //Fall through to root index modifications.
case Mo.mode.INDEX.ROOT:
$('.cat_bar').next().find('.up_contain:first').pcss('border-top-left-radius','6px').pcss('border-top-right-radius','6px');
$('.info.home-s>a').css({ 'text-shadow' : '1px 1px white', 'font-size' : '1.3em' })
.next('.lastpost-hack').css('margin',0);
$('.stats>p>strong').css('text-shadow', '1px 1px white');
$('div.up_contain')
.css('border','1px solid #AAA')
.pcss( 'box-shadow', 'inset 0px 0px 7px 1px rgba(225,225,225,1)' )
.children('div.icon')
.css('padding-top','15px');
Rehash_stylizeWhiteBtns( '.topbottom,.button-forum' );
break;
case Mo.mode.THREAD:
//
Rehash_stylizeWhiteBtns( '.topbottom,.button-forum' );
Rehash_stylizePosts( $('.post_wrapper') );
//If images load late, their post container will need to be resized.
$('.post > .inner > img').on('load', function() {
Rehash_stylizePosts( $(this).closest('.post_wrapper') );
$(this).off();
}).each(function() {
if(this.complete) $(this).off();
});
break;
case Mo.mode.LASTPOSTS:
Rehash_stylizePosts( $('.windowbg,.windowbg2') );
break;
};
}
function Rehash_stylizeWhiteBtns( who ){
$(who).css({ 'border-radius':'6px', 'background-color':'#ddd', 'border':'1px solid #999', 'color':'black' });
$('.pagesection').each(function(){
$(this)
.prepend('')
.children('.floatleft:not(".buttonlist")')
.removeClass('floatleft')
.css('display','inline-block')
.appendTo($(this).children('.buttonlist.floatleft'));
$(this)
.find('.topbottom')
.removeClass('topbottom')
.addClass('button-forum')
.css('margin-right', '5px');
});
$('.buttonlist, .buttonlist .pagelinks').css('margin', '0px');
}
function Rehash_stylizePosts( obj ){
var largestPosterWidth = 0;
obj
.css('border', '1px solid #AAA')
.pcss( 'box-shadow', 'inset 0px 0px 7px 1px rgba(220,220,220,1)' )
.find('.poster')
.css('margin-left', '5px')
.end()
.find('img.avatar')
.pcss('border-radius','4px')
.end()
.find('.postarea, .moderatorbar') //.find('.post, .keyinfo, .moderatorbar')
.css({ 'padding-left' : '5px', 'border-left' : '1px solid #bfbfbf' })
.end()
.find('ul.quickbuttons')
.css({ 'border' : '1px solid #bfbfbf', 'padding' : '0px', 'margin-right' : '10px' })
.end()
.find('.page_number')
.css('margin-right','5px')
.end()
.each(function(){ /** Normalize containers. **/
var poster = $(this).find('.poster');
var postarea = $(this).find('.postarea');
//var postRightHeight =
if( poster.height() > postarea.height() ){
var modb = $(this).find('.moderatorbar');
var diff = ( poster.height() - postarea.height() ) - modb.height();
if( diff > 0 ) postarea.height( postarea.height() + diff );
}
if( poster.width() > largestPosterWidth ) largestPosterWidth = poster.width();
})
.end()
.find('.messageicon')
.css('margin','0px');
return obj;
}
//EOF