2013-08-12 03:42:13 +02:00
window . onload = function ( ) { // wait for load in a dumb way because B-0
2013-08-19 08:27:46 +02:00
var cw = '/*!\n * Bootstrap v3.0.0\n *\n * Copyright 2013 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\n'
2013-08-12 03:42:13 +02:00
2013-08-18 09:28:52 +02:00
function showError ( msg , err ) {
2013-08-18 04:04:41 +02:00
$ ( ' < div id = "bsCustomizerAlert" class = "bs-customizer-alert" > \
< div class = "container" > \
< a href = "#bsCustomizerAlert" data - dismiss = "alert" class = "close pull-right" > & times ; < / a > \
2013-08-19 09:54:53 +02:00
< p class = "bs-customizer-alert-text" > < span class = "glyphicon glyphicon-warning-sign" > < / s p a n > ' + m s g + ' < / p > ' +
2013-08-18 04:04:41 +02:00
( err . extract ? '<pre class="bs-customizer-alert-extract">' + err . extract . join ( '\n' ) + '</pre>' : '' ) + ' \
< / d i v > \
< / d i v > ' ) . a p p e n d T o ( ' b o d y ' ) . a l e r t ( )
throw err
}
2013-08-18 09:28:52 +02:00
function showCallout ( msg , showUpTop ) {
var callout = $ ( ' < div class = "bs-callout bs-callout-danger" > \
< h4 > Attention ! < / h 4 > \
< p > ' + msg + ' < / p > \
< / d i v > ' )
if ( showUpTop ) {
callout . appendTo ( '.bs-docs-container' )
} else {
callout . insertAfter ( '.bs-customize-download' )
}
}
2013-08-18 03:41:36 +02:00
function getQueryParam ( key ) {
key = key . replace ( /[*+?^$.\[\]{}()|\\\/]/g , "\\$&" ) ; // escape RegEx meta chars
var match = location . search . match ( new RegExp ( "[?&]" + key + "=([^&]+)(&|$)" ) ) ;
return match && decodeURIComponent ( match [ 1 ] . replace ( /\+/g , " " ) ) ;
}
2013-08-18 09:28:52 +02:00
function createGist ( configData ) {
2013-08-18 03:41:36 +02:00
var data = {
"description" : "Bootstrap Customizer Config" ,
"public" : true ,
"files" : {
"config.json" : {
2013-08-18 09:28:52 +02:00
"content" : JSON . stringify ( configData , null , 2 )
2013-08-18 03:41:36 +02:00
}
}
}
$ . ajax ( {
url : 'https://api.github.com/gists' ,
type : 'POST' ,
dataType : 'json' ,
data : JSON . stringify ( data )
} )
2013-08-18 04:07:59 +02:00
. success ( function ( result ) {
history . replaceState ( false , document . title , window . location . origin + window . location . pathname + '?id=' + result . id )
2013-08-18 03:41:36 +02:00
} )
2013-08-18 04:04:41 +02:00
. error ( function ( err ) {
2013-08-19 08:36:36 +02:00
showError ( '<strong>Ruh roh!</strong> Could not save gist file, configuration not saved.' , err )
2013-08-18 03:41:36 +02:00
} )
}
2013-08-18 09:28:52 +02:00
function getCustomizerData ( ) {
2013-08-12 03:42:13 +02:00
var vars = { }
$ ( '#less-variables-section input' )
. each ( function ( ) {
$ ( this ) . val ( ) && ( vars [ $ ( this ) . prev ( ) . text ( ) ] = $ ( this ) . val ( ) )
} )
var data = {
vars : vars ,
2013-08-18 03:41:36 +02:00
css : $ ( '#less-section input:checked' ) . map ( function ( ) { return this . value } ) . toArray ( ) ,
js : $ ( '#plugin-section input:checked' ) . map ( function ( ) { return this . value } ) . toArray ( )
2013-08-12 03:42:13 +02:00
}
if ( $ . isEmptyObject ( data . vars ) && ! data . css . length && ! data . js . length ) return
2013-08-18 09:28:52 +02:00
return data
2013-08-12 03:42:13 +02:00
}
function parseUrl ( ) {
2013-08-18 03:41:36 +02:00
var id = getQueryParam ( 'id' )
2013-08-12 03:42:13 +02:00
2013-08-18 03:41:36 +02:00
if ( ! id ) return
2013-08-12 03:42:13 +02:00
2013-08-18 03:41:36 +02:00
$ . ajax ( {
url : 'https://api.github.com/gists/' + id ,
type : 'GET' ,
dataType : 'json'
} )
. success ( function ( result ) {
var data = JSON . parse ( result . files [ 'config.json' ] . content )
if ( data . js ) {
$ ( '#plugin-section input' ) . each ( function ( ) {
$ ( this ) . prop ( 'checked' , ~ $ . inArray ( this . value , data . js ) )
} )
2013-08-12 03:42:13 +02:00
}
2013-08-18 03:41:36 +02:00
if ( data . css ) {
$ ( '#less-section input' ) . each ( function ( ) {
$ ( this ) . prop ( 'checked' , ~ $ . inArray ( this . value , data . css ) )
} )
}
if ( data . vars ) {
for ( var i in data . vars ) {
$ ( 'input[data-var="' + i + '"]' ) . val ( data . vars [ i ] )
}
}
} )
2013-08-18 04:04:41 +02:00
. error ( function ( err ) {
showError ( 'Error fetching bootstrap config file' , err )
2013-08-18 03:41:36 +02:00
} )
2013-08-12 03:42:13 +02:00
}
function generateZip ( css , js , complete ) {
2013-08-19 08:36:36 +02:00
if ( ! css && ! js ) return showError ( '<strong>Ruh roh!</strong> No Bootstrap files selected.' , new Error ( 'no Bootstrap' ) )
2013-08-12 03:42:13 +02:00
var zip = new JSZip ( )
if ( css ) {
var cssFolder = zip . folder ( 'css' )
for ( var fileName in css ) {
cssFolder . file ( fileName , css [ fileName ] )
}
}
if ( js ) {
var jsFolder = zip . folder ( 'js' )
for ( var fileName in js ) {
jsFolder . file ( fileName , js [ fileName ] )
}
}
2013-08-18 09:28:52 +02:00
var content = zip . generate ( { type : "blob" } )
complete ( content )
2013-08-12 03:42:13 +02:00
}
function generateCustomCSS ( vars ) {
var result = ''
for ( var key in vars ) {
result += key + ': ' + vars [ key ] + ';\n'
}
return result + '\n\n'
}
function generateCSS ( ) {
var $checked = $ ( '#less-section input:checked' )
if ( ! $checked . length ) return false
var result = { }
var vars = { }
var css = ''
$ ( '#less-variables-section input' )
. each ( function ( ) {
$ ( this ) . val ( ) && ( vars [ $ ( this ) . prev ( ) . text ( ) ] = $ ( this ) . val ( ) )
} )
css += _ _less [ 'variables.less' ]
if ( vars ) css += generateCustomCSS ( vars )
css += _ _less [ 'mixins.less' ]
2013-08-19 04:40:26 +02:00
css += _ _less [ 'normalize.less' ]
css += _ _less [ 'scaffolding.less' ]
2013-08-12 03:42:13 +02:00
css += $checked
. map ( function ( ) { return _ _less [ this . value ] } )
. toArray ( )
. join ( '\n' )
css = css . replace ( /@import[^\n]*/gi , '' ) //strip any imports
try {
var parser = new less . Parser ( {
paths : [ 'variables.less' , 'mixins.less' ]
, optimization : 0
, filename : 'bootstrap.css'
} ) . parse ( css , function ( err , tree ) {
2013-08-18 04:04:41 +02:00
if ( err ) {
2013-08-19 08:36:36 +02:00
return showError ( '<strong>Ruh roh!</strong> Could not parse less files.' , err )
2013-08-18 04:04:41 +02:00
}
2013-08-12 03:42:13 +02:00
result = {
'bootstrap.css' : cw + tree . toCSS ( ) ,
'bootstrap.min.css' : cw + tree . toCSS ( { compress : true } )
}
} )
} catch ( err ) {
2013-08-19 08:36:36 +02:00
return showError ( '<strong>Ruh roh!</strong> Could not parse less files.' , err )
2013-08-12 03:42:13 +02:00
}
return result
}
function generateJavascript ( ) {
var $checked = $ ( '#plugin-section input:checked' )
if ( ! $checked . length ) return false
var js = $checked
. map ( function ( ) { return _ _js [ this . value ] } )
. toArray ( )
. join ( '\n' )
return {
'bootstrap.js' : js ,
'bootstrap.min.js' : cw + uglify ( js )
}
}
var inputsComponent = $ ( '#less-section input' )
var inputsPlugin = $ ( '#plugin-section input' )
var inputsVariables = $ ( '#less-variables-section input' )
$ ( '#less-section .toggle' ) . on ( 'click' , function ( e ) {
e . preventDefault ( )
inputsComponent . prop ( 'checked' , ! inputsComponent . is ( ':checked' ) )
} )
$ ( '#plugin-section .toggle' ) . on ( 'click' , function ( e ) {
e . preventDefault ( )
inputsPlugin . prop ( 'checked' , ! inputsPlugin . is ( ':checked' ) )
} )
$ ( '#less-variables-section .toggle' ) . on ( 'click' , function ( e ) {
e . preventDefault ( )
inputsVariables . val ( '' )
} )
2013-08-18 06:50:01 +02:00
$ ( '[data-dependencies]' ) . on ( 'click' , function ( ) {
if ( ! $ ( this ) . is ( ':checked' ) ) return
var dependencies = this . getAttribute ( 'data-dependencies' )
if ( ! dependencies ) return
dependencies = dependencies . split ( ',' )
for ( var i = 0 ; i < dependencies . length ; i ++ ) {
var dependency = $ ( '[value="' + dependencies [ i ] + '"]' )
dependency && dependency . prop ( 'checked' , true )
}
} )
$ ( '[data-dependents]' ) . on ( 'click' , function ( ) {
if ( $ ( this ) . is ( ':checked' ) ) return
var dependents = this . getAttribute ( 'data-dependents' )
if ( ! dependents ) return
dependents = dependents . split ( ',' )
for ( var i = 0 ; i < dependents . length ; i ++ ) {
var dependent = $ ( '[value="' + dependents [ i ] + '"]' )
dependent && dependent . prop ( 'checked' , false )
}
} )
2013-08-18 09:28:52 +02:00
var $compileBtn = $ ( '#btn-compile' )
var $downloadBtn = $ ( '#btn-download' )
$compileBtn . on ( 'click' , function ( e ) {
e . preventDefault ( )
$compileBtn . attr ( 'disabled' , 'disabled' )
generateZip ( generateCSS ( ) , generateJavascript ( ) , function ( blob ) {
$compileBtn . removeAttr ( 'disabled' )
saveAs ( blob , "bootstrap.zip" )
createGist ( getCustomizerData ( ) )
} )
} )
// browser support alerts
if ( ! window . URL && navigator . userAgent . toLowerCase ( ) . indexOf ( 'safari' ) != - 1 ) {
showCallout ( " Looks like you 're using safari, which sadly doesn' t have the best support \
for HTML5 blobs . Because of this your file will be downloaded with the name < code > \ "untitled\" < / c o d e > . \
However , if you check your downloads folder , just rename this < code > \ "untitled\" < / c o d e > f i l e \
to < code > \ "bootstrap.zip\"</code> and you should be good to go!" )
} else if ( ! window . URL && ! window . webkitURL ) {
$ ( '.bs-docs-section, .bs-sidebar' ) . css ( 'display' , 'none' )
showCallout ( " Looks like your current browser doesn ' t support the Bootstrap Customizer . Please take a second \
to < a href = \ "https://www.google.com/intl/en/chrome/browser/\"> upgrade to a more modern browser</a>." , true )
}
2013-08-18 03:41:36 +02:00
parseUrl ( )
2013-08-19 08:27:46 +02:00
}