diff --git a/src/coffee/site.coffee b/src/coffee/site.coffee index 4c3bdb4..f8576ea 100644 --- a/src/coffee/site.coffee +++ b/src/coffee/site.coffee @@ -115,17 +115,20 @@ class Warper click_submit: -> $('#btn-submit').attr('disabled', true).html 'Running...' $('#btn-reset').attr('disabled', true).html 'Running...' + $('#cryptocurrency').prop('disabled', true) $('#passphrase, #salt, checkbox-salt-confirm').attr 'disabled', true $('.progress-pbkdf2, .progress-scrypt').html '' $('.progress-form').show() warpwallet.run { + coinType : $('#cryptocurrency').val() passphrase : $('#passphrase').val() salt : $('#salt').val() progress_hook : (o) => @progress_hook o params : window.params }, (res) => + $('#cryptocurrency').prop('disabled', false) $('#passphrase, #checkbox-salt-confirm').attr 'disabled', false if not window.SALT_DEFAULT? $('#salt').attr 'disabled', false diff --git a/src/css/bselect.css b/src/css/bselect.css new file mode 100644 index 0000000..8aabd5e --- /dev/null +++ b/src/css/bselect.css @@ -0,0 +1,285 @@ +/*! + * BSelect v0.3.4 - 2013-07-11 + * + * Created by Gustavo Henke + * http://gustavohenke.github.io/bselect/ + */ +.bselect { + position: relative; + display: inline-block; + white-space: nowrap; +} +.bselect, +.bselect input, +.bselect button { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; +} +.bselect.open .bselect-caret { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); +} +.bselect.disabled { + opacity: 0.65; + filter: alpha(opacity=65); +} +.bselect-label, +.bselect-caret { + position: relative; + display: inline-block; + color: #333333; + font-size: 14px; + line-height: 20px; + *line-height: 20px; + background-color: #f5f5f5; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + border: 1px solid #bbbbbb; + *border: 0; + border-bottom-color: #a2a2a2; + cursor: pointer; + vertical-align: middle; +} +.bselect-label:hover, +.bselect-caret:hover { + background-position: 0 -15px; + background-color: #e6e6e6; + *background-color: #d9d9d9; + /* Buttons in IE7 don't get borders, so darken on hover */ + + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} +.bselect-label { + padding: 4px 12px; + overflow: hidden; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} +.bselect-caret { + margin-left: -1px; + padding: 4px 5px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +.bselect-caret > .caret { + display: inline-block; + width: 0; + height: 0; + margin: 8px 0 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #333333; + content: ""; + vertical-align: top; +} +.bselect.disabled .bselect-label, +.bselect.disabled .bselect-caret { + background-image: none; + cursor: not-allowed; + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.bselect.disabled .bselect-label:hover, +.bselect.disabled .bselect-caret:hover { + background-color: #f5f5f5; +} +.bselect-dropdown { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + width: 97%; + margin: 2px 0 0; + padding: 5px 1.5%; + background-color: #ffffff; + border: 1px solid #000000; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); +} +.bselect-search { + margin-bottom: 10px; + vertical-align: middle; + white-space: nowrap; +} +.bselect-search > .bselect-search-input { + display: inline-block; + vertical-align: middle; +} +.bselect-search > .bselect-search-icon { + display: inline-block; + height: 20px; + vertical-align: middle; +} +.bselect-search > .bselect-search-input { + position: relative; + padding: 4px 6px; + margin: 0; + background: #ffffff; + border: 1px solid #cccccc; + cursor: text; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.bselect-search > .bselect-search-input:focus { + z-index: 2; +} +.bselect-search > .bselect-search-icon { + width: auto; + margin-left: -1px; + padding: 4px 5px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + background-color: #eeeeee; + border: 1px solid #ccc; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} +.bselect-message { + display: none; + padding: 5px 20px 5px 15px; + line-height: 20px; + cursor: default; +} +.bselect-option-list { + line-height: 20px; + width: 100%; + margin: 0; + padding: 0; + list-style: none; + overflow-y: auto; + overflow-x: hidden; +} +.bselect-option > a { + display: block; + padding: 5px 20px 5px 15px; + color: #333333; + text-decoration: none; + white-space: normal; +} +.bselect-option.grouped { + padding-left: 15px; +} +.bselect-option:focus { + outline: 0; +} +.bselect-option:focus a { + outline: thin dotted #333; + outline-offset: -2px; +} +.bselect-option:focus a, +.bselect-option a:focus, +.bselect-option a:hover { + color: #222222; + text-shadow: 0 1px 0 rgba(100, 100, 100, 0.5); + background-color: #dddddd; + /*background-image: -moz-linear-gradient(top, #aaaaaa, #cccccc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#aaaaaa), to(#cccccc)); + background-image: -webkit-linear-gradient(top, #aaaaaa, #cccccc); + background-image: -o-linear-gradient(top, #aaaaaa, #cccccc); + background-image: linear-gradient(to bottom, #aaaaaa, #cccccc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffaaaaaa', endColorstr='#ffcccccc', GradientType=0);*/ +} +.bselect-option.active > a, +.bselect-option.active > a:hover { + color: #222222; + background-color: #dddddd; + /*background-image: -moz-linear-gradient(top, #aaaaaa, #cccccc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#aaaaaa), to(#cccccc)); + background-image: -webkit-linear-gradient(top, #aaaaaa, #cccccc); + background-image: -o-linear-gradient(top, #aaaaaa, #cccccc); + background-image: linear-gradient(to bottom, #aaaaaa, #cccccc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffaaaaaa', endColorstr='#ffcccccc', GradientType=0);*/ +} +.bselect-option-group { + padding: 5px 20px 5px 15px; + font-weight: bold; + cursor: default; + white-space: normal; +} +.bselect.bselect-mini .bselect-label, +.bselect.bselect-mini .bselect-caret { + padding: 1px 6px; + font-size: 10.5px; +} +.bselect.bselect-mini .bselect-caret { + padding-left: 5px; + padding-right: 5px; +} +.bselect.bselect-small .bselect-label, +.bselect.bselect-small .bselect-caret { + padding: 2px 10px; + font-size: 11.9px; +} +.bselect.bselect-small .bselect-caret { + padding-left: 5px; + padding-right: 5px; +} +.bselect.bselect-large .bselect-label, +.bselect.bselect-large .bselect-caret { + padding: 11px 19px; + font-size: 17.5px; +} +.bselect.bselect-large .bselect-caret { + padding-left: 12px; + padding-right: 12px; +} +.bselect.bselect-large .bselect-caret .caret { + border-left-width: 5px; + border-right-width: 5px; + border-top-width: 5px; +} +.bselect.bselect-mini, +.bselect.bselect-small, +.bselect.bselect-large { + margin-top: 6px; +} +.bselect-inaccessible { + position: relative !important; + top: -9999em !important; + left: -9999em !important; + clip: rect(0, 0, 0, 0) !important; + display: block !important; + visibility: hidden !important; + min-height: 0 !important; + height: 0 !important; + margin: 0 !important; + padding-top: 0 !important; + padding-bottom: 0 !important; + border-top: 0 !important; + border-bottom: 0 !important; +} diff --git a/src/iced/top.iced b/src/iced/top.iced index 4ed5823..6dfb88d 100644 --- a/src/iced/top.iced +++ b/src/iced/top.iced @@ -1,6 +1,7 @@ {scrypt,pbkdf2,HMAC_SHA256,WordArray,util} = require 'triplesec' generate = require('keybase-bitcoin').generate +networkVersion = require('keybase-bitcoin').networkVersion params = require('../json/params.json') #===================================== @@ -15,7 +16,8 @@ from_utf8 = (s, i) -> #===================================== -exports.run = run = ({passphrase, salt, progress_hook}, cb) -> +exports.run = run = ({coinType, passphrase, salt, progress_hook}, cb) -> + networkVersion(coinType) d = {} seeds = [] diff --git a/src/js/bselect.js b/src/js/bselect.js new file mode 100644 index 0000000..ac12518 --- /dev/null +++ b/src/js/bselect.js @@ -0,0 +1,608 @@ +/*! + * BSelect v0.3.4 - 2013-07-11 + * + * Created by Gustavo Henke + * http://gustavohenke.github.io/bselect/ + */ +(function( $, undefined ) { + "use strict"; + + var elements = 0; + var dataName = "bselect"; + var instances = []; + var bootstrapButtonSizes = [ "mini", "small", "large" ]; + var sliceArray = Array.prototype.slice; + + var methods = { + // Get/set options of the component + option: function( option, value ) { + var curr = this.data( dataName ).options || {}, + prev = $.extend( {}, curr ); + + if ( typeof option === "string" && option[ 0 ] !== "_" ) { + if ( value === undefined ) { + return curr[ option ]; + } else { + curr[ option ] = value; + updateOptions( this, prev, curr ); + + return this; + } + } else if ( $.isPlainObject( option ) ) { + $.extend( curr, option ); + updateOptions( this, prev, curr ); + + this.data( dataName ).options = curr; + } + + return curr; + }, + + // Retrieve the BSelect container + element: function() { + return this.data( dataName ).element; + }, + + toggle: function( e ) { + if ( this[ 0 ].disabled ) { + return this; + } + + var bselect = _callMethod( this, "element" ); + + if ( e instanceof $.Event ) { + var option = _callMethod( this, "option", "showOn" ); + //e.stopPropagation(); + + if ( $( e.target ).is( ".bselect-label" ) && option !== "both" ) { + return this; + } + } + + if ( bselect.find( ".bselect-dropdown" ).is( ":hidden" ) ) { + _callMethod( this, "show" ); + } else { + _callMethod( this, "hide" ); + } + + return this; + }, + show: function() { + var searchInput, activeItem, bselect, dropdown, inputWidth; + var data = this.data( dataName ); + + if ( this[ 0 ].disabled || data.open ) { + return this; + } + + bselect = data.element; + dropdown = bselect.find( ".bselect-dropdown" ); + + dropdown.css( "left", "-9999em" ).show(); + adjustDropdownHeight( bselect ); + + // Adjust the scrolling to match the current select option position - issue #10 + activeItem = bselect.find( ".bselect-option.active" ); + if ( activeItem.length ) { + var optionList = bselect.find( ".bselect-option-list" ), + activeItemPos = activeItem.position().top, + optionListPos = optionList.position().top; + + if ( activeItemPos - optionListPos < optionList.height() ) { + optionList.scrollTop( 0 ); + } else { + optionList.scrollTop( activeItemPos - optionListPos ); + } + } + + dropdown.hide().css( "left", "auto" ); + + dropdown.slideDown( _callMethod( this, "option", "animationDuration" ) ); + this.data( dataName, $.extend( data, { + open: true + })); + + // The following class will allow us to show that nice inset shadow in .dropdown-toggle + bselect.addClass( "open" ); + + // Adjust the size of the search input to match the container inner width + searchInput = bselect.find( ".bselect-search-input" ).focus(); + inputWidth = searchInput.parent().width() - searchInput.next().outerWidth(); + searchInput.innerWidth( inputWidth ); + + bselect.find( ".bselect-search-input" ).attr( "aria-expanded", "true" ); + + return this; + }, + hide: function( clear ) { + var data = this.data( dataName ); + if ( this[ 0 ].disabled || !data.open ) { + return this; + } + + var options = data.options, + bselect = data.element; + + clear = clear === undefined ? true : clear; + + this.data( dataName, $.extend( data, { + open: false + })); + + bselect.find( ".bselect-dropdown" ).slideUp( options.animationDuration ); + bselect.removeClass( "open" ); + + // Clear the search input and the results, if that's case + if ( clear && options.clearSearchOnExit ) { + _callMethod( this, "clearSearch" ); + } + + bselect.find( ".bselect-search-input" ).attr( "aria-expanded", "false" ); + + return this; + }, + select: function( arg ) { + var $elem, val; + var bselect = _callMethod( this, "element" ); + + if ( arg instanceof $.Event ) { + $elem = $( arg.currentTarget ); + } else { + $elem = bselect.find( "li" ).eq( arg ); + + if ( !$elem.length ) { + return this; + } + } + + // Remove the highlighted status from any previously selected item... + var index = bselect.find( "li" ) + .removeClass( "active" ) + .attr( "aria-selected", "false" ) + .index( $elem ); + + var option = this.find( "option[value!='']" ).get( index ); + + // Trigger the selected event + this.trigger( "bselectselect", [ option ] ); + + // ...and add to the new selected item :) + val = $elem.addClass( "active" ).data( "value" ); + $elem.attr( "aria-selected", "true" ); + + bselect.find( ".bselect-label" ).text( $elem.text() ); + _callMethod( this, "hide" ); + + // We'll keep up-to-date the old select, too + this.data( dataName ).tempDisable = true; + this.val( val ).trigger( "change" ); + + // Trigger the selected event + this.trigger( "bselectselected", [ val, option ] ); + + return this; + }, + + // Searches every item in the list for the given text + search: function( arg ) { + var listItems, listItem, i, len, results; + var options = _callMethod( this, "option" ); + var searched = arg instanceof $.Event ? arg.target.value : arg; + var bselect = _callMethod( this, "element" ); + + if ( this[ 0 ].disabled ) { + return this; + } + + // Avoid searching for nothing + if ( searched === "" ) { + _callMethod( this, "clearSearch" ); + } + + if ( !( arg instanceof $.Event ) ) { + bselect.find( ".bselect-search" ).val( searched ); + } + + // Same search/few chars? We won't search then! + if ( + ( searched === options.lastSearch ) || + ( searched.length < options.minSearchInput ) + ) { + return; + } + + // Initialize the result collection + results = $(); + + listItems = bselect.find( "li" ).hide(); + for ( i = 0, len = listItems.length; i < len; i++ ) { + listItem = listItems[ i ]; + if ( listItem.textContent.toLowerCase().indexOf( searched.toLowerCase() ) > -1 ) { + results = results.add( $( listItem ).show() ); + } + } + + if ( results.length === 0 ) { + showNoOptionsAvailable( this ); + } else { + bselect.find( ".bselect-message" ).hide(); + } + + this.trigger( "bselectsearch", [ searched, results ] ); + + adjustDropdownHeight( listItems.end() ); + return this; + }, + + clearSearch: function() { + var bselect = _callMethod( this, "element" ); + + bselect.find( ".bselect-search-input" ).val( "" ); + bselect.find( "li" ).show(); + bselect.find( ".bselect-message" ).hide(); + + adjustDropdownHeight( bselect ); + + return this; + }, + + // Disable the bselect instance + disable: function() { + if ( !this[ 0 ].disabled ) { + _callMethod( this, "element" ).addClass( "disabled" ); + this.prop( "disabled", true ); + } + + return this; + }, + + // Enable the bselect instance + enable: function() { + if ( this[ 0 ].disabled ) { + _callMethod( this, "element" ).removeClass( "disabled" ); + this.prop( "disabled", false ); + } + + return this; + }, + + // Refreshes the option list. Useful when new HTML is added + refresh: function() { + var bselect = _callMethod( this, "element" ); + var optionList = bselect.find( ".bselect-option-list" ).empty(); + var mapping = {}; + var i = 0; + + bselect.toggleClass( "disabled", this.prop( "disabled" ) ); + + this.find( "option, > optgroup" ).each(function() { + var classes, li; + var isOption = $( this ).is( "option" ); + + if ( isOption && !this.value ) { + return; + } + + if ( isOption ) { + classes = "bselect-option"; + if ( $( this ).closest( "optgroup" ).length ) { + classes += " grouped"; + } + } else { + classes = "bselect-option-group"; + } + + li = $( "
  • " ).attr({ + "class": classes, + // While there aren't roles for optgroup, we'll stick with the role option. + role: "option", + tabindex: isOption ? 2 : -1, + "aria-selected": "false" + }); + + if ( isOption ) { + li.data( "value", this.value ); + mapping[ this.value ] = i; + + li.html( "" + this.text + "" ); + } else { + li.text( this.label ); + } + + li.appendTo( optionList ); + i++; + }); + + if ( i === 0 ) { + showNoOptionsAvailable( this ); + } + + this.data( dataName ).itemsMap = mapping; + return this; + }, + + destroy: function() { + var bselect = _callMethod( this, "element" ); + this.data( dataName, null ); + + // Remove our cached thing + instances.splice( instances.indexOf( this ), 1 ); + + bselect.remove(); + this.removeClass( "bselect-inaccessible" ).unbind( ".bselect" ); + return this; + } + }; + + // Determine whether an DOM Element has bselect instance + function hasBSelect( el ) { + return $.isPlainObject( $( el ).data( dataName ) ); + } + + // Helper function that will call an BSelect method in the context of $elem + function _callMethod( $elem, method ) { + if ( methods[ method ] !== undefined ) { + return methods[ method ].apply( $elem, sliceArray.call( arguments, 2 ) ); + } + + return $elem; + } + + /** + * Get the placeholder of an element. + * Retrieves in the following order: + * - bselect options + * - .data("placeholder") / attribute data-placeholder + * - Default bselect i18n "selectAnOption" + */ + function getPlaceholder( $elem ) { + return _callMethod( $elem, "option", "placeholder" ) || + $elem.data( "placeholder" ) || + $.bselect.i18n.selectAnOption; + } + + // Adjusts the dropdown height of an bselect. + function adjustDropdownHeight( $elem ) { + var list = $elem.find( ".bselect-option-list" ); + var len = list.find( "li:visible" ).length; + + list.innerHeight( parseInt( list.css( "line-height" ), 10 ) * 1.5 * ( len < 5 ? len : 5 ) ); + } + + // Updates visual properties of the bselect after the plugin was initialized + function updateOptions( $elem, prev, curr ) { + var bselect = _callMethod( $elem, "element" ); + + $.each( prev, function(key, val) { + if ( curr[ key ] !== val ) { + if ( key === "size" ) { + var sizes = $.map( bootstrapButtonSizes.slice( 0 ), function( size ) { + return "bselect-" + size; + }).join( " " ); + + bselect.removeClass( sizes ); + if ( bootstrapButtonSizes.indexOf( curr.size ) > -1 ) { + bselect.addClass( "bselect-" + curr.size ); + } + } + } + }); + } + + // Show the 'no options available' message + function showNoOptionsAvailable( $elem ) { + var bselect = _callMethod( $elem, "element" ); + bselect.find( ".bselect-message" ).text( $.bselect.i18n.noOptionsAvailable ).show(); + } + + /** + * Handle keypress on the search input and on the options. + * - On the search input: arrow up goes to the last visible item, while arrow down + * does the opposite. + * - In the options, arrows are used to navigate and enter to select. + */ + function handleKeypress( e ) { + if ( e.keyCode !== 38 && e.keyCode !== 40 && e.keyCode !== 13 ) { + return; + } + + var $this = $( this ), + isInput = $this.is( ".bselect-search-input" ); + + switch ( e.keyCode ) { + // UP + case 38: + if ( isInput ) { + $( e.delegateTarget ).find( ".bselect-option:visible:last" ).focus(); + } else { + $this.prevAll( ".bselect-option:visible" ).eq( 0 ).focus(); + } + break; + + // DOWN + case 40: + if ( isInput ) { + $( e.delegateTarget ).find( ".bselect-option:visible:first" ).focus(); + } else { + $this.nextAll( ".bselect-option:visible" ).eq( 0 ).focus(); + } + break; + + // ENTER + case 13: + if ( !isInput ) { + $this.trigger( "click" ); + } + break; + } + + return false; + } + + // Run all the setup stuff + function setup( elem, options ) { + var caret, label, container, id, dropdown; + var $elem = $( elem ); + + // First of, let's build the base HTML of BSelect + id = ++elements; + container = $( "
    ", { + id: "bselect-" + id + }); + + dropdown = $( "
    " ); + + // Configure the search input + if ( options.searchInput === true ) { + var search = $( "