├── .gitignore ├── content ├── art_assets │ ├── bg1.jpg │ └── cards │ │ ├── tableau_ph.png │ │ └── playing_card_assets_large.png ├── font_awesome │ ├── font │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ └── fontawesome-webfont.woff │ └── css │ │ ├── font-awesome.min.css │ │ └── font-awesome.css ├── sound_assets │ └── card_sounds │ │ ├── cardflip.mp3 │ │ ├── cardflip.ogg │ │ └── cardflip.wav ├── site.css └── spider.css ├── .idea ├── jsLibraryMappings.xml └── libraries │ ├── Knockout_2_3_0.xml │ └── jQuery.xml ├── meta └── Licenses.txt ├── README.md ├── LICENSE.md ├── scripts ├── spider │ ├── fSpider.card.deck.js │ ├── fSpider.vmHub.js │ ├── fSpider.debug.js │ ├── fSpider.state.js │ ├── fSpider.utils.js │ ├── fSpider.ui.draggable.js │ ├── fSpider.history.js │ ├── fSpider.ui.modal.js │ ├── fSpider.settings.js │ ├── fSpider.card.groups.js │ └── fSpider.card.js └── howler │ └── howler.min.js └── default.html /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ project files 2 | .idea 3 | *.iml 4 | out 5 | gen 6 | -------------------------------------------------------------------------------- /content/art_assets/bg1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzley/fSpider/HEAD/content/art_assets/bg1.jpg -------------------------------------------------------------------------------- /content/art_assets/cards/tableau_ph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzley/fSpider/HEAD/content/art_assets/cards/tableau_ph.png -------------------------------------------------------------------------------- /content/font_awesome/font/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzley/fSpider/HEAD/content/font_awesome/font/FontAwesome.otf -------------------------------------------------------------------------------- /content/sound_assets/card_sounds/cardflip.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzley/fSpider/HEAD/content/sound_assets/card_sounds/cardflip.mp3 -------------------------------------------------------------------------------- /content/sound_assets/card_sounds/cardflip.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzley/fSpider/HEAD/content/sound_assets/card_sounds/cardflip.ogg -------------------------------------------------------------------------------- /content/sound_assets/card_sounds/cardflip.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzley/fSpider/HEAD/content/sound_assets/card_sounds/cardflip.wav -------------------------------------------------------------------------------- /content/font_awesome/font/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzley/fSpider/HEAD/content/font_awesome/font/fontawesome-webfont.eot -------------------------------------------------------------------------------- /content/font_awesome/font/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzley/fSpider/HEAD/content/font_awesome/font/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /content/font_awesome/font/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzley/fSpider/HEAD/content/font_awesome/font/fontawesome-webfont.woff -------------------------------------------------------------------------------- /content/art_assets/cards/playing_card_assets_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzley/fSpider/HEAD/content/art_assets/cards/playing_card_assets_large.png -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /meta/Licenses.txt: -------------------------------------------------------------------------------- 1 | ///////////////////\\\\\\\\\\\\\\\\\\ 2 | //////Vectorized Playing Cards\\\\\\\ 3 | \\\\\\\\\\\\\\\\\\\/////////////////// 4 | Vectorized Playing Cards 1.3- http://code.google.com/p/vectorized-playing-cards/ 5 | Copyright 2011 - Chris Aguilar 6 | Licensed under LGPL 3 - www.gnu.org/copyleft/lesser.html 7 | ///////////////////\\\\\\\\\\\\\\\\\\ 8 | \\\\\\Vectorized Playing Cards//////// 9 | \\\\\\\\\\\\\\\\\\//////////////////// -------------------------------------------------------------------------------- /.idea/libraries/Knockout_2_3_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/jQuery.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /content/site.css: -------------------------------------------------------------------------------- 1 | html { 2 | margin: 0; 3 | height: 100%; 4 | width: 100%; 5 | } 6 | 7 | body { 8 | margin: 0; 9 | height: 100%; 10 | width: 100%; 11 | font-size: .85em; 12 | font-family: "Segoe UI", Verdana, Helvetica, sans-serif; 13 | color: #232323; 14 | background-color: #fff; 15 | } 16 | 17 | header, footer, nav, section { 18 | display: block; 19 | } 20 | 21 | fieldset { 22 | border: 1px solid #ddd; 23 | padding: 0 1.4em 1.4em 1.4em; 24 | margin: 0 0 1.5em 0; 25 | } 26 | 27 | legend { 28 | font-size: 1.2em; 29 | font-weight: bold; 30 | } 31 | 32 | textarea { 33 | min-height: 75px; 34 | } 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Just a simple Spider Solitaire clone, written in javascript. 2 | The project utilizes [KineticJS](http://kineticjs.com/) for the canvas/drawing and [howler](http://goldfirestudios.com/blog/104/howler.js-Modern-Web-Audio-Javascript-Library) for the sound effects. 3 | 4 | **Feel free to embed this game on your own website. I only ask that you credit me somehow (a link to this github page would be good).** 5 | 6 | The [latest version of the game](http://fuzzley.info/spider/) is hosted on http://fuzzley.info/spider/. You may have to clear your cache to see changes. If you find any problems, or if you'd like to see a feature implemented, please let me know :). 7 | 8 | Have fun! 9 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Andrey Gavel andrey.gavel@gmail.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /scripts/spider/fSpider.card.deck.js: -------------------------------------------------------------------------------- 1 | var fSpider = fSpider || {}; 2 | 3 | fSpider.Deck = (function (Deck, undefined) { 4 | 'use strict'; 5 | 6 | //constructor 7 | Deck = function () { 8 | }; 9 | 10 | //fields 11 | Deck.prototype.cards = []; 12 | 13 | //getters/setters 14 | Deck.prototype.getCards = function () { 15 | return this.cards; 16 | }; 17 | Deck.prototype.setCards = function (cards) { 18 | this.cards = cards; 19 | }; 20 | 21 | //methods 22 | Deck.prototype.shuffle = function () { 23 | var newIndex, temp; 24 | 25 | var length = this.getSize(); 26 | for (var i = 0; i < length; i++) { 27 | newIndex = Math.round(Math.random() * (length - 1)); 28 | 29 | temp = this.getCardAt(newIndex); 30 | this.setCardAt(newIndex, this.cards[i]); 31 | this.setCardAt(i, temp); 32 | } 33 | }; 34 | 35 | Deck.prototype.getCardAt = function (index) { 36 | return this.cards[index]; 37 | }; 38 | 39 | Deck.prototype.setCardAt = function (index, card) { 40 | this.cards[index] = card; 41 | }; 42 | 43 | Deck.prototype.getSize = function () { 44 | return (this.cards || []).length; 45 | }; 46 | 47 | return Deck; 48 | })(fSpider.Deck || {}); -------------------------------------------------------------------------------- /scripts/spider/fSpider.vmHub.js: -------------------------------------------------------------------------------- 1 | var fSpider = fSpider || {}; 2 | 3 | fSpider.vmHub = (function (vmHub, $, ko, undefined) { 4 | 'use strict'; 5 | 6 | ko.bindingHandlers.timeShortText = { 7 | init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 8 | }, 9 | update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 10 | var value = ko.utils.unwrapObservable(valueAccessor()); 11 | if (value == null || isNaN(value) === true) { 12 | value = 0; 13 | } 14 | var valueF = fSpider.Utils.formatTime(value); 15 | $(element).text(valueF); 16 | } 17 | }; 18 | 19 | ko.bindingHandlers.timeShortValue = { 20 | init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 21 | }, 22 | update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 23 | var value = ko.utils.unwrapObservable(valueAccessor()); 24 | if (value == null || isNaN(value) === true) { 25 | value = 0; 26 | } 27 | var valueF = fSpider.Utils.formatTime(value); 28 | $(element).val(valueF); 29 | } 30 | }; 31 | 32 | vmHub.hubs = {}; 33 | 34 | vmHub.registerVM = function (vmName, vm) { 35 | vmHub.hubs[vmName] = vm; 36 | }; 37 | 38 | vmHub.bind = function (element) { 39 | ko.applyBindings(vmHub.hubs, element); 40 | }; 41 | 42 | return vmHub; 43 | })(fSpider.vmHub || {}, window.jQuery, window.ko); -------------------------------------------------------------------------------- /scripts/spider/fSpider.debug.js: -------------------------------------------------------------------------------- 1 | var fSpider = fSpider || {}; 2 | 3 | fSpider.Debug = (function (Debug, undefined) { 4 | 'use strict'; 5 | 6 | //constructor 7 | Debug = function (board) { 8 | this.board = board; 9 | }; 10 | 11 | //fields 12 | Debug.prototype.board = null; 13 | 14 | //functions 15 | Debug.prototype.prepareDrawCompleteSequenceTest = function () { 16 | Debug.prepareDrawCompleteSequenceTest.call(this.board); 17 | }; 18 | 19 | Debug.prepareDrawCompleteSequenceTest = function (b) { 20 | b.tableauPiles.forEach(function (tPile) { 21 | b.stockPile.transferCards(tPile.cards); 22 | }); 23 | var cards = []; 24 | for (var i = fSpider.PlayingCard.CARD_TYPES.king; i >= fSpider.PlayingCard.CARD_TYPES.ace; i--) 25 | { 26 | for (var j = 0; j < b.deck.getSize(); j++) 27 | { 28 | if (b.deck.cards[j].getType() === i) { 29 | cards.push(b.deck.cards[j]); 30 | b.deck.cards[j].setFaceUp(true); 31 | break; 32 | } 33 | } 34 | } 35 | b.tableauPiles[0].transferCards(cards.slice(0, 12)); 36 | b.tableauPiles[0].arrangeCards(fSpider.board.settings.extendAnimate(false)); 37 | b.tableauPiles[0].resetListening(); 38 | b.tableauPiles[0].resetDraggable(); 39 | b.stockPile.cards.splice(b.stockPile.cards.indexOf(cards[12]), 1); 40 | b.stockPile.cards.push(cards[12]); 41 | b.stockPile.resetCardFaces(); 42 | b.stockPile.resetListening(); 43 | b.stockPile.resetDraggable(); 44 | b.stockPile.arrangeCards(); 45 | b.stockPile.moveAllCardsToGroup(); 46 | b.tableauPiles.forEach(function (tPile, index) { 47 | if (index != 0) { 48 | tPile.transferCards([b.stockPile.cards[0]]); 49 | tPile.resetCardFaces(); 50 | tPile.resetListening(); 51 | tPile.resetDraggable(); 52 | } 53 | }); 54 | b.redraw(); 55 | }; 56 | 57 | return Debug; 58 | })(fSpider.Debug || {}); -------------------------------------------------------------------------------- /scripts/spider/fSpider.state.js: -------------------------------------------------------------------------------- 1 | var fSpider = fSpider || {}; 2 | 3 | fSpider.SpiderState = (function (SpiderState, undefined) { 4 | 'use strict'; 5 | 6 | //constructor 7 | SpiderState = function (board) { 8 | this.board = board; 9 | }; 10 | 11 | //fields 12 | SpiderState.prototype.board = null; 13 | SpiderState.prototype.hintCursor = { 14 | card: null, 15 | toPile: null 16 | }; 17 | 18 | //functions 19 | SpiderState.prototype.boardStateChanged = function () { 20 | this.hintCursor.card = null; 21 | this.hintCursor.toPile = null; 22 | }; 23 | 24 | SpiderState.prototype.nextHint = function () { 25 | var hint = { 26 | card: this.hintCursor.card, 27 | toPile: this.hintCursor.toPile 28 | }; 29 | 30 | var tPile = this.hintCursor.toPile; 31 | if (this.hintCursor.card != null) { 32 | tPile = this.findNextPileThatCanBeMovedTo(this.hintCursor.card, tPile); 33 | } 34 | 35 | this.moveHintCursorForward(); 36 | 37 | return hint; 38 | }; 39 | 40 | SpiderState.prototype.moveHintCursorForward = function () { 41 | this.hintCursor.card = this.findNextCardThatCanBeMoved(this.hintCursor.card); 42 | }; 43 | 44 | SpiderState.prototype.findNextCardThatCanBeMoved = function (previousCard) { 45 | if (this.board.tableauPiles == null || this.board.tableauPiles.length <= 0) { 46 | return null; 47 | } 48 | 49 | var tPile = null; 50 | //if cursor was reset, check first pile 51 | var card = null; 52 | if (previousCard == null) { 53 | tPile = this.board.tableauPiles[0]; 54 | card = tPile.getFirstCardThatCanRemove(); 55 | if (card != null) { //if something found in first pile, just exit 56 | return card; 57 | } 58 | } else { //otherwise find the current pile 59 | tPile = this.board.tableauPiles.indexOf(previousCard.getPile()); 60 | } 61 | var oIndex = this.board.tableauPiles.indexOf(tPile) + 1; 62 | var rIndex; 63 | //look for candidate in each pile 64 | for (var i = oIndex; i < oIndex + this.board.tableauPiles.length; i++) { 65 | rIndex = i % this.board.tableauPiles.length; 66 | card = this.board.tableauPiles[rIndex].getFirstCardThatCanRemove(); 67 | if (card != null) { 68 | break; 69 | } 70 | } 71 | 72 | return card; 73 | }; 74 | 75 | SpiderState.prototype.findNextPileThatCanBeMovedTo = function (cardToMove, previousPile) { 76 | if (previousPile == null) { 77 | previousPile = cardToMove.getPile(); 78 | } 79 | 80 | var tPile = previousPile; 81 | var oIndex = this.board.tableauPiles.indexOf(tPile) + 1; 82 | var rIndex; 83 | //look for candidate in each pile 84 | for (var i = oIndex; i < oIndex + this.board.tableauPiles.length; i++) { 85 | rIndex = i % this.board.tableauPiles.length; 86 | tPile = this.board.tableauPiles[rIndex]; 87 | if (tPile.canAddCard(cardToMove) === true) { 88 | return tPile; 89 | } 90 | } 91 | return null; 92 | }; 93 | 94 | 95 | return SpiderState; 96 | })(fSpider.SpiderState || {}); -------------------------------------------------------------------------------- /scripts/spider/fSpider.utils.js: -------------------------------------------------------------------------------- 1 | var fSpider = fSpider || {}; 2 | 3 | fSpider.Utils = (function (Utils, undefined) { 4 | 'use strict'; 5 | 6 | Utils.extendObj = function(childObj, parentObj) { 7 | //http://davidshariff.com/blog/javascript-inheritance-patterns/ 8 | var tmpObj = function () {}; 9 | tmpObj.prototype = parentObj.prototype; 10 | childObj.prototype = new tmpObj(); 11 | childObj.prototype.constructor = childObj; 12 | }; 13 | 14 | Utils.extendProps = function (childObj, parentObj) { 15 | if (childObj == null) { 16 | childObj = {}; 17 | } 18 | 19 | var key; 20 | for (key in parentObj) { 21 | if (childObj[key] == null) { 22 | childObj[key] = parentObj[key]; 23 | } 24 | } 25 | return childObj; 26 | }; 27 | 28 | Utils.filterOutProperties = function (obj, ignoreProps, ignoreValues, allowFunctions) { 29 | obj = obj || {}; 30 | ignoreProps = ignoreProps || {}; 31 | ignoreValues = ignoreValues || {}; 32 | 33 | var newObj = {}; 34 | var valid; 35 | 36 | for (var option in obj) { 37 | //check for function 38 | if (typeof (obj[option]) === 'function' && allowFunctions !== true) { 39 | continue; 40 | } 41 | 42 | valid = true; 43 | 44 | //check ignore properties 45 | for (var propIndex in ignoreProps) { 46 | if (option === ignoreProps[propIndex]) { 47 | valid = false; 48 | break; 49 | } 50 | } 51 | 52 | if (valid !== true) { 53 | continue; 54 | } 55 | 56 | //check ignore values 57 | for (var valIndex in ignoreValues) { 58 | if (obj[option] === ignoreValues[valIndex]) { 59 | valid = false; 60 | break; 61 | } 62 | } 63 | 64 | if (valid !== true) { 65 | continue; 66 | } 67 | 68 | newObj[option] = obj[option]; 69 | } 70 | 71 | return newObj; 72 | }; 73 | 74 | Utils.filterInProperties = function (obj, props, ignoreValues) { 75 | obj = obj || {}; 76 | props = props || {}; 77 | ignoreValues = ignoreValues || {}; 78 | 79 | var newObj = {}; 80 | for (var i = 0; i < props.length; i++) { 81 | if (obj.hasOwnProperty(props[i]) && ignoreValues.indexOf(obj[props[i]]) < 0) { 82 | newObj[props[i]] = obj[props[i]]; 83 | } 84 | } 85 | return newObj; 86 | }; 87 | 88 | Utils.isPointInBounds = function (point, bounds) { 89 | var xValid = point.x >= bounds.x && point.x <= (bounds.x + bounds.width); // x in bounds 90 | var yValid = point.y >= bounds.y && point.y <= (bounds.y + bounds.height); //y in bounds 91 | return xValid && yValid; 92 | }; 93 | 94 | Utils.doRectsIntersect = function (rect1, rect2) { 95 | return rect1.x < (rect2.x + rect2.width) && (rect1.x + rect1.width) > rect2.x 96 | && rect1.y < (rect2.y + rect2.height) && (rect1.y + rect1.height) > rect2.y; 97 | }; 98 | 99 | Utils.distance = function (pnt1, pnt2) { 100 | var dX = pnt2.x - pnt1.x; 101 | var dY = pnt2.y - pnt1.y; 102 | 103 | return Math.sqrt((dX * dX) + (dY * dY)); 104 | }; 105 | 106 | Utils.formatPointToLayer = function (point, layer, scale) { 107 | var frmtedPoint = { x: point.x, y: point.y }; 108 | 109 | if (frmtedPoint.x != null) { 110 | frmtedPoint.x -= layer.getAbsolutePosition().x; 111 | if (scale != null && scale !== 0) { 112 | frmtedPoint.x /= scale; 113 | } 114 | } 115 | 116 | if (frmtedPoint.y != null) { 117 | frmtedPoint.y -= layer.getAbsolutePosition().y; 118 | if (scale != null && scale !== 0) { 119 | frmtedPoint.y /= scale; 120 | } 121 | } 122 | 123 | return frmtedPoint; 124 | }; 125 | 126 | Utils.formatTime = function (timeMS) { 127 | var timeStr = ''; 128 | 129 | var remaining = timeMS; 130 | var hours = Math.floor(remaining / 3600000); 131 | remaining %= 3600000; 132 | var mins = Math.floor(remaining / 60000); 133 | remaining %= 60000; 134 | var secs = Math.floor(remaining / 1000); 135 | 136 | if (hours > 0) { 137 | if (hours < 10) { 138 | timeStr += '0'; 139 | } 140 | timeStr += String(hours); 141 | timeStr += ':'; 142 | } 143 | 144 | if (mins <= 0) { 145 | timeStr += '00:'; 146 | } else { 147 | if (mins < 10) { 148 | timeStr += '0'; 149 | } 150 | timeStr += String(mins); 151 | timeStr += ':'; 152 | } 153 | 154 | if (secs <= 0) { 155 | timeStr += '00'; 156 | } else { 157 | if (secs < 10) { 158 | timeStr += '0'; 159 | } 160 | timeStr += String(secs); 161 | } 162 | 163 | return timeStr; 164 | }; 165 | 166 | return Utils; 167 | })(fSpider.Utils || {}); -------------------------------------------------------------------------------- /content/spider.css: -------------------------------------------------------------------------------- 1 | #canvas-wrap { 2 | height: 100%; 3 | overflow: hidden; 4 | background: url(art_assets/bg1.jpg) no-repeat; 5 | background-size: cover; 6 | } 7 | 8 | #canvas-resources { 9 | display: none; 10 | } 11 | 12 | #ui-container { 13 | position: absolute; 14 | top: 0; 15 | bottom: 0; 16 | left: 0; 17 | right: 0; 18 | pointer-events: none; 19 | } 20 | 21 | .lite-red { 22 | color: #fff2f2; 23 | } 24 | 25 | .lite-green { 26 | color: #e4ffe5; 27 | } 28 | 29 | .lite-yellow { 30 | color: #fcfedf; 31 | } 32 | 33 | .clear:after { 34 | content: ""; 35 | display: block; 36 | clear: both; 37 | } 38 | 39 | /* MODAL */ 40 | 41 | .modal { 42 | opacity: .7; 43 | display: inline-block; 44 | position: absolute; 45 | pointer-events: auto; 46 | } 47 | 48 | .modal:hover { 49 | opacity: 1; 50 | } 51 | 52 | .modal-controls, .modal-control, .modal-title, .modal-left, .modal-right { 53 | display: inline-block; 54 | } 55 | 56 | /* MODAL - left */ 57 | 58 | /* MODAL -left - top */ 59 | 60 | .modal-left-top, .modal-right-top { 61 | font-size: .8em; 62 | vertical-align: bottom; 63 | position: relative; 64 | z-index: 5; 65 | opacity: .6; 66 | color: #e7f2c3; 67 | border-radius: .5em .5em 0 0; 68 | } 69 | 70 | .modal-left-top { 71 | background-color: #333333; 72 | border: black solid .1em; 73 | } 74 | 75 | .modal-left-top, .modal-title { 76 | cursor: grab; 77 | cursor: -moz-grab; 78 | cursor: -webkit-grab; 79 | } 80 | 81 | .modal-left-top:active, .modal-title:active { 82 | cursor: grabbing; 83 | cursor: -moz-grabbing; 84 | cursor: -webkit-grabbing; 85 | } 86 | 87 | .modal-left-top:hover, modal-right-top:hover { 88 | opacity: 1; 89 | } 90 | 91 | .modal-title { 92 | float: left; 93 | color: lightgray; 94 | padding: 0 .1em; 95 | } 96 | 97 | .modal-controls { 98 | cursor: default; 99 | text-align: center; 100 | float: right; 101 | margin: 0 0 .1em .25em; 102 | } 103 | 104 | .modal-control { 105 | cursor: default; 106 | text-align: center; 107 | vertical-align: bottom; 108 | opacity: .8; 109 | padding: 0 .1em; 110 | margin: 0 .1em; 111 | } 112 | 113 | .modal-control:hover { 114 | opacity: 1; 115 | color: black; 116 | background-color: white; 117 | } 118 | 119 | /* MODAL - left - bottom */ 120 | 121 | .modal-left-bottom { 122 | padding: .2em .35em; 123 | background: black; 124 | opacity: 0.8; 125 | color: white; 126 | border-radius: 0 0 .4em .4em; 127 | } 128 | 129 | .modal-left-bottom:hover { 130 | opacity: 1; 131 | } 132 | 133 | /* MODAL - right */ 134 | .modal-right { 135 | vertical-align: top; 136 | opacity: 0.7; 137 | color: #ffffff; 138 | } 139 | 140 | .modal-right:hover { 141 | opacity: 1; 142 | } 143 | 144 | /* MODAL - right - top */ 145 | .modal-right-top { 146 | min-height: 1.45em; 147 | } 148 | 149 | /* MODAL - right - bottom */ 150 | 151 | .modal-right-bottom { 152 | background-color: black; 153 | border-top-right-radius: .4em; 154 | border-bottom-right-radius: .4em; 155 | } 156 | 157 | .modal-drag-handle { 158 | width: .55em; 159 | height: 1.3em; 160 | cursor: grab; 161 | cursor: -moz-grab; 162 | cursor: -webkit-grab; 163 | } 164 | 165 | .modal-drag-handle:active { 166 | cursor: grabbing; 167 | cursor: -moz-grabbing; 168 | cursor: -webkit-grabbing; 169 | } 170 | 171 | .modal-btn { 172 | cursor: default; 173 | } 174 | 175 | /* MODAL */ 176 | 177 | /* Global Options Dlg */ 178 | 179 | #global-settings-open-wrap { 180 | position: absolute; 181 | background: black; 182 | opacity: 0.8; 183 | border-radius: .5em; 184 | pointer-events: auto; 185 | bottom: 1em; 186 | right: 1em; 187 | } 188 | 189 | #global-settings-open-wrap:hover { 190 | opacity: 1; 191 | } 192 | 193 | #global-settings-open-btn { 194 | font-size: 1.5em; 195 | } 196 | 197 | #dim-overlay { 198 | position: absolute; 199 | top: 0; 200 | bottom: 0; 201 | left: 0; 202 | right: 0; 203 | background-color: black; 204 | opacity: 0.5; 205 | z-index: 1000; 206 | pointer-events: auto; 207 | } 208 | 209 | #global-options-dlg { 210 | opacity: 0.9; 211 | position: absolute; 212 | width: 11em; 213 | height: 23em; 214 | z-index: 1001; 215 | background: black; 216 | border-radius: .75em; 217 | padding: .3em; 218 | color: white; 219 | border: #191919 solid .15em; 220 | box-shadow: #3b3b3b .1em .1em; 221 | pointer-events: auto; 222 | } 223 | 224 | #global-options-header { 225 | width: 100%; 226 | height: 1.5em; 227 | position: relative; 228 | background-color: #161600; 229 | border-top-left-radius: .75em; 230 | border-top-right-radius: .75em; 231 | padding: 0 .2em; 232 | margin: -.2em -.2em -.2em -.2em; 233 | cursor: grab; 234 | cursor: -moz-grab; 235 | cursor: -webkit-grab; 236 | } 237 | 238 | #global-options-header:active { 239 | cursor: grabbing; 240 | cursor: -moz-grabbing; 241 | cursor: -webkit-grabbing; 242 | } 243 | 244 | #global-options-close-btn { 245 | cursor: default; 246 | border-radius: .3em; 247 | padding: 0.1em; 248 | } 249 | 250 | #global-options-close-btn:hover { 251 | background: white; 252 | color: black; 253 | } 254 | 255 | .global-options-section { 256 | border-radius: .5em; 257 | margin-bottom: -.25em; 258 | padding: .4em; 259 | } 260 | 261 | .global-options-section legend { 262 | font-size: 1em; 263 | color: white; 264 | display: block; 265 | } 266 | 267 | .global-options-section button { 268 | width: 100%; 269 | } 270 | 271 | /* Global Options Dlg */ 272 | 273 | /* Custom Buttons */ 274 | /* http://www.bestcssbuttongenerator.com/ */ 275 | button { 276 | border-radius: .3em; 277 | background-color: #191919; 278 | color: white; 279 | border: gray solid .1em; 280 | } 281 | 282 | button:hover { 283 | background-color: black; 284 | } 285 | 286 | button:disabled { 287 | background-color: #4e4e4e; 288 | color: #797979; 289 | } 290 | 291 | /* Custom Buttons */ -------------------------------------------------------------------------------- /scripts/spider/fSpider.ui.draggable.js: -------------------------------------------------------------------------------- 1 | (function ($, window, document, undefined) { 2 | 'use strict'; 3 | 4 | $.fn.draggable = function (options) { 5 | var opts = $.extend({ }, $.fn.draggable.defaults, options); 6 | var $contain = $(opts.containment); 7 | 8 | return this.each(function () { 9 | var $this = $(this); 10 | 11 | var containDim = null; 12 | var dim = null; 13 | var originalPos = null; 14 | var cursor = null; 15 | var offset = {}; 16 | 17 | initialize(); 18 | 19 | function initialize() { 20 | //capture original position (for relative position type) 21 | originalPos = { left: $this.offset().left, top: $this.offset().top }; 22 | var cssPos = { 23 | left: parseFloat($this.css('left')), 24 | top: parseFloat($this.css('top')), 25 | right: parseFloat($this.css('right')), 26 | bottom: parseFloat($this.css('bottom')) 27 | }; 28 | if (isNaN(cssPos.left) !== true) { 29 | originalPos.left -= parseFloat(cssPos.left); 30 | } 31 | if (isNaN(cssPos.top) !== true) { 32 | originalPos.top -= parseFloat(cssPos.top); 33 | } 34 | 35 | //attach mousedown 36 | $this.on('mousedown', onMouseDown); 37 | 38 | //fix positions on window resize 39 | $(window).on('resize', function () { 40 | captureDimensions(); 41 | fixOverDrag(); 42 | }); 43 | 44 | captureDimensions(); 45 | fixOverDrag(); 46 | } 47 | 48 | function onMouseDown(evt) { 49 | if (isIgnoreNode(evt.target) === true || isIgnoreClass(evt.target) === true) { 50 | return; 51 | } 52 | 53 | captureDimensions(); 54 | 55 | //attach move/up listeners 56 | $(document).on('mousemove', onMouseMove); 57 | $(document).on('mouseup', onMouseUp); 58 | 59 | //change cursor 60 | cursor = document.body.style.cursor; 61 | document.body.style.cursor = opts.cursor; 62 | 63 | //capture offset 64 | offset.left = evt.clientX - $this.offset().left; 65 | offset.top = evt.clientY - $this.offset().top; 66 | 67 | $(document.body).css({ 'user-select': 'none' }); 68 | 69 | opts.dragstart.call(opts.owner || this); 70 | } 71 | 72 | function onMouseUp(evt) { 73 | //detach move/up listeners 74 | $(document).off('mouseup', onMouseUp); 75 | $(document).off('mousemove', onMouseMove); 76 | 77 | //change cursor 78 | document.body.style.cursor = cursor; 79 | 80 | $(document.body).css({ 'user-select': 'auto' }); 81 | 82 | opts.dragend.call(opts.owner || this, evt); 83 | } 84 | 85 | function onMouseMove(evt) { 86 | var pos = { 87 | left: evt.clientX - offset.left, 88 | top: evt.clientY - offset.top 89 | }; 90 | positionMe(pos); 91 | fixOverDrag(); 92 | 93 | opts.dragging.call(opts.owner || this, evt); 94 | } 95 | 96 | function positionMe(pos) { 97 | var posType = $this.css('position'); 98 | 99 | //figure out if we should use top or bottom, left or right 100 | var left, top, right, bottom; 101 | left = pos.left; 102 | top = pos.top; 103 | right = containDim.width - (left + dim.width); 104 | bottom = containDim.height - (top + dim.height); 105 | 106 | if (posType == 'relative') { 107 | left -= originalPos.left; 108 | top -= originalPos.top; 109 | } 110 | 111 | if (left < right) { 112 | $this.css({ 'left': left + 'px', 'right': '' }); 113 | } else { 114 | if (posType == 'relative') { 115 | right = dim.width - containDim.width + right + originalPos.left; 116 | } 117 | $this.css({ 'left': '', 'right': right + 'px' }); 118 | } 119 | if (top < bottom) { 120 | $this.css({ 'top': top + 'px', 'bottom': '' }); 121 | } else { 122 | if (posType == 'relative') { 123 | bottom = dim.height - containDim.height + bottom + originalPos.top; 124 | } 125 | $this.css({ 'top': '', 'bottom': bottom + 'px' }); 126 | } 127 | } 128 | 129 | function fixOverDrag() { 130 | var reposition = false; 131 | 132 | var parentPos = $contain.offset(); 133 | var pos = $this.offset(); 134 | 135 | //left 136 | if (pos.left < parentPos.left) { 137 | pos.left = 0; 138 | reposition = true; 139 | } 140 | //top 141 | if (pos.top < parentPos.top) { 142 | pos.top = 0; 143 | reposition = true; 144 | } 145 | if (opts.scroll !== true) { 146 | //right 147 | if (pos.left + dim.width > (parentPos.left + containDim.width)) { 148 | pos.left = containDim.width - dim.width; 149 | reposition = true; 150 | } 151 | //bottom 152 | if (pos.top + dim.height > (parentPos.top + containDim.height)) { 153 | pos.top = containDim.height - dim.height; 154 | reposition = true; 155 | } 156 | } 157 | 158 | if (reposition === true) { 159 | positionMe(pos); 160 | } 161 | } 162 | 163 | function isIgnoreNode(target) { 164 | return opts.ignoreNodeNames.indexOf(target.nodeName) >= 0; 165 | } 166 | 167 | function isIgnoreClass(target) { 168 | for (var i = 0; i < opts.ignoreClasses.length; i++) { 169 | if ($(target).hasClass(opts.ignoreClasses[i]) === true) { 170 | return true; 171 | } 172 | } 173 | return false; 174 | } 175 | 176 | function captureDimensions() { 177 | containDim = { width: $contain[0].clientWidth, height: $contain[0].clientHeight }; 178 | dim = { width: $this[0].clientWidth, height: $this[0].clientHeight }; 179 | } 180 | }); 181 | }; 182 | 183 | $.fn.draggable.defaults = { 184 | owner: null, 185 | containment: 'body', 186 | cursor: 'move', 187 | scroll: false, 188 | ignoreNodeNames: [ 189 | 'BUTTON', 190 | 'INPUT', 191 | 'SELECT', 192 | 'LABEL' 193 | ], 194 | ignoreClasses: [ 195 | ], 196 | dragstart: function () {}, 197 | dragging: function () {}, 198 | dragend: function ($el) {} 199 | }; 200 | })(window.jQuery, window, window.document); -------------------------------------------------------------------------------- /scripts/howler/howler.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * howler.js v1.1.14 3 | * howlerjs.com 4 | * 5 | * (c) 2013, James Simpson of GoldFire Studios 6 | * goldfirestudios.com 7 | * 8 | * MIT License 9 | */ 10 | !function(){var e={},t=null,n=!0,r=!1;if("undefined"!=typeof AudioContext)t=new AudioContext;else if("undefined"!=typeof webkitAudioContext)t=new webkitAudioContext;else if("undefined"!=typeof Audio){n=!1;try{new Audio}catch(i){r=!0}}else n=!1,r=!0;if(n){var s=void 0===t.createGain?t.createGainNode():t.createGain();s.gain.value=1,s.connect(t.destination)}var o=function(){this._volume=1,this._muted=!1,this.usingWebAudio=n,this._howls=[]};o.prototype={volume:function(e){var t=this;if(e=parseFloat(e),e&&e>=0&&1>=e){t._volume=e,n&&(s.gain.value=e);for(var r in t._howls)if(t._howls.hasOwnProperty(r)&&t._howls[r]._webAudio===!1)for(var i=0;i=2?s:o.match(/data\:audio\/([^?]+);/),!s)return t.on("loaderror"),void 0;s=s[1]}if(f[s]){n=t._urls[i];break}}if(!n)return t.on("loaderror"),void 0;if(t._src=n,t._webAudio)c(t,n);else{var a=new Audio;t._audioNode.push(a),a.src=n,a._pos=0,a.preload="auto",a.volume=u._muted?0:t._volume*u.volume(),e[n]=t;var l=function(){t._duration=a.duration,0===Object.getOwnPropertyNames(t._sprite).length&&(t._sprite={_default:[0,1e3*t._duration]}),t._loaded||(t._loaded=!0,t.on("load")),t._autoplay&&t.play(),a.removeEventListener("canplaythrough",l,!1)};a.addEventListener("canplaythrough",l,!1),a.load()}return t},urls:function(e){var t=this;return e?(t.stop(),t._urls="string"==typeof e?[e]:e,t._loaded=!1,t.load(),t):t._urls},play:function(e,n){var r=this;return"function"==typeof e&&(n=e),e&&"function"!=typeof e||(e="_default"),r._loaded?r._sprite[e]?(r._inactiveNode(function(i){i._sprite=e;var s,o=i._pos>0?i._pos:r._sprite[e][0]/1e3,a=r._sprite[e][1]/1e3-i._pos,f=!(!r._loop&&!r._sprite[e][2]),l="string"==typeof n?n:Math.round(Date.now()*Math.random())+"";if(function(){var t={id:l,sprite:e,loop:f};s=setTimeout(function(){!r._webAudio&&f&&r.stop(t.id,t.timer).play(e,t.id),r._webAudio&&!f&&(r._nodeById(t.id).paused=!0),r._webAudio||f||r.stop(t.id,t.timer),r.on("end",l)},1e3*a),r._onendTimer.push(s),t.timer=r._onendTimer[r._onendTimer.length-1]}(),r._webAudio){var c=r._sprite[e][0]/1e3,h=r._sprite[e][1]/1e3;i.id=l,i.paused=!1,p(r,[f,c,h],l),r._playStart=t.currentTime,i.gain.value=r._volume,void 0===i.bufferSource.start?i.bufferSource.noteGrainOn(0,o,a):i.bufferSource.start(0,o,a)}else{if(4!==i.readyState)return r._clearEndTimer(s),function(){var t=r,s=e,o=n,u=i,a=function(){t.play(s,o),u.removeEventListener("canplaythrough",a,!1)};u.addEventListener("canplaythrough",a,!1)}(),r;i.id=l,i.currentTime=o,i.muted=u._muted,i.volume=r._volume*u.volume(),setTimeout(function(){i.play()},0)}return r.on("play"),"function"==typeof n&&n(l),r}),r):("function"==typeof n&&n(),r):(r.on("load",function(){r.play(e,n)}),r)},pause:function(e,t){var n=this;if(!n._loaded)return n.on("play",function(){n.pause(e)}),n;n._clearEndTimer(t||0);var r=e?n._nodeById(e):n._activeNode();if(r)if(r._pos=n.pos(null,e),n._webAudio){if(!r.bufferSource)return n;r.paused=!0,void 0===r.bufferSource.stop?r.bufferSource.noteOff(0):r.bufferSource.stop(0)}else r.pause();return n.on("pause"),n},stop:function(e,t){var n=this;if(!n._loaded)return n.on("play",function(){n.stop(e)}),n;n._clearEndTimer(t||0);var r=e?n._nodeById(e):n._activeNode();if(r)if(r._pos=0,n._webAudio){if(!r.bufferSource)return n;r.paused=!0,void 0===r.bufferSource.stop?r.bufferSource.noteOff(0):r.bufferSource.stop(0)}else r.pause(),r.currentTime=0;return n},mute:function(e){var t=this;if(!t._loaded)return t.on("play",function(){t.mute(e)}),t;var n=e?t._nodeById(e):t._activeNode();return n&&(t._webAudio?n.gain.value=0:n.volume=0),t},unmute:function(e){var t=this;if(!t._loaded)return t.on("play",function(){t.unmute(e)}),t;var n=e?t._nodeById(e):t._activeNode();return n&&(t._webAudio?n.gain.value=t._volume:n.volume=t._volume),t},volume:function(e,t){var n=this;if(e=parseFloat(e),e>=0&&1>=e){if(n._volume=e,!n._loaded)return n.on("play",function(){n.volume(e,t)}),n;var r=t?n._nodeById(t):n._activeNode();return r&&(n._webAudio?r.gain.value=e:r.volume=e*u.volume()),n}return n._volume},loop:function(e){var t=this;return"boolean"==typeof e?(t._loop=e,t):t._loop},sprite:function(e){var t=this;return"object"==typeof e?(t._sprite=e,t):t._sprite},pos:function(e,n){var r=this;if(!r._loaded)return r.on("load",function(){r.pos(e)}),"number"==typeof e?r:r._pos||0;e=parseFloat(e);var i=n?r._nodeById(n):r._activeNode();if(i)return r._webAudio?e>=0?(i._pos=e,r.pause(n).play(i._sprite,n),r):i._pos+(t.currentTime-r._playStart):e>=0?(i.currentTime=e,r):i.currentTime;if(e>=0)return r;for(var s=0;s=0||0>e))return i._pos3d;if(i._webAudio){var s=r?i._nodeById(r):i._activeNode();s&&(i._pos3d=[e,t,n],s.panner.setPosition(e,t,n))}return i},fade:function(e,t,n,r,i){var s=this,o=Math.abs(e-t),u=e>t?"down":"up",a=o/.01,f=n/a;if(!s._loaded)return s.on("load",function(){s.fade(e,t,n,r,i)}),s;s.volume(e,i);for(var l=1;a>=l;l++)!function(){var e=s._volume+("up"===u?.01:-.01)*l,n=Math.round(1e3*e)/1e3,o=t;setTimeout(function(){s.volume(n,i),n===o&&r&&r()},f*l)}()},fadeIn:function(e,t,n){return this.volume(0).play().fade(0,e,t,n)},fadeOut:function(e,t,n,r){var i=this;return i.fade(i._volume,e,t,function(){n&&n(),i.pause(r),i.on("end")},r)},_nodeById:function(e){for(var t=this,n=t._audioNode[0],r=0;r=0&&!(5>=n);e--)t._audioNode[e].paused&&(t._webAudio&&t._audioNode[e].disconnect(0),n--,t._audioNode.splice(e,1))},_clearEndTimer:function(e){var t=this,n=t._onendTimer.indexOf(e);n=n>=0?n:0,t._onendTimer[n]&&(clearTimeout(t._onendTimer[n]),t._onendTimer.splice(n,1))},_setupAudioNode:function(){var e=this,n=e._audioNode,r=e._audioNode.length;return n[r]=void 0===t.createGain?t.createGainNode():t.createGain(),n[r].gain.value=e._volume,n[r].paused=!0,n[r]._pos=0,n[r].readyState=4,n[r].connect(s),n[r].panner=t.createPanner(),n[r].panner.setPosition(e._pos3d[0],e._pos3d[1],e._pos3d[2]),n[r].panner.connect(n[r]),n[r]},on:function(e,t){var n=this,r=n["_on"+e];if("function"==typeof t)r.push(t);else for(var i=0;i 0; 102 | }, this); 103 | this.canRedo = ko.computed(function () { 104 | return this.cursor() < this.actionSets(); 105 | }, this); 106 | }; 107 | 108 | History.VM.prototype.reset = function () { 109 | this.actionSets(0); 110 | this.cursor(0); 111 | }; 112 | 113 | History.VM.prototype.bind = function (element) { 114 | ko.applyBindings(this, element); 115 | }; 116 | 117 | //fields 118 | History.prototype.actionSets = null; 119 | 120 | //public functions 121 | History.prototype.canUndo = function () { 122 | return this.vm.canUndo(); 123 | }; 124 | 125 | History.prototype.undo = function (settings) { 126 | if (settings == null) { 127 | settings = {}; 128 | } 129 | 130 | var actionSet; 131 | if (this.canUndo() === true) { 132 | this.cursor--; 133 | actionSet = this.actionSets[this.cursor]; 134 | actionSet.undo(settings); 135 | } 136 | return actionSet; 137 | }; 138 | 139 | History.prototype.canRedo = function () { 140 | return this.vm.canRedo(); 141 | }; 142 | 143 | History.prototype.redo = function (settings) { 144 | if (settings == null) { 145 | settings = {}; 146 | } 147 | 148 | var actionSet; 149 | if (this.canRedo() === true) { 150 | actionSet = this.actionSets[this.cursor]; 151 | actionSet.redo(settings); 152 | this.cursor++; 153 | } 154 | return actionSet; 155 | }; 156 | 157 | History.prototype.registerAction = function (action) { 158 | this.registerActionSet(new ActionSet([action])); 159 | }; 160 | 161 | History.prototype.registerActionSet = function (actionSet) { 162 | if (this.cursor < this.actionSets.length) { 163 | //cut off everything after cursor 164 | this.actionSets = this.actionSets.splice(0, this.cursor); 165 | } 166 | this.actionSets.push(actionSet); 167 | this.vm.actionSets(this.actionSets.length); 168 | this.cursor++; 169 | }; 170 | 171 | History.prototype.mergeActionSets = function (start, amount) { 172 | var length = this.actionSets.length; 173 | if (start < 0 || start > length - 2) { 174 | return; 175 | } 176 | if (amount == null) { 177 | amount = length - start; 178 | } 179 | if (start + amount < 0 || start + amount > length) { 180 | return; 181 | } 182 | var newActionSet = ActionSet.mergeActionSets(this.actionSets.slice(start, start + amount)); 183 | this.actionSets.splice(start, amount, newActionSet); 184 | this.vm.actionSets(this.actionSets.length); 185 | if (this.cursor > start) { 186 | this.cursor -= amount; 187 | this.cursor++; 188 | } 189 | }; 190 | 191 | History.prototype.clear = function () { 192 | this.actionSets = []; 193 | this.vm.actionSets(this.actionSets.length); 194 | this.cursor = 0; 195 | }; 196 | 197 | return History; 198 | })(fSpider.History || {}, window.ko); 199 | 200 | fSpider.TransferCardsAction = (function (TransferCardsAction, undefined) { 201 | 'use strict'; 202 | 203 | //constructor 204 | TransferCardsAction = function (cards, fromPile, toPile) { 205 | this.cards = cards; 206 | this.fromPile = fromPile; 207 | this.toPile = toPile; 208 | }; 209 | 210 | //fields 211 | TransferCardsAction.prototype.cards = null; 212 | TransferCardsAction.prototype.fromPile = null; 213 | TransferCardsAction.prototype.toPile = null; 214 | 215 | //public functions 216 | TransferCardsAction.prototype.undo = function (settings) { 217 | if (settings == null) { 218 | settings = {}; 219 | } 220 | 221 | this.fromPile.transferCards(this.cards, settings); 222 | this._refreshPiles(); 223 | }; 224 | 225 | TransferCardsAction.prototype.redo = function (settings) { 226 | if (settings == null) { 227 | settings = {}; 228 | } 229 | 230 | this.toPile.transferCards(this.cards, settings); 231 | this._refreshPiles(); 232 | }; 233 | 234 | TransferCardsAction.prototype._refreshPiles = function () { 235 | this.fromPile.resetListening(); 236 | this.fromPile.resetDraggable(); 237 | this.toPile.resetListening(); 238 | this.toPile.resetDraggable(); 239 | }; 240 | 241 | return TransferCardsAction; 242 | })(fSpider.TransferCardsAction || {}); 243 | 244 | fSpider.FlipCardAction = (function (FlipCardAction, undefined) { 245 | 'use strict'; 246 | 247 | //constructor 248 | FlipCardAction = function (card, isFaceUp) { 249 | this.card = card; 250 | this.isFaceUp = isFaceUp; 251 | }; 252 | 253 | //fields 254 | FlipCardAction.prototype.card = null; 255 | FlipCardAction.prototype.isFaceUp = false; 256 | 257 | //public functions 258 | FlipCardAction.prototype.undo = function (settings) { 259 | if (settings == null) { 260 | settings = {}; 261 | } 262 | 263 | this.card.setFaceUp(this.isFaceUp !== true, settings); 264 | }; 265 | 266 | FlipCardAction.prototype.redo = function (settings) { 267 | if (settings == null) { 268 | settings = {}; 269 | } 270 | 271 | this.card.setFaceUp(this.isFaceUp === true, settings); 272 | }; 273 | 274 | return FlipCardAction; 275 | })(fSpider.FlipCardAction || {}); 276 | 277 | fSpider.ReverseCardsAction = (function (ReverseCardsAction, undefined) { 278 | 'use strict'; 279 | 280 | //constructor 281 | ReverseCardsAction = function (pile) { 282 | this.pile = pile; 283 | }; 284 | 285 | //fields 286 | ReverseCardsAction.prototype.board = null; 287 | ReverseCardsAction.prototype.amount = 0; 288 | 289 | //public functions 290 | ReverseCardsAction.prototype.undo = function () { 291 | this.pile.reverseCards(); 292 | }; 293 | 294 | ReverseCardsAction.prototype.redo = function () { 295 | this.pile.reverseCards(); 296 | }; 297 | 298 | return ReverseCardsAction; 299 | })(fSpider.ReverseCardsAction || {}); 300 | 301 | fSpider.ScoreChangeAction = (function (ScoreChangeAction, undefined) { 302 | 'use strict'; 303 | 304 | //constructor 305 | ScoreChangeAction = function (board, amount) { 306 | this.board = board; 307 | this.amount = amount; 308 | }; 309 | 310 | //fields 311 | ScoreChangeAction.prototype.board = null; 312 | ScoreChangeAction.prototype.amount = 0; 313 | 314 | //public functions 315 | ScoreChangeAction.prototype.undo = function () { 316 | this.board.setScore(this.board.score - this.amount); 317 | }; 318 | 319 | ScoreChangeAction.prototype.redo = function () { 320 | this.board.setScore(this.board.score + this.amount); 321 | }; 322 | 323 | return ScoreChangeAction; 324 | })(fSpider.ScoreChangeAction || {}); -------------------------------------------------------------------------------- /scripts/spider/fSpider.ui.modal.js: -------------------------------------------------------------------------------- 1 | var fSpider = fSpider || {}; 2 | 3 | fSpider.Modal = (function (Modal, $, ko, undefined) { 4 | 'use strict'; 5 | 6 | //constructor 7 | Modal = function (element, options) { 8 | this.options = $.extend(true, {}, this.defaultOptions, options); 9 | 10 | //prepare element 11 | this.$modal = this.wrapElement(element); 12 | this.$modal.attr('id', this.options.id); 13 | if (this.options.draggable === true) { 14 | this.applyDraggable(this.$modal); 15 | } 16 | 17 | this.vm = new Modal.VM(this); 18 | 19 | this.setState(this.options.modalState, true); 20 | }; 21 | 22 | //static fields 23 | Modal.prototype.STATES = { 24 | 'CLOSED': 0, 25 | 'EXPANDED': 1, 26 | 'MINIMIZED': 2, 27 | 'PINNED': 3 28 | }; 29 | Modal.prototype.defaultOptions = { 30 | draggable: true, 31 | draggableOptions: { 32 | ignoreClasses: [ 33 | 'modal-control', 34 | 'modal-btn' 35 | ], 36 | dragend: function (evt) { 37 | 38 | } 39 | }, 40 | title: '', 41 | id: '', 42 | controls: { 43 | pin: false, 44 | minimize: false, 45 | expand: false, 46 | close: true, 47 | dragHandle: false 48 | }, 49 | modalState: Modal.prototype.STATES.EXPANDED, 50 | position: { 51 | top: '', 52 | left: '', 53 | bottom: '', 54 | right: '' 55 | }, 56 | //events 57 | pinned: function () { 58 | }, 59 | minimized: function () { 60 | }, 61 | expanded: function () { 62 | }, 63 | closed: function () { 64 | }, 65 | opened: function () { 66 | } 67 | }; 68 | 69 | //fields 70 | Modal.prototype.$modal = null; 71 | Modal.prototype.options = null; 72 | 73 | //"private" functions 74 | Modal.prototype.applyDraggable = function (el) { 75 | var opts = this.options || {}; 76 | if (opts.draggableOptions != null && opts.draggableOptions.owner == null) { 77 | opts.draggableOptions.owner = this; 78 | } 79 | el.draggable(opts.draggableOptions || {}); 80 | }; 81 | 82 | Modal.prototype.wrapElement = function (el) { 83 | var self = this; 84 | 85 | var opts = this.options || {}; 86 | var ctrls = opts.controls || {}; 87 | 88 | var $el = $(el); 89 | $el.addClass('modal-content'); 90 | 91 | var $modal = $('
').addClass('modal'); 92 | $modal.css(this.options.position); 93 | $el.parent().append($modal); 94 | 95 | //LEFT 96 | var $wrapLeft = $('
').addClass('modal-left'); 97 | var $wrapLeftTop = $('
').addClass('modal-left-top'); 98 | var $wrapLeftBottom = $('
').addClass('modal-left-bottom'); 99 | 100 | //LEFT-TOP 101 | //title bar 102 | var $titleBar = $('
').addClass('modal-title').html(opts.title); 103 | $wrapLeftTop.append($titleBar); 104 | 105 | var $controls = $('
').addClass('modal-controls'); 106 | //pin 107 | var $pin = $('
').addClass('modal-pin').addClass('modal-control') 108 | .append($('').addClass('icon-pushpin').addClass('modal-btn')) 109 | .on('click', function () { 110 | self.pin(); 111 | }); 112 | if (ctrls.pin !== true) { 113 | $pin.hide(); 114 | } 115 | $controls.append($pin); 116 | 117 | //minimize 118 | var $minimize = $('
').addClass('modal-minimize').addClass('modal-control') 119 | .append($('').addClass('icon-minus').addClass('modal-btn')) 120 | .on('click', function () { 121 | self.minimize(); 122 | }); 123 | if (ctrls.minimize !== true) { 124 | $minimize.hide(); 125 | } 126 | $controls.append($minimize); 127 | 128 | //restore 129 | var $restore = $('
').addClass('modal-restore').addClass('modal-control') 130 | .append($('').addClass('icon-external-link').addClass('modal-btn')) 131 | .on('click', function () { 132 | self.expand(); 133 | }); 134 | if (ctrls.expand !== true) { 135 | $restore.hide(); 136 | } 137 | $controls.append($restore); 138 | 139 | //close 140 | var $close = $('
').addClass('modal-close').addClass('modal-control') 141 | .append($('').addClass('icon-remove').addClass('modal-btn')) 142 | .on('click', function () { 143 | self.close(); 144 | }); 145 | if (ctrls.close !== true) { 146 | $minimize.hide(); 147 | } 148 | $controls.append($close); 149 | 150 | $wrapLeftTop.append($controls); 151 | $wrapLeftTop.append($('
').addClass('clear')); 152 | 153 | $wrapLeft.append($wrapLeftTop); 154 | 155 | //LEFT-BOTTOM 156 | $wrapLeftBottom.append($el); 157 | $wrapLeft.append($wrapLeftBottom); 158 | 159 | //LEFT END 160 | $modal.prepend($wrapLeft); 161 | 162 | //RIGHT 163 | var $wrapRight = $('
').addClass('modal-right'); 164 | var $wrapRightTop = $('
').addClass('modal-right-top'); 165 | var $wrapRightBottom = $('
').addClass('modal-right-bottom'); 166 | 167 | //RIGHT-TOP 168 | $wrapRight.append($wrapRightTop); 169 | 170 | //RIGHT-BOTTOM 171 | //drag handle 172 | var $dragHandle = $('
').addClass('modal-drag-handle'); 173 | if (ctrls.dragHandle !== true) { 174 | $dragHandle.hide(); 175 | } 176 | $wrapRightBottom.append($dragHandle); 177 | 178 | $wrapRight.append($wrapRightBottom); 179 | 180 | //RIGHT END 181 | $modal.append($wrapRight); 182 | 183 | return $modal; 184 | }; 185 | 186 | Modal.prototype.applyState = function (state, noNotify) { 187 | switch (state) { 188 | case this.STATES.EXPANDED: 189 | this.expand(noNotify); 190 | break; 191 | case this.STATES.MINIMIZED: 192 | this.minimize(noNotify); 193 | break; 194 | case this.STATES.PINNED: 195 | this.pin(noNotify); 196 | break; 197 | case this.STATES.CLOSED: 198 | this.close(noNotify); 199 | break; 200 | } 201 | }; 202 | 203 | //public functions 204 | Modal.prototype.getState = function () { 205 | return this.state; 206 | }; 207 | 208 | Modal.prototype.setState = function (state, noNotify) { 209 | if (noNotify === true) { 210 | this.vm.setStateQuiet(state); 211 | } else { 212 | this.vm.state(state); 213 | } 214 | }; 215 | 216 | Modal.prototype.expand = function (noNotify) { 217 | this.state = this.STATES.EXPANDED; 218 | this.$modal.show(); 219 | if (noNotify !== true) { 220 | this.options.expanded.call(this); 221 | } 222 | }; 223 | 224 | Modal.prototype.minimize = function (noNotify) { 225 | this.state = this.STATES.MINIMIZED; 226 | if (noNotify !== true) { 227 | this.options.minimized.call(this); 228 | } 229 | }; 230 | 231 | Modal.prototype.pin = function (noNotify) { 232 | this.state = this.STATES.PINNED; 233 | if (noNotify !== true) { 234 | this.options.pinned.call(this); 235 | } 236 | }; 237 | 238 | Modal.prototype.close = function (noNotify) { 239 | this.state = this.STATES.CLOSED; 240 | this.$modal.hide(); 241 | if (noNotify !== true) { 242 | this.options.closed.call(this); 243 | } 244 | }; 245 | 246 | Modal.prototype.save = function (prefix) { 247 | if (prefix == null) { 248 | prefix = 'fModal'; 249 | } 250 | 251 | var key = [prefix, '.', this.options.id].join(''); 252 | if (localStorage != null) { 253 | localStorage.setItem(key, this.toJSON()); 254 | return true; 255 | } 256 | return false; 257 | }; 258 | 259 | Modal.prototype.load = function (prefix) { 260 | if (prefix == null) { 261 | prefix = 'fModal'; 262 | } 263 | 264 | var key = [prefix, '.', this.options.id].join(''); 265 | if (localStorage != null) { 266 | try { 267 | var data = localStorage.getItem(key); 268 | if (data != null && data != '') { 269 | var attributes = JSON.parse(data); 270 | this.set(attributes, true); 271 | } 272 | return true; 273 | } catch (ex) { 274 | console.log(ex); 275 | } 276 | } 277 | return false; 278 | }; 279 | 280 | Modal.prototype.attributes = function () { 281 | return { 282 | state: this.getState(), 283 | position: { 284 | top: this.$modal.css('top'), 285 | bottom: this.$modal.css('bottom'), 286 | left: this.$modal.css('left'), 287 | right: this.$modal.css('right') 288 | } 289 | } 290 | }; 291 | 292 | Modal.prototype.set = function (attributes, noNotify) { 293 | if (attributes == null) { 294 | return this; 295 | } 296 | 297 | if (attributes.state != null) { 298 | this.setState(attributes.state, noNotify); 299 | } 300 | if (attributes.position != null) { 301 | if (attributes.position.top != null) { 302 | this.$modal.css('top', attributes.position.top); 303 | } 304 | if (attributes.position.bottom != null) { 305 | this.$modal.css('bottom', attributes.position.bottom); 306 | } 307 | if (attributes.position.left != null) { 308 | this.$modal.css('left', attributes.position.left); 309 | } 310 | if (attributes.position.right != null) { 311 | this.$modal.css('right', attributes.position.right); 312 | } 313 | } 314 | 315 | return this; 316 | }; 317 | 318 | Modal.prototype.toJSON = function () { 319 | return JSON.stringify(this.attributes()); 320 | }; 321 | 322 | Modal.VM = function (modal) { 323 | this.modal = modal; 324 | 325 | this.nextSetStateQuiet = false; 326 | this.state = ko.observable(0); 327 | 328 | this.isOpen = ko.observable(false); 329 | this.isOpen.subscribe(function (newIsOpen) { 330 | if (newIsOpen == true) { 331 | this.state(Modal.prototype.STATES.EXPANDED); 332 | } else { 333 | this.state(Modal.prototype.STATES.CLOSED); 334 | } 335 | }, this); 336 | 337 | this.state.subscribe(function (newState) { 338 | this.modal.applyState(newState, this.nextSetStateQuiet); 339 | this.nextSetStateQuiet = false; 340 | 341 | this.isOpen(newState == Modal.prototype.STATES.EXPANDED); 342 | }, this); 343 | }; 344 | 345 | Modal.VM.prototype.setStateQuiet = function (state) { 346 | this.nextSetStateQuiet = true; 347 | this.state(state); 348 | }; 349 | 350 | Modal.VM.prototype.STATES = Modal.prototype.STATES; 351 | 352 | return Modal; 353 | })(fSpider.Modal || {}, window.jQuery, window.ko); -------------------------------------------------------------------------------- /scripts/spider/fSpider.settings.js: -------------------------------------------------------------------------------- 1 | var fSpider = fSpider || {}; 2 | 3 | fSpider.Settings = (function (Settings, $, undefined) { 4 | 'use strict'; 5 | 6 | //dependencies 7 | var Utils = fSpider.Utils; 8 | 9 | //constructor 10 | Settings = function (options) { 11 | this.set(options); 12 | }; 13 | 14 | //fields 15 | Settings.prototype.defaultSettings = null; 16 | Settings.prototype.vm = null; 17 | 18 | //public functions 19 | Settings.prototype.set = function (options) { 20 | $.extend(true, this, this.defaultSettings, this, options); 21 | }; 22 | 23 | Settings.prototype.filter = function (props) { 24 | if (props == null) { 25 | props = []; 26 | } 27 | 28 | var settings = {}; 29 | var length = props.length; 30 | var prop; 31 | for (var i = 0; i < length; i++) { 32 | prop = props[i]; 33 | settings[prop] = this.settings[prop]; 34 | } 35 | 36 | return settings; 37 | }; 38 | 39 | Settings.prototype.extend = function (options) { 40 | return Utils.extendProps(options, this); 41 | }; 42 | 43 | Settings.prototype._save = function (key) { 44 | if (localStorage != null) { 45 | localStorage.setItem(key, this.toJSON()); 46 | return true; 47 | } 48 | return false; 49 | }; 50 | 51 | Settings.prototype._load = function (key) { 52 | if (localStorage != null) { 53 | try { 54 | var settings = JSON.parse(localStorage.getItem(key)); 55 | this.set(settings); 56 | return true; 57 | } catch (ex) { 58 | console.log(ex); 59 | } 60 | } 61 | return false; 62 | }; 63 | 64 | Settings.prototype.attributes = function () { 65 | return Utils.filterInProperties(this, Object.keys(this.defaultSettings || {}), []); 66 | }; 67 | 68 | Settings.prototype.toJSON = function () { 69 | return JSON.stringify(this.attributes()); 70 | }; 71 | 72 | return Settings; 73 | })(fSpider.Settings || {}, $); 74 | 75 | fSpider.GameSettings = (function (GameSettings, $, ko, undefined) { 76 | 'use strict'; 77 | 78 | var Utils = fSpider.Utils; 79 | var Settings = fSpider.Settings; 80 | 81 | //constructor 82 | GameSettings = function () { 83 | //setup vm proxies 84 | this.vm = new GameSettings.VM(); 85 | this.vm.changed.subscribe(function() { 86 | this.save(); 87 | }.bind(this)); 88 | 89 | Object.defineProperty(this, 'animate', { 90 | get: function () { 91 | return this.vm.animate(); 92 | }, 93 | set: function (value) { 94 | this.vm.animate(value); 95 | }, 96 | enumerable: true 97 | }); 98 | Object.defineProperty(this, 'volume', { 99 | get: function () { 100 | return this.vm.volume() ? 1 : 0; 101 | }, 102 | set: function (value) { 103 | this.vm.volume(value > 0); 104 | }, 105 | enumerable: true 106 | }); 107 | Object.defineProperty(this, 'difficulty', { 108 | get: function () { 109 | return this.vm.difficulty(); 110 | }, 111 | set: function (value) { 112 | this.vm.difficulty(value); 113 | }, 114 | enumerable: true 115 | }); 116 | Object.defineProperty(this, 'animTime', { 117 | get: function () { 118 | return this.vm.animTime(); 119 | }, 120 | set: function (value) { 121 | this.vm.animTime(value); 122 | }, 123 | enumerable: true 124 | }); 125 | Object.defineProperty(this, 'animDelay', { 126 | get: function () { 127 | return this.vm.animDelay(); 128 | }, 129 | set: function (value) { 130 | this.vm.animDelay(value); 131 | }, 132 | enumerable: true 133 | }); 134 | 135 | if (this.load() !== true) { 136 | this.set(); 137 | this.save(); 138 | } 139 | }; 140 | 141 | Utils.extendObj(GameSettings, Settings); 142 | 143 | //VM 144 | GameSettings.VM = function () { 145 | this.build(); 146 | this.reset(); 147 | }; 148 | 149 | GameSettings.VM.prototype.build = function () { 150 | this.animate = ko.observable(); 151 | this.volume = ko.observable(); 152 | this.difficulty = ko.observable(); 153 | this.difficultyOptions = ko.observableArray([ 154 | { text: '1 Suit', value: GameSettings.prototype.DIFFICULTIES.ONE_SUIT }, 155 | { text: '2 Suits', value: GameSettings.prototype.DIFFICULTIES.TWO_SUIT }, 156 | { text: '4 Suits', value: GameSettings.prototype.DIFFICULTIES.FOUR_SUIT } 157 | ]); 158 | this.animTime = ko.observable(); 159 | this.animDelay = ko.observable(); 160 | 161 | this.changed = ko.computed(function () { 162 | return ko.toJS(fSpider.Utils.filterOutProperties(this, ['changed'], [], true)); 163 | }.bind(this)); 164 | }; 165 | 166 | GameSettings.VM.prototype.reset = function () { 167 | this.animate(GameSettings.prototype.defaultSettings.animate); 168 | this.volume(GameSettings.prototype.defaultSettings.volume); 169 | this.difficulty(GameSettings.prototype.defaultSettings.difficulty); 170 | this.animTime(GameSettings.prototype.defaultSettings.animTime); 171 | this.animDelay(GameSettings.prototype.defaultSettings.animDelay); 172 | }; 173 | 174 | GameSettings.VM.prototype.bind = function (element) { 175 | ko.applyBindings(element); 176 | }; 177 | 178 | //fields 179 | GameSettings.prototype.DIFFICULTIES = { 180 | 'ONE_SUIT': 0, 181 | 'TWO_SUIT': 1, 182 | 'FOUR_SUIT': 2 183 | }; 184 | 185 | GameSettings.prototype.defaultSettings = { 186 | animate: true, 187 | volume: 1, 188 | difficulty: GameSettings.prototype.DIFFICULTIES.ONE_SUIT, 189 | animTime: 150, 190 | animDelay: 0 191 | }; 192 | 193 | //public functions 194 | GameSettings.prototype.extendAnimate = function (animate) { 195 | return Utils.extendProps({ animate: animate }, this); 196 | }; 197 | 198 | GameSettings.prototype.extendAnimTime = function (animTime) { 199 | return Utils.extendProps({ animTime: animTime }, this); 200 | }; 201 | 202 | GameSettings.prototype.extendAnimDelay = function (animDelay) { 203 | return Utils.extendProps({ animDelay: animDelay }, this); 204 | }; 205 | 206 | GameSettings.prototype.save = function () { 207 | return this._save('GameSettings'); 208 | }; 209 | 210 | GameSettings.prototype.load = function () { 211 | return this._load('GameSettings'); 212 | }; 213 | 214 | return GameSettings; 215 | })(fSpider.GameSettings || {}, window.jQuery, window.ko); 216 | 217 | fSpider.UISettings = (function (UISettings, $, ko, undefined) { 218 | 'use strict'; 219 | 220 | var Utils = fSpider.Utils; 221 | var Settings = fSpider.Settings; 222 | 223 | //constructor 224 | UISettings = function (options) { 225 | this.options = $.extend(true, {}, this.defaultSettings, options); 226 | }; 227 | 228 | Utils.extendObj(UISettings, Settings); 229 | 230 | //fields 231 | UISettings.prototype.defaultSettings = { 232 | windows: { 233 | options: { 234 | elementId: 'options-wrap', 235 | id: 'options-modal', 236 | title: 'Options', 237 | position: { top: '', bottom: '56px', left: '5px', right: '' }, 238 | modalState: 1, 239 | draggableOptions: { 240 | containment: '#ui-container', 241 | dragend: function () { 242 | this.save(); 243 | } 244 | }, 245 | closed: function () { 246 | this.save(); 247 | }, 248 | expanded: function () { 249 | this.save(); 250 | } 251 | }, 252 | score: { 253 | elementId: 'score-display', 254 | id: 'score-display-modal', 255 | title: 'Score', 256 | position: { top: '', bottom: '60px', left: '95px', right: '' }, 257 | modalState: 1, 258 | draggableOptions: { 259 | containment: '#ui-container', 260 | dragend: function () { 261 | this.save(); 262 | } 263 | }, 264 | closed: function () { 265 | this.save(); 266 | }, 267 | expanded: function () { 268 | this.save(); 269 | } 270 | }, 271 | moves: { 272 | elementId: 'moves-display', 273 | id: 'moves-display-modal', 274 | title: 'Moves', 275 | position: { top: '', bottom: '60px', left: '150px', right: '' }, 276 | modalState: 1, 277 | draggableOptions: { 278 | containment: '#ui-container', 279 | dragend: function () { 280 | this.save(); 281 | } 282 | }, 283 | closed: function () { 284 | this.save(); 285 | }, 286 | expanded: function () { 287 | this.save(); 288 | } 289 | }, 290 | time: { 291 | elementId: 'time-display', 292 | id: 'time-display-modal', 293 | title: 'Time', 294 | position: { top: '', bottom: '60px', left: '210px', right: '' }, 295 | modalState: 1, 296 | draggableOptions: { 297 | containment: '#ui-container', 298 | dragend: function () { 299 | this.save(); 300 | } 301 | }, 302 | closed: function () { 303 | this.save(); 304 | }, 305 | expanded: function () { 306 | this.save(); 307 | } 308 | }, 309 | game: { 310 | elementId: 'game-ctrls-wrap', 311 | id: 'game-ctrls-modal', 312 | title: 'Game', 313 | position: { top: '', bottom: '5px', left: '5px', right: '' }, 314 | modalState: 1, 315 | draggableOptions: { 316 | containment: '#ui-container', 317 | dragend: function () { 318 | this.save(); 319 | } 320 | }, 321 | closed: function () { 322 | this.save(); 323 | }, 324 | expanded: function () { 325 | this.save(); 326 | } 327 | } 328 | } 329 | }; 330 | 331 | //functions 332 | UISettings.prototype.loadWindows = function () { 333 | this.windows = {}; 334 | 335 | var w; 336 | for (var window in this.options.windows) { 337 | w = this.options.windows[window]; 338 | this.windows[window] = new fSpider.Modal(['#', w.elementId].join(''), fSpider.Utils.filterOutProperties(w, ['elementId'], [], true)); 339 | this.windows[window].load(); 340 | } 341 | 342 | return this.windows; 343 | }; 344 | 345 | return UISettings; 346 | })(fSpider.UISettings || {}, window.jQuery, window.ko); -------------------------------------------------------------------------------- /default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Fuzzley - Spider Solitaire 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 | 16 | 17 | 18 | 30 | 40 |
41 | 42 |
43 | 44 | 114 |
115 |
116 | 117 | 118 | 119 | 120 | 121 |
122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 324 | 325 | 326 | -------------------------------------------------------------------------------- /content/font_awesome/css/font-awesome.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:'FontAwesome';src:url('../font/fontawesome-webfont.eot?v=3.2.1');src:url('../font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'),url('../font/fontawesome-webfont.woff?v=3.2.1') format('woff'),url('../font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'),url('../font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg');font-weight:normal;font-style:normal;}[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;} 2 | [class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none;} 3 | .icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em;} 4 | a [class^="icon-"],a [class*=" icon-"]{display:inline;} 5 | [class^="icon-"].icon-fixed-width,[class*=" icon-"].icon-fixed-width{display:inline-block;width:1.1428571428571428em;text-align:right;padding-right:0.2857142857142857em;}[class^="icon-"].icon-fixed-width.icon-large,[class*=" icon-"].icon-fixed-width.icon-large{width:1.4285714285714286em;} 6 | .icons-ul{margin-left:2.142857142857143em;list-style-type:none;}.icons-ul>li{position:relative;} 7 | .icons-ul .icon-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;text-align:center;line-height:inherit;} 8 | [class^="icon-"].hide,[class*=" icon-"].hide{display:none;} 9 | .icon-muted{color:#eeeeee;} 10 | .icon-light{color:#ffffff;} 11 | .icon-dark{color:#333333;} 12 | .icon-border{border:solid 1px #eeeeee;padding:.2em .25em .15em;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} 13 | .icon-2x{font-size:2em;}.icon-2x.icon-border{border-width:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} 14 | .icon-3x{font-size:3em;}.icon-3x.icon-border{border-width:3px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} 15 | .icon-4x{font-size:4em;}.icon-4x.icon-border{border-width:4px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;} 16 | .icon-5x{font-size:5em;}.icon-5x.icon-border{border-width:5px;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px;} 17 | .pull-right{float:right;} 18 | .pull-left{float:left;} 19 | [class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em;} 20 | [class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em;} 21 | [class^="icon-"],[class*=" icon-"]{display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0% 0%;background-repeat:repeat;margin-top:0;} 22 | .icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none;} 23 | .btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em;} 24 | .btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block;} 25 | .nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em;} 26 | .btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon-"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em;} 27 | .btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em;} 28 | .btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em;} 29 | .btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0;}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em;} 30 | .btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em;} 31 | .btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em;} 32 | .nav-list [class^="icon-"],.nav-list [class*=" icon-"]{line-height:inherit;} 33 | .icon-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:-35%;}.icon-stack [class^="icon-"],.icon-stack [class*=" icon-"]{display:block;text-align:center;position:absolute;width:100%;height:100%;font-size:1em;line-height:inherit;*line-height:2em;} 34 | .icon-stack .icon-stack-base{font-size:2em;*line-height:1em;} 35 | .icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear;} 36 | a .icon-stack,a .icon-spin{display:inline-block;text-decoration:none;} 37 | @-moz-keyframes spin{0%{-moz-transform:rotate(0deg);} 100%{-moz-transform:rotate(359deg);}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg);} 100%{-webkit-transform:rotate(359deg);}}@-o-keyframes spin{0%{-o-transform:rotate(0deg);} 100%{-o-transform:rotate(359deg);}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg);} 100%{-ms-transform:rotate(359deg);}}@keyframes spin{0%{transform:rotate(0deg);} 100%{transform:rotate(359deg);}}.icon-rotate-90:before{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);} 38 | .icon-rotate-180:before{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);} 39 | .icon-rotate-270:before{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);} 40 | .icon-flip-horizontal:before{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1);} 41 | .icon-flip-vertical:before{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1);} 42 | a .icon-rotate-90:before,a .icon-rotate-180:before,a .icon-rotate-270:before,a .icon-flip-horizontal:before,a .icon-flip-vertical:before{display:inline-block;} 43 | .icon-glass:before{content:"\f000";} 44 | .icon-music:before{content:"\f001";} 45 | .icon-search:before{content:"\f002";} 46 | .icon-envelope-alt:before{content:"\f003";} 47 | .icon-heart:before{content:"\f004";} 48 | .icon-star:before{content:"\f005";} 49 | .icon-star-empty:before{content:"\f006";} 50 | .icon-user:before{content:"\f007";} 51 | .icon-film:before{content:"\f008";} 52 | .icon-th-large:before{content:"\f009";} 53 | .icon-th:before{content:"\f00a";} 54 | .icon-th-list:before{content:"\f00b";} 55 | .icon-ok:before{content:"\f00c";} 56 | .icon-remove:before{content:"\f00d";} 57 | .icon-zoom-in:before{content:"\f00e";} 58 | .icon-zoom-out:before{content:"\f010";} 59 | .icon-power-off:before,.icon-off:before{content:"\f011";} 60 | .icon-signal:before{content:"\f012";} 61 | .icon-gear:before,.icon-cog:before{content:"\f013";} 62 | .icon-trash:before{content:"\f014";} 63 | .icon-home:before{content:"\f015";} 64 | .icon-file-alt:before{content:"\f016";} 65 | .icon-time:before{content:"\f017";} 66 | .icon-road:before{content:"\f018";} 67 | .icon-download-alt:before{content:"\f019";} 68 | .icon-download:before{content:"\f01a";} 69 | .icon-upload:before{content:"\f01b";} 70 | .icon-inbox:before{content:"\f01c";} 71 | .icon-play-circle:before{content:"\f01d";} 72 | .icon-rotate-right:before,.icon-repeat:before{content:"\f01e";} 73 | .icon-refresh:before{content:"\f021";} 74 | .icon-list-alt:before{content:"\f022";} 75 | .icon-lock:before{content:"\f023";} 76 | .icon-flag:before{content:"\f024";} 77 | .icon-headphones:before{content:"\f025";} 78 | .icon-volume-off:before{content:"\f026";} 79 | .icon-volume-down:before{content:"\f027";} 80 | .icon-volume-up:before{content:"\f028";} 81 | .icon-qrcode:before{content:"\f029";} 82 | .icon-barcode:before{content:"\f02a";} 83 | .icon-tag:before{content:"\f02b";} 84 | .icon-tags:before{content:"\f02c";} 85 | .icon-book:before{content:"\f02d";} 86 | .icon-bookmark:before{content:"\f02e";} 87 | .icon-print:before{content:"\f02f";} 88 | .icon-camera:before{content:"\f030";} 89 | .icon-font:before{content:"\f031";} 90 | .icon-bold:before{content:"\f032";} 91 | .icon-italic:before{content:"\f033";} 92 | .icon-text-height:before{content:"\f034";} 93 | .icon-text-width:before{content:"\f035";} 94 | .icon-align-left:before{content:"\f036";} 95 | .icon-align-center:before{content:"\f037";} 96 | .icon-align-right:before{content:"\f038";} 97 | .icon-align-justify:before{content:"\f039";} 98 | .icon-list:before{content:"\f03a";} 99 | .icon-indent-left:before{content:"\f03b";} 100 | .icon-indent-right:before{content:"\f03c";} 101 | .icon-facetime-video:before{content:"\f03d";} 102 | .icon-picture:before{content:"\f03e";} 103 | .icon-pencil:before{content:"\f040";} 104 | .icon-map-marker:before{content:"\f041";} 105 | .icon-adjust:before{content:"\f042";} 106 | .icon-tint:before{content:"\f043";} 107 | .icon-edit:before{content:"\f044";} 108 | .icon-share:before{content:"\f045";} 109 | .icon-check:before{content:"\f046";} 110 | .icon-move:before{content:"\f047";} 111 | .icon-step-backward:before{content:"\f048";} 112 | .icon-fast-backward:before{content:"\f049";} 113 | .icon-backward:before{content:"\f04a";} 114 | .icon-play:before{content:"\f04b";} 115 | .icon-pause:before{content:"\f04c";} 116 | .icon-stop:before{content:"\f04d";} 117 | .icon-forward:before{content:"\f04e";} 118 | .icon-fast-forward:before{content:"\f050";} 119 | .icon-step-forward:before{content:"\f051";} 120 | .icon-eject:before{content:"\f052";} 121 | .icon-chevron-left:before{content:"\f053";} 122 | .icon-chevron-right:before{content:"\f054";} 123 | .icon-plus-sign:before{content:"\f055";} 124 | .icon-minus-sign:before{content:"\f056";} 125 | .icon-remove-sign:before{content:"\f057";} 126 | .icon-ok-sign:before{content:"\f058";} 127 | .icon-question-sign:before{content:"\f059";} 128 | .icon-info-sign:before{content:"\f05a";} 129 | .icon-screenshot:before{content:"\f05b";} 130 | .icon-remove-circle:before{content:"\f05c";} 131 | .icon-ok-circle:before{content:"\f05d";} 132 | .icon-ban-circle:before{content:"\f05e";} 133 | .icon-arrow-left:before{content:"\f060";} 134 | .icon-arrow-right:before{content:"\f061";} 135 | .icon-arrow-up:before{content:"\f062";} 136 | .icon-arrow-down:before{content:"\f063";} 137 | .icon-mail-forward:before,.icon-share-alt:before{content:"\f064";} 138 | .icon-resize-full:before{content:"\f065";} 139 | .icon-resize-small:before{content:"\f066";} 140 | .icon-plus:before{content:"\f067";} 141 | .icon-minus:before{content:"\f068";} 142 | .icon-asterisk:before{content:"\f069";} 143 | .icon-exclamation-sign:before{content:"\f06a";} 144 | .icon-gift:before{content:"\f06b";} 145 | .icon-leaf:before{content:"\f06c";} 146 | .icon-fire:before{content:"\f06d";} 147 | .icon-eye-open:before{content:"\f06e";} 148 | .icon-eye-close:before{content:"\f070";} 149 | .icon-warning-sign:before{content:"\f071";} 150 | .icon-plane:before{content:"\f072";} 151 | .icon-calendar:before{content:"\f073";} 152 | .icon-random:before{content:"\f074";} 153 | .icon-comment:before{content:"\f075";} 154 | .icon-magnet:before{content:"\f076";} 155 | .icon-chevron-up:before{content:"\f077";} 156 | .icon-chevron-down:before{content:"\f078";} 157 | .icon-retweet:before{content:"\f079";} 158 | .icon-shopping-cart:before{content:"\f07a";} 159 | .icon-folder-close:before{content:"\f07b";} 160 | .icon-folder-open:before{content:"\f07c";} 161 | .icon-resize-vertical:before{content:"\f07d";} 162 | .icon-resize-horizontal:before{content:"\f07e";} 163 | .icon-bar-chart:before{content:"\f080";} 164 | .icon-twitter-sign:before{content:"\f081";} 165 | .icon-facebook-sign:before{content:"\f082";} 166 | .icon-camera-retro:before{content:"\f083";} 167 | .icon-key:before{content:"\f084";} 168 | .icon-gears:before,.icon-cogs:before{content:"\f085";} 169 | .icon-comments:before{content:"\f086";} 170 | .icon-thumbs-up-alt:before{content:"\f087";} 171 | .icon-thumbs-down-alt:before{content:"\f088";} 172 | .icon-star-half:before{content:"\f089";} 173 | .icon-heart-empty:before{content:"\f08a";} 174 | .icon-signout:before{content:"\f08b";} 175 | .icon-linkedin-sign:before{content:"\f08c";} 176 | .icon-pushpin:before{content:"\f08d";} 177 | .icon-external-link:before{content:"\f08e";} 178 | .icon-signin:before{content:"\f090";} 179 | .icon-trophy:before{content:"\f091";} 180 | .icon-github-sign:before{content:"\f092";} 181 | .icon-upload-alt:before{content:"\f093";} 182 | .icon-lemon:before{content:"\f094";} 183 | .icon-phone:before{content:"\f095";} 184 | .icon-unchecked:before,.icon-check-empty:before{content:"\f096";} 185 | .icon-bookmark-empty:before{content:"\f097";} 186 | .icon-phone-sign:before{content:"\f098";} 187 | .icon-twitter:before{content:"\f099";} 188 | .icon-facebook:before{content:"\f09a";} 189 | .icon-github:before{content:"\f09b";} 190 | .icon-unlock:before{content:"\f09c";} 191 | .icon-credit-card:before{content:"\f09d";} 192 | .icon-rss:before{content:"\f09e";} 193 | .icon-hdd:before{content:"\f0a0";} 194 | .icon-bullhorn:before{content:"\f0a1";} 195 | .icon-bell:before{content:"\f0a2";} 196 | .icon-certificate:before{content:"\f0a3";} 197 | .icon-hand-right:before{content:"\f0a4";} 198 | .icon-hand-left:before{content:"\f0a5";} 199 | .icon-hand-up:before{content:"\f0a6";} 200 | .icon-hand-down:before{content:"\f0a7";} 201 | .icon-circle-arrow-left:before{content:"\f0a8";} 202 | .icon-circle-arrow-right:before{content:"\f0a9";} 203 | .icon-circle-arrow-up:before{content:"\f0aa";} 204 | .icon-circle-arrow-down:before{content:"\f0ab";} 205 | .icon-globe:before{content:"\f0ac";} 206 | .icon-wrench:before{content:"\f0ad";} 207 | .icon-tasks:before{content:"\f0ae";} 208 | .icon-filter:before{content:"\f0b0";} 209 | .icon-briefcase:before{content:"\f0b1";} 210 | .icon-fullscreen:before{content:"\f0b2";} 211 | .icon-group:before{content:"\f0c0";} 212 | .icon-link:before{content:"\f0c1";} 213 | .icon-cloud:before{content:"\f0c2";} 214 | .icon-beaker:before{content:"\f0c3";} 215 | .icon-cut:before{content:"\f0c4";} 216 | .icon-copy:before{content:"\f0c5";} 217 | .icon-paperclip:before,.icon-paper-clip:before{content:"\f0c6";} 218 | .icon-save:before{content:"\f0c7";} 219 | .icon-sign-blank:before{content:"\f0c8";} 220 | .icon-reorder:before{content:"\f0c9";} 221 | .icon-list-ul:before{content:"\f0ca";} 222 | .icon-list-ol:before{content:"\f0cb";} 223 | .icon-strikethrough:before{content:"\f0cc";} 224 | .icon-underline:before{content:"\f0cd";} 225 | .icon-table:before{content:"\f0ce";} 226 | .icon-magic:before{content:"\f0d0";} 227 | .icon-truck:before{content:"\f0d1";} 228 | .icon-pinterest:before{content:"\f0d2";} 229 | .icon-pinterest-sign:before{content:"\f0d3";} 230 | .icon-google-plus-sign:before{content:"\f0d4";} 231 | .icon-google-plus:before{content:"\f0d5";} 232 | .icon-money:before{content:"\f0d6";} 233 | .icon-caret-down:before{content:"\f0d7";} 234 | .icon-caret-up:before{content:"\f0d8";} 235 | .icon-caret-left:before{content:"\f0d9";} 236 | .icon-caret-right:before{content:"\f0da";} 237 | .icon-columns:before{content:"\f0db";} 238 | .icon-sort:before{content:"\f0dc";} 239 | .icon-sort-down:before{content:"\f0dd";} 240 | .icon-sort-up:before{content:"\f0de";} 241 | .icon-envelope:before{content:"\f0e0";} 242 | .icon-linkedin:before{content:"\f0e1";} 243 | .icon-rotate-left:before,.icon-undo:before{content:"\f0e2";} 244 | .icon-legal:before{content:"\f0e3";} 245 | .icon-dashboard:before{content:"\f0e4";} 246 | .icon-comment-alt:before{content:"\f0e5";} 247 | .icon-comments-alt:before{content:"\f0e6";} 248 | .icon-bolt:before{content:"\f0e7";} 249 | .icon-sitemap:before{content:"\f0e8";} 250 | .icon-umbrella:before{content:"\f0e9";} 251 | .icon-paste:before{content:"\f0ea";} 252 | .icon-lightbulb:before{content:"\f0eb";} 253 | .icon-exchange:before{content:"\f0ec";} 254 | .icon-cloud-download:before{content:"\f0ed";} 255 | .icon-cloud-upload:before{content:"\f0ee";} 256 | .icon-user-md:before{content:"\f0f0";} 257 | .icon-stethoscope:before{content:"\f0f1";} 258 | .icon-suitcase:before{content:"\f0f2";} 259 | .icon-bell-alt:before{content:"\f0f3";} 260 | .icon-coffee:before{content:"\f0f4";} 261 | .icon-food:before{content:"\f0f5";} 262 | .icon-file-text-alt:before{content:"\f0f6";} 263 | .icon-building:before{content:"\f0f7";} 264 | .icon-hospital:before{content:"\f0f8";} 265 | .icon-ambulance:before{content:"\f0f9";} 266 | .icon-medkit:before{content:"\f0fa";} 267 | .icon-fighter-jet:before{content:"\f0fb";} 268 | .icon-beer:before{content:"\f0fc";} 269 | .icon-h-sign:before{content:"\f0fd";} 270 | .icon-plus-sign-alt:before{content:"\f0fe";} 271 | .icon-double-angle-left:before{content:"\f100";} 272 | .icon-double-angle-right:before{content:"\f101";} 273 | .icon-double-angle-up:before{content:"\f102";} 274 | .icon-double-angle-down:before{content:"\f103";} 275 | .icon-angle-left:before{content:"\f104";} 276 | .icon-angle-right:before{content:"\f105";} 277 | .icon-angle-up:before{content:"\f106";} 278 | .icon-angle-down:before{content:"\f107";} 279 | .icon-desktop:before{content:"\f108";} 280 | .icon-laptop:before{content:"\f109";} 281 | .icon-tablet:before{content:"\f10a";} 282 | .icon-mobile-phone:before{content:"\f10b";} 283 | .icon-circle-blank:before{content:"\f10c";} 284 | .icon-quote-left:before{content:"\f10d";} 285 | .icon-quote-right:before{content:"\f10e";} 286 | .icon-spinner:before{content:"\f110";} 287 | .icon-circle:before{content:"\f111";} 288 | .icon-mail-reply:before,.icon-reply:before{content:"\f112";} 289 | .icon-github-alt:before{content:"\f113";} 290 | .icon-folder-close-alt:before{content:"\f114";} 291 | .icon-folder-open-alt:before{content:"\f115";} 292 | .icon-expand-alt:before{content:"\f116";} 293 | .icon-collapse-alt:before{content:"\f117";} 294 | .icon-smile:before{content:"\f118";} 295 | .icon-frown:before{content:"\f119";} 296 | .icon-meh:before{content:"\f11a";} 297 | .icon-gamepad:before{content:"\f11b";} 298 | .icon-keyboard:before{content:"\f11c";} 299 | .icon-flag-alt:before{content:"\f11d";} 300 | .icon-flag-checkered:before{content:"\f11e";} 301 | .icon-terminal:before{content:"\f120";} 302 | .icon-code:before{content:"\f121";} 303 | .icon-reply-all:before{content:"\f122";} 304 | .icon-mail-reply-all:before{content:"\f122";} 305 | .icon-star-half-full:before,.icon-star-half-empty:before{content:"\f123";} 306 | .icon-location-arrow:before{content:"\f124";} 307 | .icon-crop:before{content:"\f125";} 308 | .icon-code-fork:before{content:"\f126";} 309 | .icon-unlink:before{content:"\f127";} 310 | .icon-question:before{content:"\f128";} 311 | .icon-info:before{content:"\f129";} 312 | .icon-exclamation:before{content:"\f12a";} 313 | .icon-superscript:before{content:"\f12b";} 314 | .icon-subscript:before{content:"\f12c";} 315 | .icon-eraser:before{content:"\f12d";} 316 | .icon-puzzle-piece:before{content:"\f12e";} 317 | .icon-microphone:before{content:"\f130";} 318 | .icon-microphone-off:before{content:"\f131";} 319 | .icon-shield:before{content:"\f132";} 320 | .icon-calendar-empty:before{content:"\f133";} 321 | .icon-fire-extinguisher:before{content:"\f134";} 322 | .icon-rocket:before{content:"\f135";} 323 | .icon-maxcdn:before{content:"\f136";} 324 | .icon-chevron-sign-left:before{content:"\f137";} 325 | .icon-chevron-sign-right:before{content:"\f138";} 326 | .icon-chevron-sign-up:before{content:"\f139";} 327 | .icon-chevron-sign-down:before{content:"\f13a";} 328 | .icon-html5:before{content:"\f13b";} 329 | .icon-css3:before{content:"\f13c";} 330 | .icon-anchor:before{content:"\f13d";} 331 | .icon-unlock-alt:before{content:"\f13e";} 332 | .icon-bullseye:before{content:"\f140";} 333 | .icon-ellipsis-horizontal:before{content:"\f141";} 334 | .icon-ellipsis-vertical:before{content:"\f142";} 335 | .icon-rss-sign:before{content:"\f143";} 336 | .icon-play-sign:before{content:"\f144";} 337 | .icon-ticket:before{content:"\f145";} 338 | .icon-minus-sign-alt:before{content:"\f146";} 339 | .icon-check-minus:before{content:"\f147";} 340 | .icon-level-up:before{content:"\f148";} 341 | .icon-level-down:before{content:"\f149";} 342 | .icon-check-sign:before{content:"\f14a";} 343 | .icon-edit-sign:before{content:"\f14b";} 344 | .icon-external-link-sign:before{content:"\f14c";} 345 | .icon-share-sign:before{content:"\f14d";} 346 | .icon-compass:before{content:"\f14e";} 347 | .icon-collapse:before{content:"\f150";} 348 | .icon-collapse-top:before{content:"\f151";} 349 | .icon-expand:before{content:"\f152";} 350 | .icon-euro:before,.icon-eur:before{content:"\f153";} 351 | .icon-gbp:before{content:"\f154";} 352 | .icon-dollar:before,.icon-usd:before{content:"\f155";} 353 | .icon-rupee:before,.icon-inr:before{content:"\f156";} 354 | .icon-yen:before,.icon-jpy:before{content:"\f157";} 355 | .icon-renminbi:before,.icon-cny:before{content:"\f158";} 356 | .icon-won:before,.icon-krw:before{content:"\f159";} 357 | .icon-bitcoin:before,.icon-btc:before{content:"\f15a";} 358 | .icon-file:before{content:"\f15b";} 359 | .icon-file-text:before{content:"\f15c";} 360 | .icon-sort-by-alphabet:before{content:"\f15d";} 361 | .icon-sort-by-alphabet-alt:before{content:"\f15e";} 362 | .icon-sort-by-attributes:before{content:"\f160";} 363 | .icon-sort-by-attributes-alt:before{content:"\f161";} 364 | .icon-sort-by-order:before{content:"\f162";} 365 | .icon-sort-by-order-alt:before{content:"\f163";} 366 | .icon-thumbs-up:before{content:"\f164";} 367 | .icon-thumbs-down:before{content:"\f165";} 368 | .icon-youtube-sign:before{content:"\f166";} 369 | .icon-youtube:before{content:"\f167";} 370 | .icon-xing:before{content:"\f168";} 371 | .icon-xing-sign:before{content:"\f169";} 372 | .icon-youtube-play:before{content:"\f16a";} 373 | .icon-dropbox:before{content:"\f16b";} 374 | .icon-stackexchange:before{content:"\f16c";} 375 | .icon-instagram:before{content:"\f16d";} 376 | .icon-flickr:before{content:"\f16e";} 377 | .icon-adn:before{content:"\f170";} 378 | .icon-bitbucket:before{content:"\f171";} 379 | .icon-bitbucket-sign:before{content:"\f172";} 380 | .icon-tumblr:before{content:"\f173";} 381 | .icon-tumblr-sign:before{content:"\f174";} 382 | .icon-long-arrow-down:before{content:"\f175";} 383 | .icon-long-arrow-up:before{content:"\f176";} 384 | .icon-long-arrow-left:before{content:"\f177";} 385 | .icon-long-arrow-right:before{content:"\f178";} 386 | .icon-apple:before{content:"\f179";} 387 | .icon-windows:before{content:"\f17a";} 388 | .icon-android:before{content:"\f17b";} 389 | .icon-linux:before{content:"\f17c";} 390 | .icon-dribbble:before{content:"\f17d";} 391 | .icon-skype:before{content:"\f17e";} 392 | .icon-foursquare:before{content:"\f180";} 393 | .icon-trello:before{content:"\f181";} 394 | .icon-female:before{content:"\f182";} 395 | .icon-male:before{content:"\f183";} 396 | .icon-gittip:before{content:"\f184";} 397 | .icon-sun:before{content:"\f185";} 398 | .icon-moon:before{content:"\f186";} 399 | .icon-archive:before{content:"\f187";} 400 | .icon-bug:before{content:"\f188";} 401 | .icon-vk:before{content:"\f189";} 402 | .icon-weibo:before{content:"\f18a";} 403 | .icon-renren:before{content:"\f18b";} 404 | -------------------------------------------------------------------------------- /scripts/spider/fSpider.card.groups.js: -------------------------------------------------------------------------------- 1 | var fSpider = fSpider || {}; 2 | 3 | ////dependencies\\\\ 4 | //fSpider 5 | fSpider.Card = fSpider.Card || {}; 6 | fSpider.PlayingCard = fSpider.PlayingCard || {}; 7 | fSpider.Utils = fSpider.Utils || {}; 8 | 9 | fSpider.Pile = (function (Pile, undefined) { 10 | 'use strict'; 11 | 12 | Pile = function () { 13 | }; 14 | 15 | //public fields 16 | Pile.prototype.cards = null; 17 | Pile.prototype.group = null; 18 | Pile.prototype.availHeight = 0; 19 | Pile.prototype.availWidth = 0; 20 | Pile.prototype.baseZIndex = 0; 21 | 22 | //getters/setters 23 | Pile.prototype.getCards = function () { 24 | return this.cards || []; 25 | }; 26 | 27 | Pile.prototype.getCardAt = function (index) { 28 | return this.cards[index]; 29 | }; 30 | 31 | Pile.prototype.getSize = function () { 32 | return (this.cards || []).length; 33 | }; 34 | 35 | Pile.prototype.getGroup = function () { 36 | return this.group; 37 | }; 38 | 39 | Pile.prototype.setScale = function (scale) { 40 | this.group.setScale(scale); 41 | }; 42 | 43 | Pile.prototype.setX = function (x) { 44 | this.group.setX(x); 45 | }; 46 | Pile.prototype.getX = function () { 47 | return this.group.getX(); 48 | }; 49 | 50 | Pile.prototype.setWidth = function (width) { 51 | this.group.setWidth(width); 52 | }; 53 | Pile.prototype.getWidth = function (scale) { 54 | if (scale == null) { 55 | scale = 1; 56 | } 57 | return this.group.getWidth() * scale; 58 | }; 59 | 60 | Pile.prototype.setY = function (y) { 61 | this.group.setY(y); 62 | }; 63 | Pile.prototype.getY = function () { 64 | return this.group.getY(); 65 | }; 66 | 67 | 68 | Pile.prototype.setHeight = function (height) { 69 | this.group.setHeight(height); 70 | }; 71 | Pile.prototype.getHeight = function (scale) { 72 | if (scale == null) { 73 | scale = 1; 74 | } 75 | return this.group.getHeight() * scale; 76 | }; 77 | 78 | Pile.prototype.setVisible = function (visible) { 79 | this.group.setVisible(visible); 80 | }; 81 | 82 | Pile.prototype.setAvailableWidth = function (width) { 83 | this.availWidth = width; 84 | }; 85 | 86 | Pile.prototype.setAvailableHeight = function (height) { 87 | this.availHeight = height; 88 | }; 89 | 90 | Pile.prototype.setAvailableDimensions = function (width, height) { 91 | this.availWidth = width; 92 | this.availHeight = height; 93 | }; 94 | 95 | //public functions 96 | Pile.prototype.moveToTop = function () { 97 | this.group.moveToTop(); 98 | }; 99 | 100 | Pile.prototype.transferCards = function (cards, settings, callback) { 101 | if (settings == null) { 102 | settings = {}; 103 | } 104 | 105 | if (cards == null || cards.length <= 0) { 106 | if (callback != null) { 107 | callback(); 108 | } 109 | return; 110 | } 111 | 112 | var self = this; 113 | var piles = []; 114 | var clndCards = cards.slice(0, cards.length); 115 | clndCards.forEach(function (card) { 116 | var absPos = { x: card.getAbsolutePosition().x, y: card.getAbsolutePosition().y }; 117 | var pile = card.getPile(); 118 | if (pile != null) { 119 | pile.removeCard(card); 120 | if (piles.indexOf(pile) < 0) { 121 | piles.push(pile); 122 | } 123 | } 124 | self.addCard(card, absPos); 125 | }); 126 | piles.forEach(function (pile) { 127 | pile.resetListening(); 128 | pile.resetDraggable(); 129 | }); 130 | 131 | var fromIndex = this.cards.indexOf(cards[0]); 132 | if (fromIndex < 0) { 133 | fromIndex = 0; 134 | } 135 | this.arrangeCards(settings, callback, fromIndex); 136 | }; 137 | 138 | Pile.prototype.addCard = function (card, absPos) { 139 | card.setPile(this); 140 | this.cards.push(card); 141 | this.group.add(card.getGroup()); 142 | card.getGroup().setZIndex(this.baseZIndex + this.cards.indexOf(card)); 143 | if (absPos != null) { 144 | card.setAbsolutePosition(absPos); 145 | } 146 | }; 147 | 148 | Pile.prototype.addCards = function (cards, absPositions) { 149 | var self = this; 150 | cards.forEach(function (card, i) { 151 | var absPos; 152 | if (absPositions != null && i < absPositions.length) { 153 | absPos = absPositions[i]; 154 | } 155 | self.addCard(card, absPos); 156 | }); 157 | }; 158 | 159 | Pile.prototype.removeCard = function (card) { 160 | var index = this.cards.indexOf(card); 161 | if (index >= 0) { 162 | this.cards.splice(index, 1); 163 | card.setPile(undefined); 164 | card.remove(); 165 | } 166 | return card; 167 | }; 168 | 169 | Pile.prototype.removeAllCards = function () { 170 | while (this.cards.length > 0) { 171 | this.removeCard(this.cards[0]); 172 | } 173 | }; 174 | 175 | Pile.prototype.arrangeCards = function (settings, callback, fromIndex) { 176 | //specific to pile type 177 | }; 178 | 179 | Pile.prototype.resetCardFaces = function (settings, callback) { 180 | //specific to pile type 181 | }; 182 | 183 | Pile.prototype.resetListening = function () { 184 | //specific to pile type 185 | }; 186 | 187 | Pile.prototype.resetDraggable = function () { 188 | //specific to pile type 189 | }; 190 | 191 | Pile.prototype.resetCardZOrder = function () { 192 | var base = this.baseZIndex; 193 | this.cards.forEach(function (card, i) { 194 | card.setZIndex(base + i); 195 | }); 196 | }; 197 | 198 | 199 | Pile.prototype.reverseCards = function () { 200 | var cards = this.cards.reverse(); 201 | cards.forEach(function (card) { 202 | card.getGroup().moveToTop(); 203 | }); 204 | }; 205 | 206 | Pile.prototype.getLastCard = function () { 207 | var length = this.getSize(); 208 | if (length > 0) { 209 | return this.cards[length - 1]; 210 | } 211 | //else 212 | return null; 213 | }; 214 | 215 | Pile.prototype.getCardAndCardsAfter = function (card) { 216 | var cardsToGive = []; 217 | var length = this.getSize(); 218 | 219 | var index = this.cards.indexOf(card); 220 | if (index >= 0) { 221 | for (var i = index; i < length; i++) { 222 | cardsToGive.push(this.cards[i]); 223 | } 224 | } 225 | 226 | return cardsToGive; 227 | }; 228 | 229 | Pile.prototype.countCardsAnimating = function () { 230 | var animating = 0; 231 | var length = this.cards.length; 232 | for (var i = 0; i < length; i++) { 233 | if (this.cards[i].areAnyAnimationsRunning() === true) { 234 | animating++; 235 | } 236 | } 237 | return animating; 238 | }; 239 | 240 | Pile.prototype.moveAllCardsToGroup = function () { 241 | if (this.group == null) { 242 | return; 243 | } 244 | 245 | var length = this.cards.length; 246 | var card, pos; 247 | for (var i = 0; i < length; i++) { 248 | card = this.cards[i]; 249 | if (card.getGroup().getParent() !== this.group) { 250 | pos = card.getAbsolutePosition(); 251 | card.getGroup().moveTo(this.group); 252 | card.setAbsolutePosition(pos); 253 | } 254 | } 255 | this.resetCardZOrder(); 256 | }; 257 | 258 | Pile.prototype.destroy = function () { 259 | this.removeAllCards(); 260 | this.group.remove(); 261 | }; 262 | 263 | return Pile; 264 | })(fSpider.Pile || {}); 265 | 266 | fSpider.TableauPile = (function (TableauPile, undefined) { 267 | 'use strict'; 268 | 269 | var Pile = fSpider.Pile; 270 | var PlayingCard = fSpider.PlayingCard; 271 | var Utils = fSpider.Utils; 272 | 273 | //constructor 274 | TableauPile = function (cards) { 275 | this.cards = cards || []; 276 | this.group = new Kinetic.Group(); 277 | this.baseZIndex = 2; 278 | 279 | this.placeHolderImg = new Kinetic.Image(); 280 | 281 | this.hoverBorder = new Kinetic.Rect({ 282 | visible: false, 283 | opacity: this.HOVER_BORDER.opacity, 284 | fill: this.HOVER_BORDER.fill, 285 | stroke: this.HOVER_BORDER.stroke, 286 | strokeWidth: this.HOVER_BORDER.strokeWidth, 287 | cornerRadius: this.HOVER_BORDER.cornerRadius, 288 | width: PlayingCard.CARD_DIM.w, 289 | height: PlayingCard.CARD_DIM.h 290 | }); 291 | this.group.add(this.hoverBorder); 292 | this.group.add(this.placeHolderImg); 293 | 294 | this.setWidth(PlayingCard.CARD_DIM.w); 295 | }; 296 | 297 | Utils.extendObj(TableauPile, Pile); 298 | 299 | //fields 300 | TableauPile.prototype.hovering = false; 301 | TableauPile.prototype.hoverBorder = null; 302 | 303 | TableauPile.prototype.HOVER_BORDER = { 304 | 'visible': true, 305 | 'stroke': '#FFFF99', 306 | 'strokeWidth': 5, 307 | 'cornerRadius': 4, 308 | 'fill': '#FFFF99', 309 | 'opacity': 0.25 310 | }; 311 | 312 | //getters/setters 313 | TableauPile.prototype.getPlaceHolderImg = function () { 314 | return this.placeHolderImg; 315 | }; 316 | 317 | TableauPile.prototype.setHovering = function (hovering) { 318 | if (this.hovering === hovering) { 319 | return; 320 | } 321 | this.hovering = hovering; 322 | this.refresh(); 323 | }; 324 | TableauPile.prototype.isHovering = function () { 325 | return this.hovering; 326 | }; 327 | 328 | TableauPile.prototype.getPlaceHolderWidth = function () { 329 | return this.placeHolderImg.getWidth(); 330 | }; 331 | TableauPile.prototype.setPlaceHolderWidth = function (width) { 332 | if (this.placeHolderImg != null) { 333 | this.placeHolderImg.setWidth(width); 334 | } 335 | if (this.hoverBorder != null) { 336 | this.hoverBorder.setWidth(width); 337 | } 338 | }; 339 | 340 | TableauPile.prototype.getPlaceHolderHeight = function () { 341 | return this.placeHolderImg.getHeight(); 342 | }; 343 | TableauPile.prototype.setPlaceHolderHeight = function (height) { 344 | if (this.placeHolderImg != null) { 345 | this.placeHolderImg.setHeight(height); 346 | } 347 | if (this.hoverBorder != null) { 348 | this.hoverBorder.setHeight(height); 349 | } 350 | }; 351 | 352 | //public methods 353 | TableauPile.prototype.refresh = function () { 354 | //hover border 355 | this.hoverBorder.setVisible(this.hovering === true && this.HOVER_BORDER.visible); 356 | }; 357 | 358 | TableauPile.prototype.getCompleteSequence = function () { 359 | var nCardsInCompleteSequence = 13; 360 | var card; 361 | 362 | var sequence = []; 363 | var length = this.getSize(); 364 | 365 | //basic check first, in case we don't have to iterate through all cards 366 | if (length < nCardsInCompleteSequence || this.cards[length - nCardsInCompleteSequence].isFaceUp() !== true) { //don't have enough faceup cards 367 | return sequence; 368 | } 369 | 370 | //otherwise we try find the sequence from top to bottom 371 | for (var i = 0; i < length; i++) { 372 | card = this.cards[i]; 373 | if (card.isFaceUp() !== true) { //not face up 374 | continue; //just skip it 375 | } 376 | if (sequence.length === 0) { //no possible sequence started yet 377 | if (card.getType() === PlayingCard.CARD_TYPES.king) { //card is a king 378 | sequence.push(card); //start a possible sequence 379 | } 380 | } else { //possible sequence already started 381 | var lastCard = sequence[sequence.length - 1]; 382 | if (card.getSuit() === lastCard.getSuit() && card.getType() === lastCard.getType() - 1) { //same suit and type less by 1 383 | sequence.push(card); //add to possible sequence 384 | } else { //doesn't fit 385 | sequence = []; //restart search 386 | if (card.getType() === PlayingCard.CARD_TYPES.king) { //card is a king 387 | sequence.push(card); //start a possible sequence 388 | } 389 | } 390 | } 391 | } 392 | 393 | //make sure it's a complete sequence 394 | if (sequence.length !== nCardsInCompleteSequence) { 395 | sequence = []; 396 | } 397 | 398 | return sequence; 399 | }; 400 | 401 | TableauPile.prototype.setLastCardFaceUp = function (faceUp, settings, callback) { 402 | if (settings == null) { 403 | settings = {}; 404 | } 405 | 406 | var changed = false; 407 | 408 | var length = this.getSize(); 409 | if (length > 0) { 410 | var card = this.cards[length - 1]; 411 | changed = card.isFaceUp() !== faceUp; 412 | card.setFaceUp(faceUp, settings, function () { 413 | if (callback != null) { 414 | callback(true); 415 | } 416 | }); 417 | } 418 | 419 | if (changed !== true) { 420 | if (callback != null) { 421 | callback(false); 422 | } 423 | } 424 | 425 | return changed; 426 | }; 427 | 428 | TableauPile.prototype.loadPlaceHolderImg = function (img, cropSqr, w, h) { 429 | if (this.placeHolderImg == null) { 430 | this.placeHolderImg = new Kinetic.Image(); 431 | if (this.group != null) { 432 | this.group.add(this.placeHolderImg); 433 | } 434 | } 435 | this.placeHolderImg.setImage(img); 436 | this.placeHolderImg.moveToBottom(); 437 | this.hoverBorder.moveToBottom(); 438 | if (cropSqr != null) { 439 | this.placeHolderImg.setCrop(cropSqr); 440 | } 441 | if (w != null) { 442 | this.setPlaceHolderWidth(w); 443 | } 444 | if (h != null) { 445 | this.setPlaceHolderHeight(h); 446 | } 447 | }; 448 | 449 | TableauPile.prototype.canAddCard = function (card) { 450 | var length = this.getSize(); 451 | if (length === 0) { //if no cards, always allowed 452 | return true; 453 | } 454 | var lastCard = this.cards[length - 1]; //check last card 455 | //needs to be face up and of a type greater by 1 456 | return lastCard.isFaceUp() === true && lastCard.getType() === card.getType() + 1; 457 | }; 458 | 459 | TableauPile.prototype.canRemoveCard = function (card) { 460 | var length = this.getSize(); 461 | var cardT; 462 | //basic conditions first 463 | if (card.isFaceUp() !== true) { 464 | return false; 465 | } 466 | var i = this.cards.indexOf(card); 467 | i++; //so we can start scanning cards after it 468 | while (i < length) { 469 | cardT = this.cards[i]; 470 | if (cardT.getSuit() !== card.getSuit() || cardT.getType() !== this.cards[i - 1].getType() - 1) { 471 | return false; 472 | } 473 | i++; 474 | } 475 | return true; 476 | }; 477 | 478 | TableauPile.prototype.getFirstCardThatCanRemove = function () { 479 | var length = this.getSize(); 480 | var card = null; 481 | var cardT; 482 | var i = length - 1; 483 | while (length >= 0) { 484 | cardT = this.cards[i]; 485 | //has to be face up 486 | if (cardT.isFaceUp() !== true) { 487 | break; 488 | } 489 | //if not last card and has same suit and type is one more than last one, can remove 490 | if (i < length - 1 && (cardT.getSuit() !== card.getSuit() || cardT.getType() !== card.getType() + 1)) { 491 | break; 492 | } //else 493 | card = cardT; 494 | i--; 495 | } 496 | return card; 497 | }; 498 | 499 | TableauPile.prototype.arrangeCards = function (settings, callback, fromIndex) { 500 | if (settings == null) { 501 | settings = {}; 502 | } 503 | if (fromIndex == null || fromIndex < 0) { 504 | fromIndex = 0; 505 | } 506 | 507 | var cards = this.cards; 508 | var length = cards.length; 509 | 510 | //count all face up cards (for padding amount) 511 | var faceUpCount = 0; 512 | var faceDownCount = 0; 513 | for (var i = 0; i < length; i++) { 514 | if (cards[i].isFaceUp() === true) { 515 | faceUpCount++; 516 | } else { 517 | faceDownCount++; 518 | } 519 | } 520 | 521 | //calculate padding 522 | var padTopFaceDown = 7; 523 | if (this.availHeight - (padTopFaceDown * faceDownCount) < 2) { 524 | padTopFaceDown = 2; 525 | } 526 | var faceDownTotalPad = faceDownCount * padTopFaceDown; 527 | 528 | var maxPadTopFaceUp = 20; 529 | var padTopFaceUp = (this.availHeight - PlayingCard.CARD_DIM.h - faceDownTotalPad) / faceUpCount; 530 | if (faceUpCount > 12) { 531 | padTopFaceUp /= 1.5; 532 | } 533 | if (padTopFaceUp < 14) { 534 | padTopFaceUp = 14; 535 | } 536 | if (padTopFaceUp > maxPadTopFaceUp) { 537 | padTopFaceUp = maxPadTopFaceUp; 538 | } 539 | 540 | var stillLooping = true; 541 | var expectedCallbacks = 0; 542 | var onCallback = function () { 543 | expectedCallbacks--; 544 | if (stillLooping !== true && expectedCallbacks <= 0 && callback != null) { 545 | callback(); 546 | } 547 | }; 548 | 549 | var y = 0; 550 | var prevCard; 551 | //distribute height 552 | for (i = 0; i < length; i++) { 553 | expectedCallbacks++; 554 | if (i === length - 1) { 555 | stillLooping = false; 556 | } 557 | if (i > 0) { 558 | prevCard = this.cards[i - 1]; 559 | if (prevCard.isFaceUp() === true) { 560 | y += padTopFaceUp; 561 | if (prevCard.isSelected() === true) { 562 | y += padTopFaceUp; 563 | } 564 | } else { 565 | y += padTopFaceDown; 566 | } 567 | } 568 | if (i >= fromIndex) { 569 | this.cards[i].setPosition(0, y, settings, onCallback); 570 | } else { 571 | expectedCallbacks--; 572 | } 573 | } 574 | var height = y + PlayingCard.CARD_DIM.h; 575 | 576 | this.group.setHeight(height); 577 | }; 578 | 579 | TableauPile.prototype.resetCardFaces = function (settings, callback) { 580 | if (settings == null) { 581 | settings = {}; 582 | } 583 | 584 | var stillLooping = true; 585 | var expectedCallbacks = 0; 586 | var onCallback = function () { 587 | expectedCallbacks--; 588 | if (stillLooping !== true && expectedCallbacks <= 0 && callback != null) { 589 | callback(); 590 | } 591 | }; 592 | 593 | var card; 594 | var length = this.getSize(); 595 | for (var i = 0; i < length; i++) { 596 | card = this.cards[i]; 597 | expectedCallbacks++; 598 | if (i === length - 1) { //if last card 599 | stillLooping = false; 600 | card.setFaceUp(true, settings, onCallback); 601 | } else { //otherwise 602 | card.setFaceUp(false, settings, onCallback); 603 | } 604 | } 605 | }; 606 | 607 | TableauPile.prototype.resetListening = function () { 608 | this.cards.forEach(function (card) { 609 | card.setListening(card.isFaceUp()); 610 | }); 611 | var length = this.getSize(); 612 | if (length > 0) { 613 | this.cards[length - 1].setListening(true); 614 | } 615 | 616 | if (this.placeHolderImg != null) { 617 | this.placeHolderImg.setListening(length === 0); 618 | } 619 | }; 620 | 621 | TableauPile.prototype.resetDraggable = function () { 622 | var self = this; 623 | this.cards.forEach(function (card) { 624 | card.setDraggable(self.canRemoveCard(card)); 625 | }); 626 | }; 627 | 628 | return TableauPile; 629 | })(fSpider.TableauPile || {}); 630 | 631 | fSpider.StockPile = (function (StockPile, undefined) { 632 | 'use strict'; 633 | 634 | var Pile = fSpider.Pile; 635 | var PlayingCard = fSpider.PlayingCard; 636 | var Utils = fSpider.Utils; 637 | 638 | //constructor 639 | StockPile = function (cards) { 640 | this.cards = cards || []; 641 | this.group = new Kinetic.Group(); 642 | this.setHeight(PlayingCard.CARD_DIM.h); 643 | }; 644 | 645 | Utils.extendObj(StockPile, Pile); 646 | 647 | //getters/setters 648 | 649 | //public methods 650 | StockPile.prototype.arrangeCards = function (settings, callback, fromIndex) { 651 | if (settings == null) { 652 | settings = {}; 653 | } 654 | 655 | if (fromIndex == null) { 656 | fromIndex = 0; 657 | } 658 | 659 | var stillLooping = true; 660 | var expectedCallbacks = 0; 661 | var onCallback = function () { 662 | expectedCallbacks--; 663 | if (stillLooping !== true && expectedCallbacks <= 0 && callback != null) { 664 | callback(); 665 | } 666 | }; 667 | 668 | var tableauPiles = 10; 669 | var length = this.getSize(); 670 | var card; 671 | 672 | var nSets = Math.floor(length / tableauPiles); 673 | if (nSets == 0) { 674 | nSets = .00000001; 675 | } 676 | var paddingRight = (this.availWidth - PlayingCard.CARD_DIM.w) / nSets; 677 | if (paddingRight < 0) { 678 | paddingRight = 0; 679 | } 680 | 681 | for (var i = 0; i < length; i++) { 682 | card = this.cards[i]; 683 | expectedCallbacks++; 684 | if (i === length - 1) { 685 | stillLooping = false; 686 | } 687 | card.setPosition(Math.floor((length - i - 1) / tableauPiles) * paddingRight, 0, settings, onCallback); 688 | } 689 | 690 | this.setWidth(paddingRight * nSets + PlayingCard.CARD_DIM.w); 691 | }; 692 | 693 | StockPile.prototype.resetCardFaces = function (settings, callback) { 694 | if (settings == null) { 695 | settings = {}; 696 | } 697 | 698 | var stillLooping = true; 699 | var expectedCallbacks = 0; 700 | var onCallback = function () { 701 | expectedCallbacks--; 702 | if (stillLooping !== true && expectedCallbacks <= 0 && callback != null) { 703 | callback(); 704 | } 705 | }; 706 | 707 | var self = this; 708 | this.cards.forEach(function (card, i) { 709 | expectedCallbacks++; 710 | if (i === self.cards.length - 1) { 711 | stillLooping = false; 712 | } 713 | card.setFaceUp(false, settings, onCallback); 714 | }); 715 | }; 716 | 717 | StockPile.prototype.resetListening = function () { 718 | this.cards.forEach(function (card) { 719 | card.setListening(false); 720 | }); 721 | var length = this.getSize(); 722 | if (length > 0) { 723 | this.cards[length - 1].setListening(true); 724 | } 725 | }; 726 | 727 | StockPile.prototype.resetDraggable = function () { 728 | this.cards.forEach(function (card) { 729 | card.setDraggable(false); 730 | }); 731 | }; 732 | 733 | StockPile.prototype.drawCards = function (piles, setFaceUp, settings, callback) { 734 | if (settings == null) { 735 | settings = {}; 736 | } 737 | 738 | var stillLooping = true; 739 | var expectedCallbacks = 0; 740 | var onCallback = function () { 741 | expectedCallbacks--; 742 | if (stillLooping !== true && expectedCallbacks <= 0) { 743 | var uniquePiles = []; 744 | piles.forEach(function (pile) { 745 | if (uniquePiles.indexOf(pile) < 0) { 746 | pile.resetListening(); 747 | pile.resetDraggable(); 748 | uniquePiles.push(pile); 749 | } 750 | }); 751 | if (callback != null) { 752 | callback(); 753 | } 754 | } 755 | }; 756 | 757 | var delay = 0; 758 | if (settings.animate === true) { 759 | delay = settings.animDelay; 760 | } 761 | 762 | var pLength = piles.length; 763 | var pile, card; 764 | for (var i = 0; i < pLength; i++) { 765 | if (this.getSize() <= 0) { 766 | break; 767 | } 768 | pile = piles[i]; 769 | card = this.getLastCard(); 770 | if (setFaceUp === true) { 771 | expectedCallbacks++; 772 | card.setFaceUp(true, settings.extendAnimDelay(delay * i), onCallback); 773 | } 774 | expectedCallbacks++; 775 | if (i === pLength - 1) { 776 | stillLooping = false; 777 | } 778 | pile.transferCards([card], settings.extendAnimDelay(delay * i), onCallback); 779 | } 780 | }; 781 | 782 | return StockPile; 783 | })(fSpider.StockPile || {}); 784 | 785 | fSpider.FoundationPile = (function (FoundationPile, undefined) { 786 | 'use strict'; 787 | 788 | var Pile = fSpider.Pile; 789 | var PlayingCard = fSpider.PlayingCard; 790 | var Utils = fSpider.Utils; 791 | 792 | //constructor 793 | FoundationPile = function (cards) { 794 | this.cards = cards || []; 795 | this.group = new Kinetic.Group(); 796 | this.setWidth(PlayingCard.CARD_DIM.w); 797 | this.setHeight(PlayingCard.CARD_DIM.h); 798 | }; 799 | 800 | Utils.extendObj(FoundationPile, Pile); 801 | 802 | //getters/setters 803 | 804 | //public methods 805 | FoundationPile.prototype.arrangeCards = function (settings, callback) { 806 | if (settings == null) { 807 | settings = {}; 808 | } 809 | 810 | var stillLooping = true; 811 | var expectedCallbacks = 0; 812 | var onCallback = function () { 813 | expectedCallbacks--; 814 | if (stillLooping !== true && expectedCallbacks <= 0 && callback != null) { 815 | callback(); 816 | } 817 | }; 818 | 819 | var self = this; 820 | this.cards.forEach(function (card, i) { 821 | expectedCallbacks++; 822 | if (i === self.cards.length - 1) { 823 | stillLooping = false; 824 | } 825 | card.setPosition(0, 0, settings, onCallback); 826 | }); 827 | }; 828 | 829 | FoundationPile.prototype.resetCardFaces = function (settings, callback) { 830 | if (settings == null) { 831 | settings = {}; 832 | } 833 | 834 | var stillLooping = true; 835 | var expectedCallbacks = 0; 836 | var onCallback = function () { 837 | expectedCallbacks--; 838 | if (stillLooping !== true && expectedCallbacks <= 0 && callback != null) { 839 | callback(); 840 | } 841 | }; 842 | 843 | var self = this; 844 | this.cards.forEach(function (card, i) { 845 | expectedCallbacks++; 846 | if (i === self.cards.length - 1) { 847 | stillLooping = false; 848 | } 849 | card.setFaceUp(true, settings, onCallback); 850 | }); 851 | }; 852 | 853 | FoundationPile.prototype.resetListening = function () { 854 | this.cards.forEach(function (card) { 855 | card.setListening(false); 856 | }); 857 | }; 858 | 859 | FoundationPile.prototype.resetDraggable = function () { 860 | this.cards.forEach(function (card) { 861 | card.setDraggable(false); 862 | }); 863 | }; 864 | 865 | return FoundationPile; 866 | })(fSpider.FoundationPile || {}); -------------------------------------------------------------------------------- /scripts/spider/fSpider.card.js: -------------------------------------------------------------------------------- 1 | var fSpider = fSpider || {}; 2 | ////dependencies\\\\ 3 | //fSpider 4 | fSpider.Utils = fSpider.Utils || {}; 5 | 6 | fSpider.Card = (function (Card, Kinetic, undefined) { 7 | 'use strict'; 8 | 9 | var Utils = fSpider.Utils; 10 | 11 | //constructor 12 | Card = function () { 13 | }; 14 | 15 | //fields 16 | Card.prototype.hovering = null; 17 | Card.prototype.selected = null; 18 | Card.prototype.faceUp = null; 19 | Card.prototype.pile = null; 20 | 21 | Card.prototype.group = null; 22 | Card.prototype.faceImg = null; 23 | Card.prototype.backImg = null; 24 | Card.prototype.border = null; 25 | Card.prototype.activeBorder = null; 26 | Card.prototype.hoverBorder = null; 27 | 28 | Card.prototype.cardFlipSound = null; 29 | Card.prototype.cardMoveSound = null; 30 | 31 | Card.prototype.animationLayer = null; 32 | Card.prototype.positionAnimator = null; 33 | Card.prototype.positionAnimatorContext = null; 34 | Card.prototype.positionAnimationTimeout = null; 35 | Card.prototype.flipAnimator = null; 36 | Card.prototype.flipAnimatorContext = null; 37 | Card.prototype.flipAnimationTimeout = null; 38 | 39 | Card.prototype.borderProps = { 40 | 'visible': true, 41 | 'stroke': '#F5F5F5', 42 | 'strokeWidth': 1.5, 43 | 'cornerRadius': 3.5, 44 | 'fill': '', 45 | 'opacity': 1, 46 | 'padding': -.25 47 | }; 48 | Card.prototype.activeBorderProps = { 49 | 'visible': true, 50 | 'stroke': '#fff9b0', 51 | 'strokeWidth': 4, 52 | 'cornerRadius': 6, 53 | 'fill': '', 54 | 'opacity': .9, 55 | 'padding': 2 56 | }; 57 | Card.prototype.hoverBorderProps = { 58 | 'visible': true, 59 | 'stroke': '#a8a8a8', 60 | 'strokeWidth': 1.25, 61 | 'cornerRadius': 4, 62 | 'fill': '', 63 | 'opacity': 1, 64 | 'padding': 0 65 | }; 66 | 67 | //getters setters 68 | Card.prototype.getFaceImg = function () { 69 | return this.faceImg; 70 | }; 71 | 72 | Card.prototype.getBackImg = function () { 73 | return this.backImg; 74 | }; 75 | 76 | Card.prototype.getGroup = function () { 77 | return this.group; 78 | }; 79 | 80 | Card.prototype.getBorder = function () { 81 | return this.border; 82 | }; 83 | 84 | Card.prototype.getActiveBorder = function () { 85 | return this.activeBorder; 86 | }; 87 | 88 | Card.prototype.getHoverBorder = function () { 89 | return this.hoverBorder; 90 | }; 91 | 92 | Card.prototype.setAnimationLayer = function (layer) { 93 | this.animationLayer = layer; 94 | }; 95 | Card.prototype.getAnimationLayer = function () { 96 | return this.animationLayer; 97 | }; 98 | 99 | Card.prototype.setCardFlipSound = function (cardFlipSound) { 100 | this.cardFlipSound = cardFlipSound; 101 | }; 102 | 103 | Card.prototype.setCardMoveSound = function (cardMoveSound) { 104 | this.cardMoveSound = cardMoveSound; 105 | }; 106 | 107 | Card.prototype.getPile = function () { 108 | return this.pile; 109 | }; 110 | Card.prototype.setPile = function (pile) { 111 | this.pile = pile; 112 | }; 113 | 114 | Card.prototype.isFaceUp = function () { 115 | return this.faceUp; 116 | }; 117 | Card.prototype.setFaceUp = function (faceUp, settings, callback) { 118 | if (settings == null) { 119 | settings = {}; 120 | } 121 | 122 | //stop any existing position animation 123 | if (this.isFlipAnimationRunning() === true) { 124 | this.stopFlipAnimation(true); 125 | } 126 | 127 | if (this.faceUp === faceUp) { 128 | if (callback != null) { 129 | callback(this); 130 | } 131 | return; 132 | } 133 | 134 | this.faceUp = faceUp; 135 | 136 | var animTime = 0; 137 | var delay = 0; 138 | if (settings.animate === true) { 139 | if (settings.animTime != null) { 140 | animTime = settings.animTime; 141 | } 142 | if (settings.animDelay != null) { 143 | delay = settings.animDelay + 0; 144 | } 145 | this.flipAnimatorContext = this.prepareFlipAnimationContext(faceUp, animTime, callback); 146 | } 147 | var sound = false; 148 | if (settings.volume != null && this.cardFlipSound != null) { 149 | this.cardFlipSound.volume(settings.volume); 150 | sound = true; 151 | } 152 | 153 | var self = this; 154 | var flip = function () { 155 | if (animTime > 0) { 156 | self.group.getLayer().draw(); 157 | self.startFlipAnimation(); 158 | } else { 159 | self.refresh(); 160 | if (callback != null) { 161 | callback(self); 162 | } 163 | } 164 | if (sound === true) { 165 | self.cardFlipSound.play(); 166 | } 167 | }; 168 | 169 | if (delay > 0) { 170 | this.flipAnimationTimeout = setTimeout(function () { 171 | flip(); 172 | 173 | clearTimeout(self.flipAnimationTimeout); 174 | self.flipAnimationTimeout = null; 175 | }, delay); 176 | } else { 177 | flip(); 178 | } 179 | }; 180 | 181 | Card.prototype.setPosition = function (x, y, settings, callback) { 182 | if (settings == null) { 183 | settings = {}; 184 | } 185 | 186 | //stop any existing position animation 187 | if (this.isPositionAnimationRunning() === true) { 188 | this.stopPositionAnimation(false); 189 | } 190 | 191 | if (Math.abs(this.group.getX() - x) < .001 && Math.abs(this.group.getY() - y) < .001) { 192 | if (callback != null) { 193 | callback(this); 194 | } 195 | return; 196 | } 197 | 198 | var animTime = 0; 199 | var delay = 0; 200 | if (settings.animate === true) { 201 | if (settings.animTime != null) { 202 | animTime = settings.animTime; 203 | } 204 | if (settings.animDelay != null) { 205 | delay = settings.animDelay; 206 | } 207 | this.positionAnimatorContext = this.preparePositionAnimationContext(x, y, animTime, callback); 208 | } 209 | var sound = false; 210 | if (settings.volume != null && this.cardMoveSound != null) { 211 | this.cardMoveSound.volume(settings.volume); 212 | sound = true; 213 | } 214 | 215 | var self = this; 216 | var setPos = function () { 217 | if (animTime > 0) { 218 | self.startPositionAnimation(); 219 | } else { 220 | self.group.setPosition(x, y); 221 | if (callback != null) { 222 | callback(self); 223 | } 224 | } 225 | 226 | if (sound === true) { 227 | self.cardMoveSound.play(); 228 | } 229 | }; 230 | 231 | if (delay > 0) { 232 | this.positionAnimationTimeout = setTimeout(function () { 233 | setPos(); 234 | 235 | clearTimeout(self.positionAnimationTimeout); 236 | self.positionAnimationTimeout = null; 237 | }, delay); 238 | } else { 239 | setPos(); 240 | } 241 | }; 242 | Card.prototype.getPosition = function () { 243 | return this.group.getPosition(); 244 | }; 245 | 246 | Card.prototype.getX = function () { 247 | return this.group.getX(); 248 | }; 249 | 250 | Card.prototype.getY = function () { 251 | return this.group.getY(); 252 | }; 253 | 254 | Card.prototype.getWidth = function (scale) { 255 | if (scale == null) { 256 | scale = this.group.getScaleX(); 257 | } 258 | return this.group.getWidth() * scale; 259 | }; 260 | Card.prototype.setWidth = function (width) { 261 | if (this.group != null) { 262 | this.group.setWidth(width); 263 | } 264 | if (this.border != null) { 265 | this.border.setWidth(width + this.borderProps.padding * 2); 266 | } 267 | if (this.activeBorder != null) { 268 | this.activeBorder.setWidth(width + this.activeBorderProps.padding * 2); 269 | } 270 | if (this.hoverBorder != null) { 271 | this.hoverBorder.setWidth(width + this.hoverBorderProps.padding * 2); 272 | } 273 | if (this.backImg != null) { 274 | this.backImg.setWidth(width); 275 | } 276 | if (this.faceImg != null) { 277 | this.faceImg.setWidth(width); 278 | } 279 | }; 280 | 281 | Card.prototype.getHeight = function (scale) { 282 | if (scale == null) { 283 | scale = this.group.getScaleY(); 284 | } 285 | return this.group.getHeight() * scale; 286 | }; 287 | Card.prototype.setHeight = function (height) { 288 | if (this.group != null) { 289 | this.group.setHeight(height); 290 | } 291 | if (this.border != null) { 292 | this.border.setHeight(height + this.borderProps.padding * 2); 293 | } 294 | if (this.activeBorder != null) { 295 | this.activeBorder.setHeight(height + this.activeBorderProps.padding * 2); 296 | } 297 | if (this.hoverBorder != null) { 298 | this.hoverBorder.setHeight(height + this.hoverBorderProps.padding * 2); 299 | } 300 | if (this.backImg != null) { 301 | this.backImg.setHeight(height); 302 | } 303 | if (this.faceImg != null) { 304 | this.faceImg.setHeight(height); 305 | } 306 | }; 307 | 308 | Card.prototype.getAbsolutePosition = function () { 309 | return this.group.getAbsolutePosition(); 310 | }; 311 | Card.prototype.setAbsolutePosition = function (absPos) { 312 | return this.group.setAbsolutePosition(absPos); 313 | }; 314 | 315 | Card.prototype.setZIndex = function (zIndex) { 316 | this.group.setZIndex(zIndex); 317 | }; 318 | 319 | Card.prototype.getAbsoluteCenter = function (scale) { 320 | if (scale === undefined) { 321 | scale = 1; 322 | } 323 | var pos = this.group.getAbsolutePosition(); 324 | return { 325 | 'x': pos.x + (this.getWidth(scale) / 2), 326 | 'y': pos.y + (this.getHeight(scale) / 2) 327 | }; 328 | }; 329 | 330 | Card.prototype.setListening = function (listening) { 331 | this.group.setListening(listening); 332 | }; 333 | 334 | Card.prototype.setDraggable = function (draggable) { 335 | this.group.setDraggable(draggable); 336 | }; 337 | 338 | Card.prototype.setVisible = function (visible) { 339 | this.getGroup().setVisible(visible); 340 | }; 341 | 342 | Card.prototype.setHovering = function (hovering) { 343 | if (this.hovering === hovering) { 344 | return; 345 | } 346 | this.hovering = hovering; 347 | this.refresh(); 348 | }; 349 | Card.prototype.isHovering = function () { 350 | return this.hovering; 351 | }; 352 | 353 | //wont' tell pile 354 | Card.prototype.setSelected = function (selected, tellParent, settings) { 355 | if (settings == null) { 356 | settings = {}; 357 | } 358 | 359 | if (this.selected === selected) { 360 | return; 361 | } 362 | this.selected = selected; 363 | this.refresh(); 364 | if (tellParent === true && this.pile != null) { 365 | this.pile.arrangeCards(settings); 366 | } 367 | }; 368 | Card.prototype.isSelected = function () { 369 | return this.selected; 370 | }; 371 | 372 | Card.prototype.on = function (eventName, callback) { 373 | this.group.on(eventName, callback); 374 | }; 375 | 376 | Card.prototype.off = function (eventName, callback) { 377 | this.group.off(eventName, callback); 378 | }; 379 | 380 | //public methods 381 | Card.prototype.refresh = function () { 382 | //card face/back visibility 383 | if (this.faceImg != null) { 384 | this.faceImg.setVisible(this.faceUp === true); 385 | } 386 | if (this.backImg != null) { 387 | this.backImg.setVisible(this.faceUp !== true); 388 | } 389 | 390 | //active boarder 391 | this.activeBorder.setVisible(this.hovering === true || this.selected === true); 392 | 393 | //hover border 394 | this.hoverBorder.setVisible(this.hovering === true); 395 | }; 396 | 397 | Card.prototype.remove = function () { 398 | this.group.remove(); 399 | }; 400 | 401 | Card.prototype.loadFaceImg = function (img, cropSqr, w, h) { 402 | if (this.faceImg == null) { 403 | this.faceImg = new Kinetic.Image(); 404 | if (this.group != null) { 405 | this.group.add(this.faceImg); 406 | } 407 | } 408 | this.faceImg.setImage(img); 409 | this.faceImg.moveToBottom(); 410 | if (cropSqr != null) { 411 | this.faceImg.setCrop(cropSqr); 412 | } 413 | if (w != null) { 414 | this.setWidth(w); 415 | } 416 | if (h != null) { 417 | this.setHeight(h); 418 | } 419 | }; 420 | 421 | Card.prototype.loadBackImg = function (img, cropSqr, w, h) { 422 | if (this.backImg == null) { 423 | this.backImg = new Kinetic.Image(); 424 | if (this.group != null) { 425 | this.group.add(this.backImg); 426 | } 427 | } 428 | this.backImg.setImage(img); 429 | this.backImg.moveToBottom(); 430 | if (cropSqr != null) { 431 | this.backImg.setCrop(cropSqr); 432 | } 433 | if (w != null) { 434 | this.setWidth(w); 435 | } 436 | if (h != null) { 437 | this.setHeight(h); 438 | } 439 | }; 440 | 441 | Card.prototype.tryMoveToAnimationLayer = function () { 442 | if (this.animationLayer == null || this.group.getLayer() === this.animationLayer) { 443 | return false; 444 | } 445 | 446 | var absPos = this.getAbsolutePosition(); 447 | this.group.moveTo(this.animationLayer); 448 | this.setAbsolutePosition(absPos); 449 | return true; 450 | }; 451 | 452 | Card.prototype.tryMoveToPileGroup = function () { 453 | if (this.pile == null || this.pile.getGroup() == null || this.group.getParent() == this.pile.getGroup()) { 454 | return false; 455 | } 456 | 457 | var absPos = this.getAbsolutePosition(); 458 | this.group.moveTo(this.pile.getGroup()); 459 | this.setAbsolutePosition(absPos); 460 | this.pile.resetCardZOrder(); 461 | return true; 462 | }; 463 | 464 | ////animations 465 | Card.prototype.areAnyAnimationsRunning = function () { 466 | return this.isPositionAnimationRunning() === true || this.isFlipAnimationRunning() === true; 467 | }; 468 | 469 | Card.prototype.stopAllAnimations = function () { 470 | if (this.isPositionAnimationRunning() === true) { 471 | this.stopPositionAnimation(true); 472 | } 473 | if (this.isFlipAnimationRunning() === true) { 474 | this.stopFlipAnimation(true); 475 | } 476 | }; 477 | 478 | //position animation 479 | Card.prototype.isPositionAnimationRunning = function () { 480 | return this.positionAnimationTimeout != null || (this.positionAnimator != null && this.positionAnimator.isRunning() === true); 481 | }; 482 | 483 | Card.prototype.preparePositionAnimationContext = function (x, y, animTime, callback) { 484 | //find absolute positions for ourselves and our parent 485 | var scale = this.group.getScaleX(); 486 | var absPos = this.group.getAbsolutePosition(); 487 | var layer = this.group.getLayer(); 488 | var ownerAbsPos, ownerLayer; 489 | if (this.pile != null && this.pile.getGroup() != null) { 490 | ownerAbsPos = this.pile.getGroup().getAbsolutePosition(); 491 | scale = this.pile.getGroup().getScaleX(); 492 | ownerLayer = this.pile.getGroup().getLayer(); 493 | } else { 494 | ownerAbsPos = { x: absPos.x, y: absPos.y }; 495 | ownerLayer = this.group.getLayer(); 496 | } 497 | 498 | //figure out our delta 499 | var from = fSpider.Utils.formatPointToLayer(absPos, this.animationLayer || layer); 500 | var to = fSpider.Utils.formatPointToLayer(ownerAbsPos, ownerLayer); 501 | to.y += y * scale; 502 | to.x += x * scale; 503 | var delta = { x: to.x - from.x, y: to.y - from.y }; 504 | 505 | //build context 506 | var context = {}; 507 | context.callback = callback; 508 | context.originalLayer = layer; 509 | context.animTime = animTime; 510 | context.intendedPos = { x: x, y: y }; 511 | context.intendedAbsPos = to; 512 | context.originalAbsPos = from; 513 | context.msStep = { x: delta.x / animTime, y: delta.y / animTime }; 514 | 515 | this.group.setListening(false); 516 | 517 | return context; 518 | }; 519 | 520 | Card.prototype.startPositionAnimation = function () { 521 | var layer = this.group.getLayer(); 522 | //if animation layer isn't current layer, move to animation layer 523 | if (this.tryMoveToAnimationLayer() === true) { 524 | this.group.moveToTop(); 525 | this.group.getLayer().draw(); 526 | if (layer !== this.group.getLayer()) { 527 | layer.draw(); 528 | } 529 | } else if (this.pile != null && this.pile.getGroup() != null && this.group.getLayer() != null) { 530 | this.pile.moveToTop(); 531 | } 532 | 533 | if (this.positionAnimator == null) { 534 | var self = this; 535 | this.positionAnimator = new Kinetic.Animation(function (frame) { 536 | self.stepPositionAnimation(frame); 537 | }, this.animationLayer || layer); 538 | } 539 | 540 | this.positionAnimator.start(); 541 | }; 542 | 543 | Card.prototype.stopPositionAnimation = function (moveToIntendedPos) { 544 | var context = this.positionAnimatorContext; 545 | 546 | if (this.positionAnimationTimeout != null) { 547 | //stop any existing position change delay 548 | clearTimeout(this.positionAnimationTimeout); 549 | this.positionAnimationTimeout = null; 550 | } 551 | 552 | if (this.positionAnimator != null && this.positionAnimator.isRunning() === true) { 553 | this.positionAnimator.stop(); 554 | } 555 | 556 | if (moveToIntendedPos === true) { 557 | this.group.setAbsolutePosition(context.intendedAbsPos); 558 | } 559 | 560 | var layer = this.group.getLayer(); 561 | //we need to wait for other animations in the group to stop before moving them all back to original layer 562 | //otherwise we get some graphical glitches with cards having the wrong z order because of 2 layers 563 | if (this.pile != null && this.pile.getGroup() !== this.group.getParent()) { 564 | var animating = this.pile.countCardsAnimating(); 565 | if (animating < 1) { 566 | this.pile.moveAllCardsToGroup(); 567 | this.pile.resetListening(); 568 | this.pile.resetDraggable(); 569 | this.group.getLayer().draw(); 570 | if (layer !== this.group.getLayer()) { 571 | layer.draw(); 572 | } 573 | } else { 574 | layer.draw(); 575 | } 576 | } 577 | 578 | //cleanup 579 | this.positionAnimator = null; 580 | this.positionAnimatorContext = null; 581 | 582 | if (context.callback != null) { 583 | context.callback(this); 584 | } 585 | }; 586 | 587 | Card.prototype.stepPositionAnimation = function (frame) { 588 | var context = this.positionAnimatorContext; 589 | if (frame.time >= context.animTime) { //done with animation 590 | this.stopPositionAnimation(true); 591 | } else { //animation delta 592 | var absPos = this.group.getAbsolutePosition(); 593 | var newAbsPos = { x: absPos.x + frame.timeDiff * context.msStep.x, y: absPos.y + frame.timeDiff * context.msStep.y }; 594 | this.group.setAbsolutePosition(newAbsPos); 595 | } 596 | }; 597 | 598 | //flip animation 599 | Card.prototype.isFlipAnimationRunning = function () { 600 | return this.flipAnimationTimeout != null || (this.flipAnimator != null && this.flipAnimator.isRunning() === true); 601 | }; 602 | 603 | Card.prototype.prepareFlipAnimationContext = function (faceUp, animTime, callback) { 604 | //build context 605 | var context = {}; 606 | context.callback = callback; 607 | context.originalLayer = this.group.getLayer(); 608 | context.animTime = animTime; 609 | context.originalScaleX = this.group.getScaleX(); 610 | context.intendedFaceUp = faceUp; 611 | context.halfwayTime = animTime / 2; 612 | context.halfwayPassed = false; 613 | context.msStep = context.originalScaleX / context.halfwayTime; 614 | 615 | return context; 616 | }; 617 | 618 | Card.prototype.startFlipAnimation = function () { 619 | var layer = this.group.getLayer(); 620 | 621 | //if animation layer isn't current layer, move to animation layer 622 | if (this.tryMoveToAnimationLayer() === true) { 623 | this.group.moveToTop(); 624 | // layer.draw(); 625 | // this.group.getLayer().draw(); 626 | } else if (this.pile != null && this.pile.getGroup() != null && this.group.getLayer() != null) { 627 | this.pile.moveToTop(); 628 | } 629 | 630 | if (this.flipAnimator == null) { 631 | var self = this; 632 | this.flipAnimator = new Kinetic.Animation(function (frame) { 633 | self.stepFlipAnimation(frame); 634 | }, this.animationLayer || layer); 635 | } 636 | 637 | this.flipAnimator.start(); 638 | }; 639 | 640 | Card.prototype.stopFlipAnimation = function (setIntendedFaceUp) { 641 | var context = this.flipAnimatorContext; 642 | 643 | if (this.flipAnimationTimeout != null) { 644 | //stop any existing flip change delay 645 | clearTimeout(this.flipAnimationTimeout); 646 | this.flipAnimationTimeout = null; 647 | } 648 | 649 | if (this.flipAnimator != null && this.flipAnimator.isRunning() === true) { 650 | this.flipAnimator.stop(); 651 | } 652 | 653 | if (setIntendedFaceUp === true) { 654 | this.faceUp = context.intendedFaceUp; 655 | this.group.setScaleX(context.originalScaleX); 656 | } 657 | this.border.setX(0); 658 | this.faceImg.setX(0); 659 | this.backImg.setX(0); 660 | this.refresh(); 661 | 662 | var layer = this.group.getLayer(); 663 | //we need to wait for other animations in the group to stop before moving them all back to original layer 664 | //otherwise we get some graphical glitches with cards having the wrong z order because of 2 layers 665 | if (this.pile != null && this.pile.getGroup() !== this.group.getParent()) { 666 | var animating = this.pile.countCardsAnimating(); 667 | if (animating < 1) { 668 | this.pile.moveAllCardsToGroup(); 669 | this.group.getLayer().draw(); 670 | if (layer !== this.group.getLayer()) { 671 | layer.draw(); 672 | } 673 | } 674 | } 675 | 676 | // //redraw original layer 677 | // if (context.originalLayer != null) { 678 | // context.originalLayer.draw(); 679 | // } 680 | 681 | //cleanup 682 | this.flipAnimator = null; 683 | this.flipAnimatorContext = null; 684 | 685 | if (context.callback != null) { 686 | context.callback(this); 687 | } 688 | }; 689 | 690 | Card.prototype.stepFlipAnimation = function (frame) { 691 | var context = this.flipAnimatorContext; 692 | if (frame.time >= context.animTime) { //done with animation 693 | this.refresh(); 694 | this.stopFlipAnimation(true); 695 | } else { 696 | var newScale = this.group.getScaleX(); 697 | if (frame.time < context.halfwayTime) { //first half (squeeze) 698 | newScale -= context.msStep * frame.timeDiff; 699 | if (newScale < 0) { 700 | newScale = 0; 701 | } 702 | this.border.setX(this.border.getWidth() / 2 * (context.originalScaleX - newScale)); 703 | this.faceImg.setX(this.faceImg.getWidth() / 2 * (context.originalScaleX - newScale)); 704 | this.backImg.setX(this.backImg.getWidth() / 2 * (context.originalScaleX - newScale)); 705 | } else { //second half (stretch) 706 | if (context.halfwayPassed !== true) { 707 | context.halfwayPassed = true; 708 | this.refresh(); 709 | } 710 | newScale += context.msStep * frame.timeDiff; 711 | if (newScale > context.originalScaleX) { 712 | newScale = context.originalScaleX; 713 | } 714 | this.border.setX(this.border.getWidth() / 2 - this.border.getWidth() / 2 * newScale); 715 | this.faceImg.setX(this.faceImg.getWidth() / 2 - this.faceImg.getWidth() / 2 * newScale); 716 | this.backImg.setX(this.backImg.getWidth() / 2 - this.backImg.getWidth() / 2 * newScale); 717 | } 718 | this.group.setScaleX(newScale); 719 | } 720 | }; 721 | 722 | //misc 723 | return Card; 724 | })(fSpider.Card || {}, window.Kinetic); 725 | 726 | fSpider.PlayingCard = (function (PlayingCard, Kinetic, undefined) { 727 | 'use strict'; 728 | 729 | var Card = fSpider.Card; 730 | var Utils = fSpider.Utils; 731 | 732 | PlayingCard = function (suit, type) { 733 | var self = this; 734 | 735 | this.suit = suit; 736 | this.type = type; 737 | 738 | this.group = new Kinetic.Group({ 739 | width: PlayingCard.CARD_DIM.w, 740 | height: PlayingCard.CARD_DIM.h 741 | }); 742 | this.border = new Kinetic.Rect({ 743 | visible: this.borderProps.visible, 744 | x: 0 - this.borderProps.padding, 745 | y: 0 - this.borderProps.padding, 746 | opacity: this.borderProps.opacity, 747 | fill: this.borderProps.fill, 748 | stroke: this.borderProps.stroke, 749 | strokeWidth: this.borderProps.strokeWidth, 750 | cornerRadius: this.borderProps.cornerRadius 751 | }); 752 | this.activeBorder = new Kinetic.Rect({ 753 | visible: false, 754 | x: 0 - this.activeBorderProps.padding, 755 | y: 0 - this.activeBorderProps.padding, 756 | opacity: this.activeBorderProps.opacity, 757 | fill: this.activeBorderProps.fill, 758 | stroke: this.activeBorderProps.stroke, 759 | strokeWidth: this.activeBorderProps.strokeWidth, 760 | cornerRadius: this.activeBorderProps.cornerRadius 761 | }); 762 | this.hoverBorder = new Kinetic.Rect({ 763 | visible: false, 764 | x: 0 - this.hoverBorderProps.padding, 765 | y: 0 - this.hoverBorderProps.padding, 766 | opacity: this.hoverBorderProps.opacity, 767 | fill: this.hoverBorderProps.fill, 768 | stroke: this.hoverBorderProps.stroke, 769 | strokeWidth: this.hoverBorderProps.strokeWidth, 770 | cornerRadius: this.hoverBorderProps.cornerRadius 771 | }); 772 | 773 | this.group.add(this.border); 774 | this.group.add(this.activeBorder); 775 | this.group.add(this.hoverBorder); 776 | }; 777 | 778 | Utils.extendObj(PlayingCard, Card); 779 | 780 | //fields 781 | PlayingCard.prototype.suit = 0; 782 | PlayingCard.prototype.type = 0; 783 | 784 | //getters setters 785 | PlayingCard.prototype.getSuit = function () { 786 | return this.suit; 787 | }; 788 | PlayingCard.prototype.setSuit = function (suit) { 789 | this.suit = suit; 790 | }; 791 | 792 | PlayingCard.prototype.getType = function () { 793 | return this.type; 794 | }; 795 | PlayingCard.prototype.setType = function (type) { 796 | this.type = type; 797 | }; 798 | 799 | //public functions 800 | 801 | //static fields 802 | PlayingCard.CARD_DIM = { w: 90, h: 120 }; 803 | PlayingCard.CARD_TYPES = { 804 | ace: 0, 805 | two: 1, 806 | three: 2, 807 | four: 3, 808 | five: 4, 809 | six: 5, 810 | seven: 6, 811 | eight: 7, 812 | nine: 8, 813 | ten: 9, 814 | jack: 10, 815 | queen: 11, 816 | king: 12 817 | }; 818 | PlayingCard.CARD_SUITS = { 819 | clubs: 0, 820 | hearts: 1, 821 | spades: 2, 822 | diamonds: 3 823 | }; 824 | 825 | return PlayingCard; 826 | })(fSpider.PlayingCard || {}, window.Kinetic); -------------------------------------------------------------------------------- /content/font_awesome/css/font-awesome.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 3.2.1 3 | * the iconic font designed for Bootstrap 4 | * ------------------------------------------------------------------------------ 5 | * The full suite of pictographic icons, examples, and documentation can be 6 | * found at http://fontawesome.io. Stay up to date on Twitter at 7 | * http://twitter.com/fontawesome. 8 | * 9 | * License 10 | * ------------------------------------------------------------------------------ 11 | * - The Font Awesome font is licensed under SIL OFL 1.1 - 12 | * http://scripts.sil.org/OFL 13 | * - Font Awesome CSS, LESS, and SASS files are licensed under MIT License - 14 | * http://opensource.org/licenses/mit-license.html 15 | * - Font Awesome documentation licensed under CC BY 3.0 - 16 | * http://creativecommons.org/licenses/by/3.0/ 17 | * - Attribution is no longer required in Font Awesome 3.0, but much appreciated: 18 | * "Font Awesome by Dave Gandy - http://fontawesome.io" 19 | * 20 | * Author - Dave Gandy 21 | * ------------------------------------------------------------------------------ 22 | * Email: dave@fontawesome.io 23 | * Twitter: http://twitter.com/davegandy 24 | * Work: Lead Product Designer @ Kyruus - http://kyruus.com 25 | */ 26 | /* FONT PATH 27 | * -------------------------- */ 28 | @font-face { 29 | font-family: 'FontAwesome'; 30 | src: url('../font/fontawesome-webfont.eot?v=3.2.1'); 31 | src: url('../font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'), url('../font/fontawesome-webfont.woff?v=3.2.1') format('woff'), url('../font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'), url('../font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg'); 32 | font-weight: normal; 33 | font-style: normal; 34 | } 35 | /* FONT AWESOME CORE 36 | * -------------------------- */ 37 | [class^="icon-"], 38 | [class*=" icon-"] { 39 | font-family: FontAwesome; 40 | font-weight: normal; 41 | font-style: normal; 42 | text-decoration: inherit; 43 | -webkit-font-smoothing: antialiased; 44 | *margin-right: .3em; 45 | } 46 | [class^="icon-"]:before, 47 | [class*=" icon-"]:before { 48 | text-decoration: inherit; 49 | display: inline-block; 50 | speak: none; 51 | } 52 | /* makes the font 33% larger relative to the icon container */ 53 | .icon-large:before { 54 | vertical-align: -10%; 55 | font-size: 1.3333333333333333em; 56 | } 57 | /* makes sure icons active on rollover in links */ 58 | a [class^="icon-"], 59 | a [class*=" icon-"] { 60 | display: inline; 61 | } 62 | /* increased font size for icon-large */ 63 | [class^="icon-"].icon-fixed-width, 64 | [class*=" icon-"].icon-fixed-width { 65 | display: inline-block; 66 | width: 1.1428571428571428em; 67 | text-align: right; 68 | padding-right: 0.2857142857142857em; 69 | } 70 | [class^="icon-"].icon-fixed-width.icon-large, 71 | [class*=" icon-"].icon-fixed-width.icon-large { 72 | width: 1.4285714285714286em; 73 | } 74 | .icons-ul { 75 | margin-left: 2.142857142857143em; 76 | list-style-type: none; 77 | } 78 | .icons-ul > li { 79 | position: relative; 80 | } 81 | .icons-ul .icon-li { 82 | position: absolute; 83 | left: -2.142857142857143em; 84 | width: 2.142857142857143em; 85 | text-align: center; 86 | line-height: inherit; 87 | } 88 | [class^="icon-"].hide, 89 | [class*=" icon-"].hide { 90 | display: none; 91 | } 92 | .icon-muted { 93 | color: #eeeeee; 94 | } 95 | .icon-light { 96 | color: #ffffff; 97 | } 98 | .icon-dark { 99 | color: #333333; 100 | } 101 | .icon-border { 102 | border: solid 1px #eeeeee; 103 | padding: .2em .25em .15em; 104 | -webkit-border-radius: 3px; 105 | -moz-border-radius: 3px; 106 | border-radius: 3px; 107 | } 108 | .icon-2x { 109 | font-size: 2em; 110 | } 111 | .icon-2x.icon-border { 112 | border-width: 2px; 113 | -webkit-border-radius: 4px; 114 | -moz-border-radius: 4px; 115 | border-radius: 4px; 116 | } 117 | .icon-3x { 118 | font-size: 3em; 119 | } 120 | .icon-3x.icon-border { 121 | border-width: 3px; 122 | -webkit-border-radius: 5px; 123 | -moz-border-radius: 5px; 124 | border-radius: 5px; 125 | } 126 | .icon-4x { 127 | font-size: 4em; 128 | } 129 | .icon-4x.icon-border { 130 | border-width: 4px; 131 | -webkit-border-radius: 6px; 132 | -moz-border-radius: 6px; 133 | border-radius: 6px; 134 | } 135 | .icon-5x { 136 | font-size: 5em; 137 | } 138 | .icon-5x.icon-border { 139 | border-width: 5px; 140 | -webkit-border-radius: 7px; 141 | -moz-border-radius: 7px; 142 | border-radius: 7px; 143 | } 144 | .pull-right { 145 | float: right; 146 | } 147 | .pull-left { 148 | float: left; 149 | } 150 | [class^="icon-"].pull-left, 151 | [class*=" icon-"].pull-left { 152 | margin-right: .3em; 153 | } 154 | [class^="icon-"].pull-right, 155 | [class*=" icon-"].pull-right { 156 | margin-left: .3em; 157 | } 158 | /* BOOTSTRAP SPECIFIC CLASSES 159 | * -------------------------- */ 160 | /* Bootstrap 2.0 sprites.less reset */ 161 | [class^="icon-"], 162 | [class*=" icon-"] { 163 | display: inline; 164 | width: auto; 165 | height: auto; 166 | line-height: normal; 167 | vertical-align: baseline; 168 | background-image: none; 169 | background-position: 0% 0%; 170 | background-repeat: repeat; 171 | margin-top: 0; 172 | } 173 | /* more sprites.less reset */ 174 | .icon-white, 175 | .nav-pills > .active > a > [class^="icon-"], 176 | .nav-pills > .active > a > [class*=" icon-"], 177 | .nav-list > .active > a > [class^="icon-"], 178 | .nav-list > .active > a > [class*=" icon-"], 179 | .navbar-inverse .nav > .active > a > [class^="icon-"], 180 | .navbar-inverse .nav > .active > a > [class*=" icon-"], 181 | .dropdown-menu > li > a:hover > [class^="icon-"], 182 | .dropdown-menu > li > a:hover > [class*=" icon-"], 183 | .dropdown-menu > .active > a > [class^="icon-"], 184 | .dropdown-menu > .active > a > [class*=" icon-"], 185 | .dropdown-submenu:hover > a > [class^="icon-"], 186 | .dropdown-submenu:hover > a > [class*=" icon-"] { 187 | background-image: none; 188 | } 189 | /* keeps Bootstrap styles with and without icons the same */ 190 | .btn [class^="icon-"].icon-large, 191 | .nav [class^="icon-"].icon-large, 192 | .btn [class*=" icon-"].icon-large, 193 | .nav [class*=" icon-"].icon-large { 194 | line-height: .9em; 195 | } 196 | .btn [class^="icon-"].icon-spin, 197 | .nav [class^="icon-"].icon-spin, 198 | .btn [class*=" icon-"].icon-spin, 199 | .nav [class*=" icon-"].icon-spin { 200 | display: inline-block; 201 | } 202 | .nav-tabs [class^="icon-"], 203 | .nav-pills [class^="icon-"], 204 | .nav-tabs [class*=" icon-"], 205 | .nav-pills [class*=" icon-"], 206 | .nav-tabs [class^="icon-"].icon-large, 207 | .nav-pills [class^="icon-"].icon-large, 208 | .nav-tabs [class*=" icon-"].icon-large, 209 | .nav-pills [class*=" icon-"].icon-large { 210 | line-height: .9em; 211 | } 212 | .btn [class^="icon-"].pull-left.icon-2x, 213 | .btn [class*=" icon-"].pull-left.icon-2x, 214 | .btn [class^="icon-"].pull-right.icon-2x, 215 | .btn [class*=" icon-"].pull-right.icon-2x { 216 | margin-top: .18em; 217 | } 218 | .btn [class^="icon-"].icon-spin.icon-large, 219 | .btn [class*=" icon-"].icon-spin.icon-large { 220 | line-height: .8em; 221 | } 222 | .btn.btn-small [class^="icon-"].pull-left.icon-2x, 223 | .btn.btn-small [class*=" icon-"].pull-left.icon-2x, 224 | .btn.btn-small [class^="icon-"].pull-right.icon-2x, 225 | .btn.btn-small [class*=" icon-"].pull-right.icon-2x { 226 | margin-top: .25em; 227 | } 228 | .btn.btn-large [class^="icon-"], 229 | .btn.btn-large [class*=" icon-"] { 230 | margin-top: 0; 231 | } 232 | .btn.btn-large [class^="icon-"].pull-left.icon-2x, 233 | .btn.btn-large [class*=" icon-"].pull-left.icon-2x, 234 | .btn.btn-large [class^="icon-"].pull-right.icon-2x, 235 | .btn.btn-large [class*=" icon-"].pull-right.icon-2x { 236 | margin-top: .05em; 237 | } 238 | .btn.btn-large [class^="icon-"].pull-left.icon-2x, 239 | .btn.btn-large [class*=" icon-"].pull-left.icon-2x { 240 | margin-right: .2em; 241 | } 242 | .btn.btn-large [class^="icon-"].pull-right.icon-2x, 243 | .btn.btn-large [class*=" icon-"].pull-right.icon-2x { 244 | margin-left: .2em; 245 | } 246 | /* Fixes alignment in nav lists */ 247 | .nav-list [class^="icon-"], 248 | .nav-list [class*=" icon-"] { 249 | line-height: inherit; 250 | } 251 | /* EXTRAS 252 | * -------------------------- */ 253 | /* Stacked and layered icon */ 254 | .icon-stack { 255 | position: relative; 256 | display: inline-block; 257 | width: 2em; 258 | height: 2em; 259 | line-height: 2em; 260 | vertical-align: -35%; 261 | } 262 | .icon-stack [class^="icon-"], 263 | .icon-stack [class*=" icon-"] { 264 | display: block; 265 | text-align: center; 266 | position: absolute; 267 | width: 100%; 268 | height: 100%; 269 | font-size: 1em; 270 | line-height: inherit; 271 | *line-height: 2em; 272 | } 273 | .icon-stack .icon-stack-base { 274 | font-size: 2em; 275 | *line-height: 1em; 276 | } 277 | /* Animated rotating icon */ 278 | .icon-spin { 279 | display: inline-block; 280 | -moz-animation: spin 2s infinite linear; 281 | -o-animation: spin 2s infinite linear; 282 | -webkit-animation: spin 2s infinite linear; 283 | animation: spin 2s infinite linear; 284 | } 285 | /* Prevent stack and spinners from being taken inline when inside a link */ 286 | a .icon-stack, 287 | a .icon-spin { 288 | display: inline-block; 289 | text-decoration: none; 290 | } 291 | @-moz-keyframes spin { 292 | 0% { 293 | -moz-transform: rotate(0deg); 294 | } 295 | 100% { 296 | -moz-transform: rotate(359deg); 297 | } 298 | } 299 | @-webkit-keyframes spin { 300 | 0% { 301 | -webkit-transform: rotate(0deg); 302 | } 303 | 100% { 304 | -webkit-transform: rotate(359deg); 305 | } 306 | } 307 | @-o-keyframes spin { 308 | 0% { 309 | -o-transform: rotate(0deg); 310 | } 311 | 100% { 312 | -o-transform: rotate(359deg); 313 | } 314 | } 315 | @-ms-keyframes spin { 316 | 0% { 317 | -ms-transform: rotate(0deg); 318 | } 319 | 100% { 320 | -ms-transform: rotate(359deg); 321 | } 322 | } 323 | @keyframes spin { 324 | 0% { 325 | transform: rotate(0deg); 326 | } 327 | 100% { 328 | transform: rotate(359deg); 329 | } 330 | } 331 | /* Icon rotations and mirroring */ 332 | .icon-rotate-90:before { 333 | -webkit-transform: rotate(90deg); 334 | -moz-transform: rotate(90deg); 335 | -ms-transform: rotate(90deg); 336 | -o-transform: rotate(90deg); 337 | transform: rotate(90deg); 338 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); 339 | } 340 | .icon-rotate-180:before { 341 | -webkit-transform: rotate(180deg); 342 | -moz-transform: rotate(180deg); 343 | -ms-transform: rotate(180deg); 344 | -o-transform: rotate(180deg); 345 | transform: rotate(180deg); 346 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); 347 | } 348 | .icon-rotate-270:before { 349 | -webkit-transform: rotate(270deg); 350 | -moz-transform: rotate(270deg); 351 | -ms-transform: rotate(270deg); 352 | -o-transform: rotate(270deg); 353 | transform: rotate(270deg); 354 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); 355 | } 356 | .icon-flip-horizontal:before { 357 | -webkit-transform: scale(-1, 1); 358 | -moz-transform: scale(-1, 1); 359 | -ms-transform: scale(-1, 1); 360 | -o-transform: scale(-1, 1); 361 | transform: scale(-1, 1); 362 | } 363 | .icon-flip-vertical:before { 364 | -webkit-transform: scale(1, -1); 365 | -moz-transform: scale(1, -1); 366 | -ms-transform: scale(1, -1); 367 | -o-transform: scale(1, -1); 368 | transform: scale(1, -1); 369 | } 370 | /* ensure rotation occurs inside anchor tags */ 371 | a .icon-rotate-90:before, 372 | a .icon-rotate-180:before, 373 | a .icon-rotate-270:before, 374 | a .icon-flip-horizontal:before, 375 | a .icon-flip-vertical:before { 376 | display: inline-block; 377 | } 378 | /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen 379 | readers do not read off random characters that represent icons */ 380 | .icon-glass:before { 381 | content: "\f000"; 382 | } 383 | .icon-music:before { 384 | content: "\f001"; 385 | } 386 | .icon-search:before { 387 | content: "\f002"; 388 | } 389 | .icon-envelope-alt:before { 390 | content: "\f003"; 391 | } 392 | .icon-heart:before { 393 | content: "\f004"; 394 | } 395 | .icon-star:before { 396 | content: "\f005"; 397 | } 398 | .icon-star-empty:before { 399 | content: "\f006"; 400 | } 401 | .icon-user:before { 402 | content: "\f007"; 403 | } 404 | .icon-film:before { 405 | content: "\f008"; 406 | } 407 | .icon-th-large:before { 408 | content: "\f009"; 409 | } 410 | .icon-th:before { 411 | content: "\f00a"; 412 | } 413 | .icon-th-list:before { 414 | content: "\f00b"; 415 | } 416 | .icon-ok:before { 417 | content: "\f00c"; 418 | } 419 | .icon-remove:before { 420 | content: "\f00d"; 421 | } 422 | .icon-zoom-in:before { 423 | content: "\f00e"; 424 | } 425 | .icon-zoom-out:before { 426 | content: "\f010"; 427 | } 428 | .icon-power-off:before, 429 | .icon-off:before { 430 | content: "\f011"; 431 | } 432 | .icon-signal:before { 433 | content: "\f012"; 434 | } 435 | .icon-gear:before, 436 | .icon-cog:before { 437 | content: "\f013"; 438 | } 439 | .icon-trash:before { 440 | content: "\f014"; 441 | } 442 | .icon-home:before { 443 | content: "\f015"; 444 | } 445 | .icon-file-alt:before { 446 | content: "\f016"; 447 | } 448 | .icon-time:before { 449 | content: "\f017"; 450 | } 451 | .icon-road:before { 452 | content: "\f018"; 453 | } 454 | .icon-download-alt:before { 455 | content: "\f019"; 456 | } 457 | .icon-download:before { 458 | content: "\f01a"; 459 | } 460 | .icon-upload:before { 461 | content: "\f01b"; 462 | } 463 | .icon-inbox:before { 464 | content: "\f01c"; 465 | } 466 | .icon-play-circle:before { 467 | content: "\f01d"; 468 | } 469 | .icon-rotate-right:before, 470 | .icon-repeat:before { 471 | content: "\f01e"; 472 | } 473 | .icon-refresh:before { 474 | content: "\f021"; 475 | } 476 | .icon-list-alt:before { 477 | content: "\f022"; 478 | } 479 | .icon-lock:before { 480 | content: "\f023"; 481 | } 482 | .icon-flag:before { 483 | content: "\f024"; 484 | } 485 | .icon-headphones:before { 486 | content: "\f025"; 487 | } 488 | .icon-volume-off:before { 489 | content: "\f026"; 490 | } 491 | .icon-volume-down:before { 492 | content: "\f027"; 493 | } 494 | .icon-volume-up:before { 495 | content: "\f028"; 496 | } 497 | .icon-qrcode:before { 498 | content: "\f029"; 499 | } 500 | .icon-barcode:before { 501 | content: "\f02a"; 502 | } 503 | .icon-tag:before { 504 | content: "\f02b"; 505 | } 506 | .icon-tags:before { 507 | content: "\f02c"; 508 | } 509 | .icon-book:before { 510 | content: "\f02d"; 511 | } 512 | .icon-bookmark:before { 513 | content: "\f02e"; 514 | } 515 | .icon-print:before { 516 | content: "\f02f"; 517 | } 518 | .icon-camera:before { 519 | content: "\f030"; 520 | } 521 | .icon-font:before { 522 | content: "\f031"; 523 | } 524 | .icon-bold:before { 525 | content: "\f032"; 526 | } 527 | .icon-italic:before { 528 | content: "\f033"; 529 | } 530 | .icon-text-height:before { 531 | content: "\f034"; 532 | } 533 | .icon-text-width:before { 534 | content: "\f035"; 535 | } 536 | .icon-align-left:before { 537 | content: "\f036"; 538 | } 539 | .icon-align-center:before { 540 | content: "\f037"; 541 | } 542 | .icon-align-right:before { 543 | content: "\f038"; 544 | } 545 | .icon-align-justify:before { 546 | content: "\f039"; 547 | } 548 | .icon-list:before { 549 | content: "\f03a"; 550 | } 551 | .icon-indent-left:before { 552 | content: "\f03b"; 553 | } 554 | .icon-indent-right:before { 555 | content: "\f03c"; 556 | } 557 | .icon-facetime-video:before { 558 | content: "\f03d"; 559 | } 560 | .icon-picture:before { 561 | content: "\f03e"; 562 | } 563 | .icon-pencil:before { 564 | content: "\f040"; 565 | } 566 | .icon-map-marker:before { 567 | content: "\f041"; 568 | } 569 | .icon-adjust:before { 570 | content: "\f042"; 571 | } 572 | .icon-tint:before { 573 | content: "\f043"; 574 | } 575 | .icon-edit:before { 576 | content: "\f044"; 577 | } 578 | .icon-share:before { 579 | content: "\f045"; 580 | } 581 | .icon-check:before { 582 | content: "\f046"; 583 | } 584 | .icon-move:before { 585 | content: "\f047"; 586 | } 587 | .icon-step-backward:before { 588 | content: "\f048"; 589 | } 590 | .icon-fast-backward:before { 591 | content: "\f049"; 592 | } 593 | .icon-backward:before { 594 | content: "\f04a"; 595 | } 596 | .icon-play:before { 597 | content: "\f04b"; 598 | } 599 | .icon-pause:before { 600 | content: "\f04c"; 601 | } 602 | .icon-stop:before { 603 | content: "\f04d"; 604 | } 605 | .icon-forward:before { 606 | content: "\f04e"; 607 | } 608 | .icon-fast-forward:before { 609 | content: "\f050"; 610 | } 611 | .icon-step-forward:before { 612 | content: "\f051"; 613 | } 614 | .icon-eject:before { 615 | content: "\f052"; 616 | } 617 | .icon-chevron-left:before { 618 | content: "\f053"; 619 | } 620 | .icon-chevron-right:before { 621 | content: "\f054"; 622 | } 623 | .icon-plus-sign:before { 624 | content: "\f055"; 625 | } 626 | .icon-minus-sign:before { 627 | content: "\f056"; 628 | } 629 | .icon-remove-sign:before { 630 | content: "\f057"; 631 | } 632 | .icon-ok-sign:before { 633 | content: "\f058"; 634 | } 635 | .icon-question-sign:before { 636 | content: "\f059"; 637 | } 638 | .icon-info-sign:before { 639 | content: "\f05a"; 640 | } 641 | .icon-screenshot:before { 642 | content: "\f05b"; 643 | } 644 | .icon-remove-circle:before { 645 | content: "\f05c"; 646 | } 647 | .icon-ok-circle:before { 648 | content: "\f05d"; 649 | } 650 | .icon-ban-circle:before { 651 | content: "\f05e"; 652 | } 653 | .icon-arrow-left:before { 654 | content: "\f060"; 655 | } 656 | .icon-arrow-right:before { 657 | content: "\f061"; 658 | } 659 | .icon-arrow-up:before { 660 | content: "\f062"; 661 | } 662 | .icon-arrow-down:before { 663 | content: "\f063"; 664 | } 665 | .icon-mail-forward:before, 666 | .icon-share-alt:before { 667 | content: "\f064"; 668 | } 669 | .icon-resize-full:before { 670 | content: "\f065"; 671 | } 672 | .icon-resize-small:before { 673 | content: "\f066"; 674 | } 675 | .icon-plus:before { 676 | content: "\f067"; 677 | } 678 | .icon-minus:before { 679 | content: "\f068"; 680 | } 681 | .icon-asterisk:before { 682 | content: "\f069"; 683 | } 684 | .icon-exclamation-sign:before { 685 | content: "\f06a"; 686 | } 687 | .icon-gift:before { 688 | content: "\f06b"; 689 | } 690 | .icon-leaf:before { 691 | content: "\f06c"; 692 | } 693 | .icon-fire:before { 694 | content: "\f06d"; 695 | } 696 | .icon-eye-open:before { 697 | content: "\f06e"; 698 | } 699 | .icon-eye-close:before { 700 | content: "\f070"; 701 | } 702 | .icon-warning-sign:before { 703 | content: "\f071"; 704 | } 705 | .icon-plane:before { 706 | content: "\f072"; 707 | } 708 | .icon-calendar:before { 709 | content: "\f073"; 710 | } 711 | .icon-random:before { 712 | content: "\f074"; 713 | } 714 | .icon-comment:before { 715 | content: "\f075"; 716 | } 717 | .icon-magnet:before { 718 | content: "\f076"; 719 | } 720 | .icon-chevron-up:before { 721 | content: "\f077"; 722 | } 723 | .icon-chevron-down:before { 724 | content: "\f078"; 725 | } 726 | .icon-retweet:before { 727 | content: "\f079"; 728 | } 729 | .icon-shopping-cart:before { 730 | content: "\f07a"; 731 | } 732 | .icon-folder-close:before { 733 | content: "\f07b"; 734 | } 735 | .icon-folder-open:before { 736 | content: "\f07c"; 737 | } 738 | .icon-resize-vertical:before { 739 | content: "\f07d"; 740 | } 741 | .icon-resize-horizontal:before { 742 | content: "\f07e"; 743 | } 744 | .icon-bar-chart:before { 745 | content: "\f080"; 746 | } 747 | .icon-twitter-sign:before { 748 | content: "\f081"; 749 | } 750 | .icon-facebook-sign:before { 751 | content: "\f082"; 752 | } 753 | .icon-camera-retro:before { 754 | content: "\f083"; 755 | } 756 | .icon-key:before { 757 | content: "\f084"; 758 | } 759 | .icon-gears:before, 760 | .icon-cogs:before { 761 | content: "\f085"; 762 | } 763 | .icon-comments:before { 764 | content: "\f086"; 765 | } 766 | .icon-thumbs-up-alt:before { 767 | content: "\f087"; 768 | } 769 | .icon-thumbs-down-alt:before { 770 | content: "\f088"; 771 | } 772 | .icon-star-half:before { 773 | content: "\f089"; 774 | } 775 | .icon-heart-empty:before { 776 | content: "\f08a"; 777 | } 778 | .icon-signout:before { 779 | content: "\f08b"; 780 | } 781 | .icon-linkedin-sign:before { 782 | content: "\f08c"; 783 | } 784 | .icon-pushpin:before { 785 | content: "\f08d"; 786 | } 787 | .icon-external-link:before { 788 | content: "\f08e"; 789 | } 790 | .icon-signin:before { 791 | content: "\f090"; 792 | } 793 | .icon-trophy:before { 794 | content: "\f091"; 795 | } 796 | .icon-github-sign:before { 797 | content: "\f092"; 798 | } 799 | .icon-upload-alt:before { 800 | content: "\f093"; 801 | } 802 | .icon-lemon:before { 803 | content: "\f094"; 804 | } 805 | .icon-phone:before { 806 | content: "\f095"; 807 | } 808 | .icon-unchecked:before, 809 | .icon-check-empty:before { 810 | content: "\f096"; 811 | } 812 | .icon-bookmark-empty:before { 813 | content: "\f097"; 814 | } 815 | .icon-phone-sign:before { 816 | content: "\f098"; 817 | } 818 | .icon-twitter:before { 819 | content: "\f099"; 820 | } 821 | .icon-facebook:before { 822 | content: "\f09a"; 823 | } 824 | .icon-github:before { 825 | content: "\f09b"; 826 | } 827 | .icon-unlock:before { 828 | content: "\f09c"; 829 | } 830 | .icon-credit-card:before { 831 | content: "\f09d"; 832 | } 833 | .icon-rss:before { 834 | content: "\f09e"; 835 | } 836 | .icon-hdd:before { 837 | content: "\f0a0"; 838 | } 839 | .icon-bullhorn:before { 840 | content: "\f0a1"; 841 | } 842 | .icon-bell:before { 843 | content: "\f0a2"; 844 | } 845 | .icon-certificate:before { 846 | content: "\f0a3"; 847 | } 848 | .icon-hand-right:before { 849 | content: "\f0a4"; 850 | } 851 | .icon-hand-left:before { 852 | content: "\f0a5"; 853 | } 854 | .icon-hand-up:before { 855 | content: "\f0a6"; 856 | } 857 | .icon-hand-down:before { 858 | content: "\f0a7"; 859 | } 860 | .icon-circle-arrow-left:before { 861 | content: "\f0a8"; 862 | } 863 | .icon-circle-arrow-right:before { 864 | content: "\f0a9"; 865 | } 866 | .icon-circle-arrow-up:before { 867 | content: "\f0aa"; 868 | } 869 | .icon-circle-arrow-down:before { 870 | content: "\f0ab"; 871 | } 872 | .icon-globe:before { 873 | content: "\f0ac"; 874 | } 875 | .icon-wrench:before { 876 | content: "\f0ad"; 877 | } 878 | .icon-tasks:before { 879 | content: "\f0ae"; 880 | } 881 | .icon-filter:before { 882 | content: "\f0b0"; 883 | } 884 | .icon-briefcase:before { 885 | content: "\f0b1"; 886 | } 887 | .icon-fullscreen:before { 888 | content: "\f0b2"; 889 | } 890 | .icon-group:before { 891 | content: "\f0c0"; 892 | } 893 | .icon-link:before { 894 | content: "\f0c1"; 895 | } 896 | .icon-cloud:before { 897 | content: "\f0c2"; 898 | } 899 | .icon-beaker:before { 900 | content: "\f0c3"; 901 | } 902 | .icon-cut:before { 903 | content: "\f0c4"; 904 | } 905 | .icon-copy:before { 906 | content: "\f0c5"; 907 | } 908 | .icon-paperclip:before, 909 | .icon-paper-clip:before { 910 | content: "\f0c6"; 911 | } 912 | .icon-save:before { 913 | content: "\f0c7"; 914 | } 915 | .icon-sign-blank:before { 916 | content: "\f0c8"; 917 | } 918 | .icon-reorder:before { 919 | content: "\f0c9"; 920 | } 921 | .icon-list-ul:before { 922 | content: "\f0ca"; 923 | } 924 | .icon-list-ol:before { 925 | content: "\f0cb"; 926 | } 927 | .icon-strikethrough:before { 928 | content: "\f0cc"; 929 | } 930 | .icon-underline:before { 931 | content: "\f0cd"; 932 | } 933 | .icon-table:before { 934 | content: "\f0ce"; 935 | } 936 | .icon-magic:before { 937 | content: "\f0d0"; 938 | } 939 | .icon-truck:before { 940 | content: "\f0d1"; 941 | } 942 | .icon-pinterest:before { 943 | content: "\f0d2"; 944 | } 945 | .icon-pinterest-sign:before { 946 | content: "\f0d3"; 947 | } 948 | .icon-google-plus-sign:before { 949 | content: "\f0d4"; 950 | } 951 | .icon-google-plus:before { 952 | content: "\f0d5"; 953 | } 954 | .icon-money:before { 955 | content: "\f0d6"; 956 | } 957 | .icon-caret-down:before { 958 | content: "\f0d7"; 959 | } 960 | .icon-caret-up:before { 961 | content: "\f0d8"; 962 | } 963 | .icon-caret-left:before { 964 | content: "\f0d9"; 965 | } 966 | .icon-caret-right:before { 967 | content: "\f0da"; 968 | } 969 | .icon-columns:before { 970 | content: "\f0db"; 971 | } 972 | .icon-sort:before { 973 | content: "\f0dc"; 974 | } 975 | .icon-sort-down:before { 976 | content: "\f0dd"; 977 | } 978 | .icon-sort-up:before { 979 | content: "\f0de"; 980 | } 981 | .icon-envelope:before { 982 | content: "\f0e0"; 983 | } 984 | .icon-linkedin:before { 985 | content: "\f0e1"; 986 | } 987 | .icon-rotate-left:before, 988 | .icon-undo:before { 989 | content: "\f0e2"; 990 | } 991 | .icon-legal:before { 992 | content: "\f0e3"; 993 | } 994 | .icon-dashboard:before { 995 | content: "\f0e4"; 996 | } 997 | .icon-comment-alt:before { 998 | content: "\f0e5"; 999 | } 1000 | .icon-comments-alt:before { 1001 | content: "\f0e6"; 1002 | } 1003 | .icon-bolt:before { 1004 | content: "\f0e7"; 1005 | } 1006 | .icon-sitemap:before { 1007 | content: "\f0e8"; 1008 | } 1009 | .icon-umbrella:before { 1010 | content: "\f0e9"; 1011 | } 1012 | .icon-paste:before { 1013 | content: "\f0ea"; 1014 | } 1015 | .icon-lightbulb:before { 1016 | content: "\f0eb"; 1017 | } 1018 | .icon-exchange:before { 1019 | content: "\f0ec"; 1020 | } 1021 | .icon-cloud-download:before { 1022 | content: "\f0ed"; 1023 | } 1024 | .icon-cloud-upload:before { 1025 | content: "\f0ee"; 1026 | } 1027 | .icon-user-md:before { 1028 | content: "\f0f0"; 1029 | } 1030 | .icon-stethoscope:before { 1031 | content: "\f0f1"; 1032 | } 1033 | .icon-suitcase:before { 1034 | content: "\f0f2"; 1035 | } 1036 | .icon-bell-alt:before { 1037 | content: "\f0f3"; 1038 | } 1039 | .icon-coffee:before { 1040 | content: "\f0f4"; 1041 | } 1042 | .icon-food:before { 1043 | content: "\f0f5"; 1044 | } 1045 | .icon-file-text-alt:before { 1046 | content: "\f0f6"; 1047 | } 1048 | .icon-building:before { 1049 | content: "\f0f7"; 1050 | } 1051 | .icon-hospital:before { 1052 | content: "\f0f8"; 1053 | } 1054 | .icon-ambulance:before { 1055 | content: "\f0f9"; 1056 | } 1057 | .icon-medkit:before { 1058 | content: "\f0fa"; 1059 | } 1060 | .icon-fighter-jet:before { 1061 | content: "\f0fb"; 1062 | } 1063 | .icon-beer:before { 1064 | content: "\f0fc"; 1065 | } 1066 | .icon-h-sign:before { 1067 | content: "\f0fd"; 1068 | } 1069 | .icon-plus-sign-alt:before { 1070 | content: "\f0fe"; 1071 | } 1072 | .icon-double-angle-left:before { 1073 | content: "\f100"; 1074 | } 1075 | .icon-double-angle-right:before { 1076 | content: "\f101"; 1077 | } 1078 | .icon-double-angle-up:before { 1079 | content: "\f102"; 1080 | } 1081 | .icon-double-angle-down:before { 1082 | content: "\f103"; 1083 | } 1084 | .icon-angle-left:before { 1085 | content: "\f104"; 1086 | } 1087 | .icon-angle-right:before { 1088 | content: "\f105"; 1089 | } 1090 | .icon-angle-up:before { 1091 | content: "\f106"; 1092 | } 1093 | .icon-angle-down:before { 1094 | content: "\f107"; 1095 | } 1096 | .icon-desktop:before { 1097 | content: "\f108"; 1098 | } 1099 | .icon-laptop:before { 1100 | content: "\f109"; 1101 | } 1102 | .icon-tablet:before { 1103 | content: "\f10a"; 1104 | } 1105 | .icon-mobile-phone:before { 1106 | content: "\f10b"; 1107 | } 1108 | .icon-circle-blank:before { 1109 | content: "\f10c"; 1110 | } 1111 | .icon-quote-left:before { 1112 | content: "\f10d"; 1113 | } 1114 | .icon-quote-right:before { 1115 | content: "\f10e"; 1116 | } 1117 | .icon-spinner:before { 1118 | content: "\f110"; 1119 | } 1120 | .icon-circle:before { 1121 | content: "\f111"; 1122 | } 1123 | .icon-mail-reply:before, 1124 | .icon-reply:before { 1125 | content: "\f112"; 1126 | } 1127 | .icon-github-alt:before { 1128 | content: "\f113"; 1129 | } 1130 | .icon-folder-close-alt:before { 1131 | content: "\f114"; 1132 | } 1133 | .icon-folder-open-alt:before { 1134 | content: "\f115"; 1135 | } 1136 | .icon-expand-alt:before { 1137 | content: "\f116"; 1138 | } 1139 | .icon-collapse-alt:before { 1140 | content: "\f117"; 1141 | } 1142 | .icon-smile:before { 1143 | content: "\f118"; 1144 | } 1145 | .icon-frown:before { 1146 | content: "\f119"; 1147 | } 1148 | .icon-meh:before { 1149 | content: "\f11a"; 1150 | } 1151 | .icon-gamepad:before { 1152 | content: "\f11b"; 1153 | } 1154 | .icon-keyboard:before { 1155 | content: "\f11c"; 1156 | } 1157 | .icon-flag-alt:before { 1158 | content: "\f11d"; 1159 | } 1160 | .icon-flag-checkered:before { 1161 | content: "\f11e"; 1162 | } 1163 | .icon-terminal:before { 1164 | content: "\f120"; 1165 | } 1166 | .icon-code:before { 1167 | content: "\f121"; 1168 | } 1169 | .icon-reply-all:before { 1170 | content: "\f122"; 1171 | } 1172 | .icon-mail-reply-all:before { 1173 | content: "\f122"; 1174 | } 1175 | .icon-star-half-full:before, 1176 | .icon-star-half-empty:before { 1177 | content: "\f123"; 1178 | } 1179 | .icon-location-arrow:before { 1180 | content: "\f124"; 1181 | } 1182 | .icon-crop:before { 1183 | content: "\f125"; 1184 | } 1185 | .icon-code-fork:before { 1186 | content: "\f126"; 1187 | } 1188 | .icon-unlink:before { 1189 | content: "\f127"; 1190 | } 1191 | .icon-question:before { 1192 | content: "\f128"; 1193 | } 1194 | .icon-info:before { 1195 | content: "\f129"; 1196 | } 1197 | .icon-exclamation:before { 1198 | content: "\f12a"; 1199 | } 1200 | .icon-superscript:before { 1201 | content: "\f12b"; 1202 | } 1203 | .icon-subscript:before { 1204 | content: "\f12c"; 1205 | } 1206 | .icon-eraser:before { 1207 | content: "\f12d"; 1208 | } 1209 | .icon-puzzle-piece:before { 1210 | content: "\f12e"; 1211 | } 1212 | .icon-microphone:before { 1213 | content: "\f130"; 1214 | } 1215 | .icon-microphone-off:before { 1216 | content: "\f131"; 1217 | } 1218 | .icon-shield:before { 1219 | content: "\f132"; 1220 | } 1221 | .icon-calendar-empty:before { 1222 | content: "\f133"; 1223 | } 1224 | .icon-fire-extinguisher:before { 1225 | content: "\f134"; 1226 | } 1227 | .icon-rocket:before { 1228 | content: "\f135"; 1229 | } 1230 | .icon-maxcdn:before { 1231 | content: "\f136"; 1232 | } 1233 | .icon-chevron-sign-left:before { 1234 | content: "\f137"; 1235 | } 1236 | .icon-chevron-sign-right:before { 1237 | content: "\f138"; 1238 | } 1239 | .icon-chevron-sign-up:before { 1240 | content: "\f139"; 1241 | } 1242 | .icon-chevron-sign-down:before { 1243 | content: "\f13a"; 1244 | } 1245 | .icon-html5:before { 1246 | content: "\f13b"; 1247 | } 1248 | .icon-css3:before { 1249 | content: "\f13c"; 1250 | } 1251 | .icon-anchor:before { 1252 | content: "\f13d"; 1253 | } 1254 | .icon-unlock-alt:before { 1255 | content: "\f13e"; 1256 | } 1257 | .icon-bullseye:before { 1258 | content: "\f140"; 1259 | } 1260 | .icon-ellipsis-horizontal:before { 1261 | content: "\f141"; 1262 | } 1263 | .icon-ellipsis-vertical:before { 1264 | content: "\f142"; 1265 | } 1266 | .icon-rss-sign:before { 1267 | content: "\f143"; 1268 | } 1269 | .icon-play-sign:before { 1270 | content: "\f144"; 1271 | } 1272 | .icon-ticket:before { 1273 | content: "\f145"; 1274 | } 1275 | .icon-minus-sign-alt:before { 1276 | content: "\f146"; 1277 | } 1278 | .icon-check-minus:before { 1279 | content: "\f147"; 1280 | } 1281 | .icon-level-up:before { 1282 | content: "\f148"; 1283 | } 1284 | .icon-level-down:before { 1285 | content: "\f149"; 1286 | } 1287 | .icon-check-sign:before { 1288 | content: "\f14a"; 1289 | } 1290 | .icon-edit-sign:before { 1291 | content: "\f14b"; 1292 | } 1293 | .icon-external-link-sign:before { 1294 | content: "\f14c"; 1295 | } 1296 | .icon-share-sign:before { 1297 | content: "\f14d"; 1298 | } 1299 | .icon-compass:before { 1300 | content: "\f14e"; 1301 | } 1302 | .icon-collapse:before { 1303 | content: "\f150"; 1304 | } 1305 | .icon-collapse-top:before { 1306 | content: "\f151"; 1307 | } 1308 | .icon-expand:before { 1309 | content: "\f152"; 1310 | } 1311 | .icon-euro:before, 1312 | .icon-eur:before { 1313 | content: "\f153"; 1314 | } 1315 | .icon-gbp:before { 1316 | content: "\f154"; 1317 | } 1318 | .icon-dollar:before, 1319 | .icon-usd:before { 1320 | content: "\f155"; 1321 | } 1322 | .icon-rupee:before, 1323 | .icon-inr:before { 1324 | content: "\f156"; 1325 | } 1326 | .icon-yen:before, 1327 | .icon-jpy:before { 1328 | content: "\f157"; 1329 | } 1330 | .icon-renminbi:before, 1331 | .icon-cny:before { 1332 | content: "\f158"; 1333 | } 1334 | .icon-won:before, 1335 | .icon-krw:before { 1336 | content: "\f159"; 1337 | } 1338 | .icon-bitcoin:before, 1339 | .icon-btc:before { 1340 | content: "\f15a"; 1341 | } 1342 | .icon-file:before { 1343 | content: "\f15b"; 1344 | } 1345 | .icon-file-text:before { 1346 | content: "\f15c"; 1347 | } 1348 | .icon-sort-by-alphabet:before { 1349 | content: "\f15d"; 1350 | } 1351 | .icon-sort-by-alphabet-alt:before { 1352 | content: "\f15e"; 1353 | } 1354 | .icon-sort-by-attributes:before { 1355 | content: "\f160"; 1356 | } 1357 | .icon-sort-by-attributes-alt:before { 1358 | content: "\f161"; 1359 | } 1360 | .icon-sort-by-order:before { 1361 | content: "\f162"; 1362 | } 1363 | .icon-sort-by-order-alt:before { 1364 | content: "\f163"; 1365 | } 1366 | .icon-thumbs-up:before { 1367 | content: "\f164"; 1368 | } 1369 | .icon-thumbs-down:before { 1370 | content: "\f165"; 1371 | } 1372 | .icon-youtube-sign:before { 1373 | content: "\f166"; 1374 | } 1375 | .icon-youtube:before { 1376 | content: "\f167"; 1377 | } 1378 | .icon-xing:before { 1379 | content: "\f168"; 1380 | } 1381 | .icon-xing-sign:before { 1382 | content: "\f169"; 1383 | } 1384 | .icon-youtube-play:before { 1385 | content: "\f16a"; 1386 | } 1387 | .icon-dropbox:before { 1388 | content: "\f16b"; 1389 | } 1390 | .icon-stackexchange:before { 1391 | content: "\f16c"; 1392 | } 1393 | .icon-instagram:before { 1394 | content: "\f16d"; 1395 | } 1396 | .icon-flickr:before { 1397 | content: "\f16e"; 1398 | } 1399 | .icon-adn:before { 1400 | content: "\f170"; 1401 | } 1402 | .icon-bitbucket:before { 1403 | content: "\f171"; 1404 | } 1405 | .icon-bitbucket-sign:before { 1406 | content: "\f172"; 1407 | } 1408 | .icon-tumblr:before { 1409 | content: "\f173"; 1410 | } 1411 | .icon-tumblr-sign:before { 1412 | content: "\f174"; 1413 | } 1414 | .icon-long-arrow-down:before { 1415 | content: "\f175"; 1416 | } 1417 | .icon-long-arrow-up:before { 1418 | content: "\f176"; 1419 | } 1420 | .icon-long-arrow-left:before { 1421 | content: "\f177"; 1422 | } 1423 | .icon-long-arrow-right:before { 1424 | content: "\f178"; 1425 | } 1426 | .icon-apple:before { 1427 | content: "\f179"; 1428 | } 1429 | .icon-windows:before { 1430 | content: "\f17a"; 1431 | } 1432 | .icon-android:before { 1433 | content: "\f17b"; 1434 | } 1435 | .icon-linux:before { 1436 | content: "\f17c"; 1437 | } 1438 | .icon-dribbble:before { 1439 | content: "\f17d"; 1440 | } 1441 | .icon-skype:before { 1442 | content: "\f17e"; 1443 | } 1444 | .icon-foursquare:before { 1445 | content: "\f180"; 1446 | } 1447 | .icon-trello:before { 1448 | content: "\f181"; 1449 | } 1450 | .icon-female:before { 1451 | content: "\f182"; 1452 | } 1453 | .icon-male:before { 1454 | content: "\f183"; 1455 | } 1456 | .icon-gittip:before { 1457 | content: "\f184"; 1458 | } 1459 | .icon-sun:before { 1460 | content: "\f185"; 1461 | } 1462 | .icon-moon:before { 1463 | content: "\f186"; 1464 | } 1465 | .icon-archive:before { 1466 | content: "\f187"; 1467 | } 1468 | .icon-bug:before { 1469 | content: "\f188"; 1470 | } 1471 | .icon-vk:before { 1472 | content: "\f189"; 1473 | } 1474 | .icon-weibo:before { 1475 | content: "\f18a"; 1476 | } 1477 | .icon-renren:before { 1478 | content: "\f18b"; 1479 | } 1480 | --------------------------------------------------------------------------------