- Full move to high charts.
- Cleanup homepage. - Expanded libraries - Added limits (for budgets) - Extended models - Added popups for charts. - [skip-ci]
| @@ -1,5 +1,6 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Helper\Preferences\PreferencesHelperInterface as PHI; | ||||
| use Firefly\Helper\Toolkit\Toolkit as tk; | ||||
| use Firefly\Storage\Account\AccountRepositoryInterface as ARI; | ||||
| use Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface as TJRI; | ||||
| @@ -12,15 +13,17 @@ class ChartController extends BaseController | ||||
|  | ||||
|     protected $_accounts; | ||||
|     protected $_journals; | ||||
|     protected $_preferences; | ||||
|  | ||||
|     /** | ||||
|      * @param ARI  $accounts | ||||
|      * @param TJRI $journals | ||||
|      */ | ||||
|     public function __construct(ARI $accounts, TJRI $journals) | ||||
|     public function __construct(ARI $accounts, TJRI $journals, PHI $preferences) | ||||
|     { | ||||
|         $this->_accounts = $accounts; | ||||
|         $this->_journals = $journals; | ||||
|         $this->_preferences = $preferences; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -34,98 +37,139 @@ class ChartController extends BaseController | ||||
|         $current = clone $start; | ||||
|         $return = []; | ||||
|         $account = null; | ||||
|         $today = new Carbon\Carbon; | ||||
|  | ||||
|         if (!is_null($accountId)) { | ||||
|             /** @var \Account $account */ | ||||
|             $account = $this->_accounts->find($accountId); | ||||
|         } | ||||
|  | ||||
|         if (is_null($account)) { | ||||
|             $accounts = $this->_accounts->getActiveDefault(); | ||||
|  | ||||
|             $pref = $this->_preferences->get('frontpageAccounts', []); | ||||
|             if ($pref->data == []) { | ||||
|                 $accounts = $this->_accounts->getActiveDefault(); | ||||
|             } else { | ||||
|                 $accounts = $this->_accounts->getByIds($pref->data); | ||||
|             } | ||||
|             foreach ($accounts as $account) { | ||||
|                 $return[] = ['name' => $account->name, 'data' => []]; | ||||
|                 $return[] = ['name' => $account->name, 'id' => 'acc-' . $account->id, 'data' => []]; | ||||
|  | ||||
|             } | ||||
|             while ($current <= $end) { | ||||
|  | ||||
|                 // loop accounts: | ||||
|                 foreach ($accounts as $index => $account) { | ||||
|  | ||||
|  | ||||
|                     if ($current > $today) { | ||||
|                         $return[$index]['data'][] = [$current->timestamp * 1000, $account->predict(clone $current)]; | ||||
|                     } else { | ||||
|                         $return[$index]['data'][] = [$current->timestamp * 1000, $account->balance(clone $current)]; | ||||
|                     } | ||||
|                 } | ||||
|                 $current->addDay(); | ||||
|             } | ||||
|         } else { | ||||
|             $return[0] = ['name' => $account->name, 'data' => []]; | ||||
|             $return[0] = ['name' => $account->name, 'id' => $account->id, 'data' => []]; | ||||
|  | ||||
|             while ($current <= $end) { | ||||
|  | ||||
|                 if ($current > $today) { | ||||
|                     $return[0]['data'][] = [$current->timestamp * 1000, $account->predict(clone $current)]; | ||||
|                 } else { | ||||
|                     $return[0]['data'][] = [$current->timestamp * 1000, $account->balance(clone $current)]; | ||||
|                 } | ||||
|  | ||||
|                 $current->addDay(); | ||||
|             } | ||||
|  | ||||
|         } | ||||
| //        // add an error bar as experiment: | ||||
| //        foreach($return as $index => $serie) { | ||||
| //            $err = [ | ||||
| //                'type' => 'errorbar', | ||||
| //                'name' => $serie['name'].' pred', | ||||
| //                'linkedTo' => $serie['id'], | ||||
| //                'data' => [] | ||||
| //            ]; | ||||
| //            foreach($serie['data'] as $entry) { | ||||
| //                $err['data'][] = [$entry[0],10,300]; | ||||
| //            } | ||||
| //            $return[] = $err; | ||||
| //        } | ||||
|  | ||||
|  | ||||
|         return Response::json($return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all budgets used in transaction(journals) this period: | ||||
|      * Return some beneficiary info for an account and a date. | ||||
|      * | ||||
|      * @param $name | ||||
|      * @param $day | ||||
|      * @param $month | ||||
|      * @param $year | ||||
|      */ | ||||
|     public function homeBudgets() | ||||
|     public function homeAccountInfo($name, $day, $month, $year) | ||||
|     { | ||||
|         $account = $this->_accounts->findByName($name); | ||||
|         $result = []; | ||||
|         $sum = 0; | ||||
|         if ($account) { | ||||
|             $date = \Carbon\Carbon::createFromDate($year, $month, $day); | ||||
|             $journals = $this->_journals->getByAccountAndDate($account, $date); | ||||
|  | ||||
|             // loop all journals: | ||||
|             foreach ($journals as $journal) { | ||||
|                 foreach ($journal->transactions as $transaction) { | ||||
|                     $name = $transaction->account->name; | ||||
|                     if ($transaction->account->id != $account->id) { | ||||
|                         $result[$name] = isset($result[$name]) ? $result[$name] + floatval($transaction->amount) | ||||
|                             : floatval($transaction->amount); | ||||
|                         $sum += floatval($transaction->amount); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return View::make('charts.info')->with('rows', $result)->with('sum', $sum); | ||||
|     } | ||||
|  | ||||
|     public function homeCategories() { | ||||
|         list($start, $end) = tk::getDateRange(); | ||||
|         $data = [ | ||||
|             'type' => 'pie', | ||||
|             'name' => 'Expense: ', | ||||
|             'data' => [] | ||||
|         $account = null; | ||||
|         $result = []; | ||||
|         // grab all transaction journals in this period: | ||||
|         $journals = $this->_journals->getByDateRange($start,$end); | ||||
|  | ||||
|         $result = []; | ||||
|         foreach ($journals as $journal) { | ||||
|             // has to be one: | ||||
|  | ||||
|             if (!isset($journal->transactions[0])) { | ||||
|                 throw new FireflyException('Journal #' . $journal->id . ' has ' . count($journal->transactions) | ||||
|                     . ' transactions!'); | ||||
|             } | ||||
|             $transaction = $journal->transactions[0]; | ||||
|             $amount = floatval($transaction->amount); | ||||
|  | ||||
|             // get budget from journal: | ||||
|             $budget = $journal->categories()->first(); | ||||
|             $budgetName = is_null($budget) ? '(no category)' : $budget->name; | ||||
|  | ||||
|             $result[$budgetName] = isset($result[$budgetName]) ? $result[$budgetName] + floatval($amount) : $amount; | ||||
|  | ||||
|         } | ||||
|         unset($journal, $transaction, $budget, $amount); | ||||
|  | ||||
|         // sort | ||||
|         arsort($result); | ||||
|         $chartData = [ | ||||
|         ]; | ||||
|  | ||||
|         $result = $this->_journals->homeBudgetChart($start, $end); | ||||
|  | ||||
|         foreach ($result as $name => $amount) { | ||||
|             $data['data'][] = [$name, $amount]; | ||||
|         } | ||||
|         return Response::json([$data]); | ||||
|  | ||||
|         foreach($result as $name => $value) { | ||||
|             $chartData[] = [$name, $value]; | ||||
|         } | ||||
|  | ||||
|     /** | ||||
|      * Get all categories used in transaction(journals) this period. | ||||
|      */ | ||||
|     public function homeCategories() | ||||
|     { | ||||
|         list($start, $end) = tk::getDateRange(); | ||||
|  | ||||
|         $result = $this->_journals->homeCategoryChart($start, $end); | ||||
|         $data = [ | ||||
|             'type' => 'pie', | ||||
|             'name' => 'Amount: ', | ||||
|             'data' => [] | ||||
|         ]; | ||||
|  | ||||
|         foreach ($result as $name => $amount) { | ||||
|             $data['data'][] = [$name, $amount]; | ||||
|         } | ||||
|         return Response::json([$data]); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * get all beneficiaries used in transaction(journals) this period. | ||||
|      */ | ||||
|     public function homeBeneficiaries() | ||||
|     { | ||||
|         list($start, $end) = tk::getDateRange(); | ||||
|         $data = [ | ||||
|             'type' => 'pie', | ||||
|             'name' => 'Amount: ', | ||||
|             'data' => [] | ||||
|         ]; | ||||
|  | ||||
|         $result = $this->_journals->homeBeneficiaryChart($start, $end); | ||||
|  | ||||
|         foreach ($result as $name => $amount) { | ||||
|             $data['data'][] = [$name, $amount]; | ||||
|         } | ||||
|         return Response::json([$data]); | ||||
|         return Response::json($chartData); | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -30,24 +30,10 @@ class HomeController extends BaseController | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         // get list setting: | ||||
|         $pref = $this->_preferences->get('frontpageAccounts', []); | ||||
|  | ||||
|         // get the accounts to display on the home screen: | ||||
|         $count = $this->_accounts->count(); | ||||
|         if ($pref->data == []) { | ||||
|             $list = $this->_accounts->getActiveDefault(); | ||||
|         } else { | ||||
|             $list = $this->_accounts->getByIds($pref->data); | ||||
|         } | ||||
|  | ||||
|         // get transactions for each account: | ||||
|         foreach ($list as $account) { | ||||
|             $account->transactionList = $this->_journal->getByAccount($account, 10); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         // build the home screen: | ||||
|         return View::make('index')->with('count', $count)->with('accounts', $list); | ||||
|         return View::make('index')->with('count', $count); | ||||
|     } | ||||
| } | ||||
| @@ -40,6 +40,8 @@ class MigrationController extends BaseController | ||||
|                 exit(); | ||||
|             } | ||||
|         } | ||||
|         echo '<a href="'.route('index').'">home</a>'; | ||||
|         exit(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -0,0 +1,41 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
|  | ||||
| class CreateLimitsTable extends Migration { | ||||
|  | ||||
| 	/** | ||||
| 	 * Run the migrations. | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	public function up() | ||||
| 	{ | ||||
| 		Schema::create('limits', function(Blueprint $table) | ||||
| 		{ | ||||
| 			$table->increments('id'); | ||||
| 			$table->timestamps(); | ||||
|             $table->integer('component_id')->unsigned(); | ||||
|             $table->date('startdate'); | ||||
|             $table->date('enddate'); | ||||
|             $table->decimal('amount',10,2); | ||||
|  | ||||
|             // connect component | ||||
|             $table->foreign('component_id') | ||||
|                 ->references('id')->on('components') | ||||
|                 ->onDelete('cascade'); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Reverse the migrations. | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	public function down() | ||||
| 	{ | ||||
| 		Schema::drop('limits'); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -167,127 +167,16 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function homeBudgetChart(\Carbon\Carbon $start, \Carbon\Carbon $end) | ||||
|     { | ||||
|         return $this->homeComponentChart($start, $end, 'Budget'); | ||||
|     } | ||||
|  | ||||
|     public function homeComponentChart(\Carbon\Carbon $start, \Carbon\Carbon $end, $chartType) | ||||
|     { | ||||
|  | ||||
|         // lets make this simple. | ||||
|         $types = []; | ||||
|         foreach (\TransactionType::whereIn('type', ['Withdrawal'])->get() as $t) { | ||||
|             $types[] = $t->id; | ||||
|         } | ||||
|         unset($t); | ||||
|  | ||||
|         // get all journals, partly filtered: | ||||
|         $journals = \TransactionJournal:: | ||||
|             with( | ||||
|                 ['components'         => function ($q) use ($chartType) { | ||||
|                         $q->where('class', $chartType); | ||||
|                     }, 'transactions' => function ($q) { | ||||
|                         $q->where('amount', '>', 0); | ||||
|                     }] | ||||
|             ) | ||||
|             ->after($start)->before($end) | ||||
|             ->where('completed', 1) | ||||
|             ->whereIn('transaction_type_id', $types) | ||||
|             ->get(['transaction_journals.*']); | ||||
|         unset($types); | ||||
|         $result = []; | ||||
|  | ||||
|  | ||||
|         foreach ($journals as $journal) { | ||||
|             // has to be one: | ||||
|             if (!isset($journal->transactions[0])) { | ||||
|                 throw new FireflyException('Journal #' . $journal->id . ' has ' . count($journal->transactions) | ||||
|                     . ' transactions!'); | ||||
|             } | ||||
|             $transaction = $journal->transactions[0]; | ||||
|             $amount = floatval($transaction->amount); | ||||
|  | ||||
|  | ||||
|             // MIGHT be one: | ||||
|             $budget = isset($journal->components[0]) ? $journal->components[0] : null; | ||||
|             if (!is_null($budget)) { | ||||
|                 $name = $budget->name; | ||||
|             } else { | ||||
|                 $name = '(no budget)'; | ||||
|             } | ||||
|             $result[$name] = isset($result[$name]) ? $result[$name] + $amount : $amount; | ||||
|  | ||||
|         } | ||||
|         unset($journal, $transaction, $budget, $name, $amount); | ||||
|  | ||||
|         // sort | ||||
|         arsort($result); | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     public function homeCategoryChart(\Carbon\Carbon $start, \Carbon\Carbon $end) | ||||
|     { | ||||
|         return $this->homeComponentChart($start, $end, 'Category'); | ||||
|     } | ||||
|  | ||||
|     public function homeBeneficiaryChart(\Carbon\Carbon $start, \Carbon\Carbon $end) | ||||
|     { | ||||
|         $result = []; | ||||
|  | ||||
|         // lets make this simple. | ||||
|         $types = []; | ||||
|         foreach (\TransactionType::whereIn('type', ['Withdrawal'])->get() as $t) { | ||||
|             $types[] = $t->id; | ||||
|         } | ||||
|         unset($t); | ||||
|  | ||||
|         // account type we want to see: | ||||
|         $accountType = \AccountType::where('description', 'Beneficiary account')->first(); | ||||
|         $accountTypeID = $accountType->id; | ||||
|  | ||||
|         // get all journals, partly filtered: | ||||
|         $journals = \TransactionJournal:: | ||||
|             with( | ||||
|                 ['transactions', 'transactions.account' => function ($q) use ($accountTypeID) { | ||||
|                         $q->where('account_type_id', $accountTypeID); | ||||
|                     }] | ||||
|             ) | ||||
|             ->after($start)->before($end) | ||||
|             ->whereIn('transaction_type_id', $types) | ||||
|             ->orderBy('date', 'DESC') | ||||
|             ->orderBy('id', 'DESC') | ||||
|             ->get(['transaction_journals.*']); | ||||
|         foreach ($journals as $journal) { | ||||
|             foreach ($journal->transactions as $t) { | ||||
|                 if (!is_null($t->account)) { | ||||
|                     $name = $t->account->name; | ||||
|                     $amount = floatval($t->amount) < 0 ? floatval($t->amount) * -1 : floatval($t->amount); | ||||
|  | ||||
|                     $result[$name] = isset($result[$name]) ? $result[$name] + $amount : $amount; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // sort result: | ||||
|         arsort($result); | ||||
|  | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     public function getByAccount(\Account $account, $count = 25) | ||||
|     { | ||||
|         $accountID = $account->id; | ||||
|         $query = \TransactionJournal:: | ||||
|             with( | ||||
|         $query = \Auth::user()->transactionjournals()->with( | ||||
|             [ | ||||
|                 'transactions', | ||||
|                 'transactioncurrency', | ||||
|                 'transactiontype' | ||||
|             ] | ||||
|         ) | ||||
|             ->take($count) | ||||
|             ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|             ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|             ->where('accounts.id', $accountID) | ||||
| @@ -298,5 +187,51 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito | ||||
|         return $query; | ||||
|     } | ||||
|  | ||||
|     public function getByDateRange(\Carbon\Carbon $start, \Carbon\Carbon $end) | ||||
|     { | ||||
|         // lets make this simple. | ||||
|         $types = []; | ||||
|         foreach (\TransactionType::whereIn('type', ['Withdrawal'])->get() as $t) { | ||||
|             $types[] = $t->id; | ||||
|         } | ||||
|         unset($t); | ||||
|  | ||||
|         // get all journals, partly filtered: | ||||
|         $journals = \TransactionJournal:: | ||||
|             with( | ||||
|                 ['components', 'transactions' => function ($q) { | ||||
|                         $q->where('amount', '>', 0); | ||||
|                     }] | ||||
|             ) | ||||
|             ->after($start)->before($end) | ||||
|             ->where('completed', 1) | ||||
|             ->whereIn('transaction_type_id', $types) | ||||
|             ->get(['transaction_journals.*']); | ||||
|         unset($types); | ||||
|         return $journals; | ||||
|     } | ||||
|  | ||||
|     public function getByAccountAndDate(\Account $account, \Carbon\Carbon $date) | ||||
|     { | ||||
|         $accountID = $account->id; | ||||
|         $query = \Auth::user()->transactionjournals()->with( | ||||
|             [ | ||||
|                 'transactions', | ||||
|                 'transactions.account', | ||||
|                 'transactioncurrency', | ||||
|                 'transactiontype' | ||||
|             ] | ||||
|         ) | ||||
|             ->distinct() | ||||
|             ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|             ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|             ->where('transactions.account_id', $accountID) | ||||
|             ->where('transaction_journals.date', $date->format('Y-m-d')) | ||||
|             ->orderBy('transaction_journals.date', 'DESC') | ||||
|             ->orderBy('transaction_journals.id', 'DESC') | ||||
|             ->get(['transaction_journals.*']); | ||||
|         return $query; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -13,12 +13,8 @@ interface TransactionJournalRepositoryInterface | ||||
|  | ||||
|     public function getByAccount(\Account $account, $count = 25); | ||||
|  | ||||
|     public function homeBudgetChart(\Carbon\Carbon $start, \Carbon\Carbon $end); | ||||
|     public function getByAccountAndDate(\Account $account, \Carbon\Carbon $date); | ||||
|  | ||||
|     public function homeCategoryChart(\Carbon\Carbon $start, \Carbon\Carbon $end); | ||||
|  | ||||
|     public function homeBeneficiaryChart(\Carbon\Carbon $start, \Carbon\Carbon $end); | ||||
|  | ||||
|     public function homeComponentChart(\Carbon\Carbon $start, \Carbon\Carbon $end, $chartType); | ||||
|     public function getByDateRange(\Carbon\Carbon $start, \Carbon\Carbon $end); | ||||
|  | ||||
| } | ||||
| @@ -88,10 +88,14 @@ class Account extends Ardent | ||||
|                 ->leftJoin( | ||||
|                     'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' | ||||
|                 ) | ||||
|                 ->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount') | ||||
|                 ->where('transaction_journals.date', '<', $date->format('Y-m-d'))->sum('transactions.amount') | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function predict(\Carbon\Carbon $date) { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Transactions. | ||||
|      * | ||||
|   | ||||
| @@ -42,6 +42,10 @@ class Component extends Firefly\Database\SingleTableInheritanceEntity | ||||
|         return $this->belongsToMany('Transaction'); | ||||
|     } | ||||
|  | ||||
|     public function limits() { | ||||
|         return $this->belongsTo('Limit'); | ||||
|     } | ||||
|  | ||||
|     public function transactionjournals() | ||||
|     { | ||||
|         return $this->belongsToMany('TransactionJournal'); | ||||
|   | ||||
							
								
								
									
										41
									
								
								app/models/Limit.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,41 @@ | ||||
| <?php | ||||
|  | ||||
| use LaravelBook\Ardent\Ardent as Ardent; | ||||
|  | ||||
| class Limit extends Ardent | ||||
| { | ||||
|  | ||||
|     public static $rules | ||||
|         = [ | ||||
|             'component_id' => 'required|exists:components,id', | ||||
|             'startdate'    => 'required|date', | ||||
|             'enddate'      => 'required|date', | ||||
|             'amount'       => 'numeric|required|min:0.01' | ||||
|  | ||||
|         ]; | ||||
|  | ||||
|     public static $factory | ||||
|         = [ | ||||
|             'component_id' => 'factory|Budget', | ||||
|             'startdate'    => 'date', | ||||
|             'enddate'      => 'date', | ||||
|             'amount'       => '100' | ||||
|         ]; | ||||
|  | ||||
|     public function component() | ||||
|     { | ||||
|         return $this->belongsTo('Component'); | ||||
|     } | ||||
|  | ||||
|     public function budget() | ||||
|     { | ||||
|         return $this->belongsTo('Budget', 'component_id'); | ||||
|     } | ||||
|  | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'startdate', 'enddate']; | ||||
|     } | ||||
|  | ||||
|  | ||||
| }  | ||||
| @@ -7,9 +7,9 @@ Route::group(['before' => 'auth'], function () { | ||||
|  | ||||
|         // chart controller | ||||
|         Route::get('/chart/home/account/{account?}', ['uses' => 'ChartController@homeAccount', 'as' => 'chart.home']); | ||||
|         Route::get('/chart/home/budgets', ['uses' => 'ChartController@homeBudgets', 'as' => 'chart.budgets']); | ||||
|         Route::get('/chart/home/beneficiaries', ['uses' => 'ChartController@homeBeneficiaries', 'as' => 'chart.beneficiaries']); | ||||
|         Route::get('/chart/home/categories', ['uses' => 'ChartController@homeCategories', 'as' => 'chart.categories']); | ||||
|         Route::get('/chart/home/info/{account}/{day}/{month}/{year}', ['uses' => 'ChartController@homeAccountInfo', 'as' => 'chart.info']); | ||||
|  | ||||
|  | ||||
|         // preferences controller | ||||
|         Route::get('/preferences', ['uses' => 'PreferencesController@index', 'as' => 'preferences']); | ||||
| @@ -26,6 +26,9 @@ Route::group(['before' => 'auth'], function () { | ||||
|         Route::get('/accounts/create', ['uses' => 'AccountController@create', 'as' => 'accounts.create']); | ||||
|         Route::get('/accounts/{account}', ['uses' => 'AccountController@show', 'as' => 'accounts.show']); | ||||
|  | ||||
|         // budget controller | ||||
|         Route::get('/bugets',['uses' => 'BudgetController@index','as' => 'budgets.index']); | ||||
|  | ||||
|         // JSON controller: | ||||
|         Route::get('/json/beneficiaries', ['uses' => 'JsonController@beneficiaries', 'as' => 'json.beneficiaries']); | ||||
|         Route::get('/json/categories', ['uses' => 'JsonController@categories', 'as' => 'json.categories']); | ||||
|   | ||||
| @@ -13,64 +13,12 @@ class HomeControllerTest extends TestCase | ||||
|         View::shouldReceive('share'); | ||||
|         View::shouldReceive('make')->with('index')->once()->andReturn(\Mockery::self()) | ||||
|             ->shouldReceive('with')->once()         // Pass a 'with' parameter | ||||
|             ->with('count', 0) | ||||
|             ->andReturn(Mockery::self()) | ||||
|             ->shouldReceive('with')->once() // another 'with' parameter. | ||||
|             ->with('accounts',[]) | ||||
|             ->andReturn(Mockery::self()) | ||||
|             ; | ||||
|             ->with('count', 0); | ||||
|         Auth::shouldReceive('check')->andReturn(true); | ||||
|  | ||||
|         // mock account repository | ||||
|         $accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
|         $accounts->shouldReceive('count')->andReturn(0); | ||||
|         $accounts->shouldReceive('getActiveDefault')->andReturn([]); | ||||
|  | ||||
|         $preferences = $this->mock('Firefly\Helper\Preferences\PreferencesHelperInterface'); | ||||
|         $preferences->shouldReceive('get')->with('frontpageAccounts',[])->andReturn(new \Preference)->once(); | ||||
|  | ||||
|         // call | ||||
|         $this->call('GET', '/'); | ||||
|  | ||||
|         // test | ||||
|         $this->assertResponseOk(); | ||||
|     } | ||||
|  | ||||
|     public function testIndexWithAccount() { | ||||
|  | ||||
|         // mock Account | ||||
|         $account = $this->mock('Account'); | ||||
|         $account->shouldReceive('setAttribute')->with('transactionList',[]); | ||||
|  | ||||
|         // mock account repository | ||||
|         $accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
|         $accounts->shouldReceive('count')->andReturn(0); | ||||
|         $accounts->shouldReceive('getByIds')->andReturn([$account]); | ||||
|  | ||||
|         // mock: | ||||
|         View::shouldReceive('share'); | ||||
|         View::shouldReceive('make')->with('index')->once()->andReturn(\Mockery::self()) | ||||
|             ->shouldReceive('with')->once()         // Pass a 'with' parameter | ||||
|             ->with('count', 0) | ||||
|             ->andReturn(Mockery::self()) | ||||
|             ->shouldReceive('with')->once() // another 'with' parameter. | ||||
|             ->with('accounts',[$account]) | ||||
|             ->andReturn(Mockery::self()) | ||||
|         ; | ||||
|  | ||||
|  | ||||
|  | ||||
|         // mock transaction journal | ||||
|         $tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'); | ||||
|         $tj->shouldReceive('getByAccount')->with($account,10)->andReturn([]); | ||||
|  | ||||
|         // mock preferences helper: | ||||
|         $pref = $this->mock('Preference'); | ||||
|         $pref->shouldReceive('getAttribute', 'data')->andReturn([1]); | ||||
|  | ||||
|  | ||||
|         $preferences = $this->mock('Firefly\Helper\Preferences\PreferencesHelperInterface'); | ||||
|         $preferences->shouldReceive('get')->with('frontpageAccounts',[])->andReturn($pref)->once(); | ||||
|  | ||||
|         // call | ||||
|         $this->call('GET', '/'); | ||||
|   | ||||
							
								
								
									
										12
									
								
								app/views/charts/info.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,12 @@ | ||||
| <table class="table table-condensed"> | ||||
|     <tr> | ||||
|         <th>Total</th> | ||||
|         <th>{{mf($sum*-1)}}</th> | ||||
|     </tr> | ||||
|     @foreach($rows as $name => $amount) | ||||
|     <tr> | ||||
|         <td><a href="#">{{{$name}}}</a></td> | ||||
|         <td>{{mf($amount*-1)}}</td> | ||||
|     </tr> | ||||
|     @endforeach | ||||
| </table> | ||||
| @@ -35,6 +35,7 @@ | ||||
|         </p> | ||||
|     </div> | ||||
| </div> | ||||
| <div id="something">Bla bla</div> | ||||
| <div class="row"> | ||||
|     <div class="col-lg-6 col-md-6 col-sm-12"> | ||||
|         <h2><a href="{{route('migrate')}}">Migrate from Firefly II</a></h2> | ||||
| @@ -54,64 +55,27 @@ | ||||
|  | ||||
|     <!-- ACCOUNTS --> | ||||
|     <div class="row"> | ||||
|     @foreach($accounts as $index => $account) | ||||
|         <div class="col-lg-6"> | ||||
|             <div id="chart_{{{$account->id}}}" data-id="{{{$account->id}}}" style="width:100%;" class="homeChart" data-title="{{{$account->name}}}"></div> | ||||
|             <p> | ||||
|                 Go to <a href="#" title="Overview for {{{$account->name}}}">{{{$account->name}}}</a> | ||||
|             </p> | ||||
|  | ||||
|         <div class="col-lg-12 col-md-12 col-sm-12"> | ||||
|             <div id="chart"></div> | ||||
|         </div> | ||||
|         @if($index % 2 == 1) | ||||
|         </div><div class="row"> | ||||
|         @endif | ||||
|     @endforeach | ||||
|     </div> | ||||
|  | ||||
|     <!-- TRANSACTIONS --> | ||||
|     <div class="row"> | ||||
|         @foreach($accounts as $index => $account) | ||||
|         <div class="col-lg-6"> | ||||
|             <h4>{{$account->name}}</h4> | ||||
|             @include('transactions.journals',['journals' => $account->transactionList]) | ||||
|         </div> | ||||
|         @if($index % 2 == 1) | ||||
|     </div><div class="row"> | ||||
|         @endif | ||||
|         @endforeach | ||||
|     </div> | ||||
|  | ||||
|  | ||||
|     <!-- week / month / year navigation --> | ||||
|     <div class="row"> | ||||
|         <div class="col-lg-2 col-sm-6 col-md-2"> | ||||
|             <a href="#" class="btn btn-default btn-xs">Previous [period]</a> | ||||
|         </div> | ||||
|  | ||||
|         <div class="col-lg-offset-8 col-lg-2 col-sm-6 col-md-offset-8 col-md-2" style="text-align: right;"> | ||||
|             <a href="#" class="btn btn-default btn-xs">Next [period]</a> | ||||
|         <div class="col-lg-12 col-md-12 col-sm-12"> | ||||
|             <div id="categories"></div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <!-- Beneficiaries, categories and budget pie charts: --> | ||||
|     <div class="row"> | ||||
|         <div class="col-lg-4 col-sm-6 col-md-6"> | ||||
|             <div style="width:80%;margin:0 auto;" id="beneficiaryChart"></div> | ||||
|         </div> | ||||
|         <div class="col-lg-4 col-sm-6 col-md-6"> | ||||
|             <div style="width:80%;margin:0 auto;" id="categoryChart"></div> | ||||
|         </div> | ||||
|         <div class="col-lg-4 col-sm-6 col-md-6"> | ||||
|             <div style="width:80%;margin:0 auto;" id="budgetChart"></div> | ||||
|         </div> | ||||
|     </div> | ||||
|     <br /><br /><br /><br /><br /> | ||||
|  | ||||
|  | ||||
| @endif | ||||
|  | ||||
| @stop | ||||
| @section('scripts') | ||||
|     <script src="assets/javascript/highcharts.js"></script> | ||||
|     <script src="assets/javascript/index.new.js"></script> | ||||
|     <script src="assets/javascript/highcharts-more.js"></script> | ||||
|     <script src="assets/javascript/highslide-full.min.js"></script> | ||||
|     <script src="assets/javascript/highslide.config.js"></script> | ||||
|     <script src="assets/javascript/index.js"></script> | ||||
| @stop | ||||
| @section('styles') | ||||
|     <link href="assets/css/highslide.css" rel="stylesheet"> | ||||
| @stop | ||||
| @@ -10,6 +10,7 @@ | ||||
|     <!-- Bootstrap --> | ||||
|     <link href="assets/bootstrap/css/bootstrap.min.css" rel="stylesheet"> | ||||
|     <link href="assets/css/site.css" rel="stylesheet"> | ||||
|     @yield('styles') | ||||
|  | ||||
|     <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> | ||||
|     <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> | ||||
|   | ||||
| @@ -21,8 +21,8 @@ $r = Route::current()->getName(); | ||||
|                 <li class="dropdown"> | ||||
|                     <a href="#" class="dropdown-toggle" data-toggle="dropdown">Go to...<span class="caret"></span></a> | ||||
|                     <ul class="dropdown-menu" role="menu"> | ||||
|                         <li><a href="{{route('accounts.index')}}">Accounts</a></li> | ||||
|                         <li><a href="#">Another action</a></li> | ||||
|                         <li><a href="{{route('accounts.index')}}"><span class="glyphicon glyphicon-inbox"></span> Accounts</a></li> | ||||
|                         <li><a href="{{route('budgets.index')}}"><span class="glyphicon glyphicon-euro"></span> Budgets</a></li> | ||||
|                         <li><a href="#">Something else here</a></li> | ||||
|                         <li class="divider"></li> | ||||
|                         <li><a href="#">Separated link</a></li> | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/close.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 1.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/closeX.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/controlbar-black-border.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 5.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/controlbar-text-buttons.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 1.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/controlbar-white-small.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 3.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/controlbar-white.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 4.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/controlbar2.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 884 B | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/controlbar3.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 838 B | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/controlbar4-hover.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 2.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/controlbar4.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 854 B | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/fullexpand.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 209 B | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/geckodimmer.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 2.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/icon.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 867 B | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/loader.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 668 B | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/loader.white.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 673 B | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/outlines/Outlines.psd
									
									
									
									
									
										Executable file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/outlines/beveled.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/outlines/drop-shadow.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 2.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/outlines/glossy-dark.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 2.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/outlines/outer-glow.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 3.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/outlines/rounded-black.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 3.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/outlines/rounded-white.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 2.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/resize.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 70 B | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/scrollarrows.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 6.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/zoomin.cur
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 326 B | 
							
								
								
									
										
											BIN
										
									
								
								public/assets/css/graphics/zoomout.cur
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 326 B | 
							
								
								
									
										889
									
								
								public/assets/css/highslide.css
									
									
									
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,889 @@ | ||||
| /** | ||||
| * @file: highslide.css  | ||||
| * @version: 4.1.13 | ||||
| */ | ||||
| .highslide-container div { | ||||
| 	font-family: Verdana, Helvetica; | ||||
| 	font-size: 10pt; | ||||
| } | ||||
| .highslide-container table { | ||||
| 	background: none; | ||||
| } | ||||
| .highslide { | ||||
| 	outline: none; | ||||
| 	text-decoration: none; | ||||
| } | ||||
| .highslide img { | ||||
| 	border: 2px solid silver; | ||||
| } | ||||
| .highslide:hover img { | ||||
| 	border-color: gray; | ||||
| } | ||||
| .highslide-active-anchor img { | ||||
| 	visibility: hidden; | ||||
| } | ||||
| .highslide-gallery .highslide-active-anchor img { | ||||
| 	border-color: black; | ||||
| 	visibility: visible; | ||||
| 	cursor: default; | ||||
| } | ||||
| .highslide-image { | ||||
| 	border-width: 2px; | ||||
| 	border-style: solid; | ||||
| 	border-color: white; | ||||
| } | ||||
| .highslide-wrapper, .highslide-outline { | ||||
| 	background: white; | ||||
| } | ||||
| .glossy-dark { | ||||
| 	background: #111; | ||||
| } | ||||
|  | ||||
| .highslide-image-blur { | ||||
| } | ||||
| .highslide-number { | ||||
| 	font-weight: bold; | ||||
| 	color: gray; | ||||
| 	font-size: .9em; | ||||
| } | ||||
| .highslide-caption { | ||||
| 	display: none; | ||||
| 	font-size: 1em; | ||||
| 	padding: 5px; | ||||
| 	/*background: white;*/ | ||||
| } | ||||
| .highslide-heading { | ||||
| 	display: none; | ||||
| 	font-weight: bold; | ||||
| 	margin: 0.4em; | ||||
| } | ||||
| .highslide-dimming { | ||||
| 	/*position: absolute;*/ | ||||
| 	background: black; | ||||
| } | ||||
| a.highslide-full-expand { | ||||
|    background: url(graphics/fullexpand.gif) no-repeat; | ||||
|    display: block; | ||||
|    margin: 0 10px 10px 0; | ||||
|    width: 34px; | ||||
|    height: 34px; | ||||
| } | ||||
| .highslide-loading { | ||||
| 	display: block; | ||||
| 	color: black; | ||||
| 	font-size: 9px; | ||||
| 	font-weight: bold; | ||||
| 	text-transform: uppercase; | ||||
| 	text-decoration: none; | ||||
| 	padding: 3px; | ||||
| 	border: 1px solid white; | ||||
| 	background-color: white; | ||||
| 	padding-left: 22px; | ||||
| 	background-image: url(graphics/loader.white.gif); | ||||
| 	background-repeat: no-repeat; | ||||
| 	background-position: 3px 1px; | ||||
| } | ||||
| a.highslide-credits, | ||||
| a.highslide-credits i { | ||||
| 	padding: 2px; | ||||
| 	color: silver; | ||||
| 	text-decoration: none; | ||||
| 	font-size: 10px; | ||||
| } | ||||
| a.highslide-credits:hover, | ||||
| a.highslide-credits:hover i { | ||||
| 	color: white; | ||||
| 	background-color: gray; | ||||
| } | ||||
| .highslide-move, .highslide-move * { | ||||
| 	cursor: move; | ||||
| } | ||||
|  | ||||
| .highslide-viewport { | ||||
| 	display: none; | ||||
| 	position: fixed; | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
| 	z-index: 1; | ||||
| 	background: none; | ||||
| 	left: 0; | ||||
| 	top: 0; | ||||
| } | ||||
| .highslide-overlay { | ||||
| 	display: none; | ||||
| } | ||||
| .hidden-container { | ||||
| 	display: none; | ||||
| } | ||||
| /* Example of a semitransparent, offset closebutton */ | ||||
| .closebutton { | ||||
| 	position: relative; | ||||
| 	top: -15px; | ||||
| 	left: 15px; | ||||
| 	width: 30px; | ||||
| 	height: 30px; | ||||
| 	cursor: pointer; | ||||
| 	background: url(graphics/close.png); | ||||
| 	/* NOTE! For IE6, you also need to update the highslide-ie6.css file. */ | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
| /* Thumbnail boxes for the galleries.                                        */ | ||||
| /* Remove these if you are not using a gallery.                              */ | ||||
| /*****************************************************************************/ | ||||
| .highslide-gallery ul { | ||||
| 	list-style-type: none; | ||||
| 	margin: 0; | ||||
| 	padding: 0; | ||||
| } | ||||
| .highslide-gallery ul li { | ||||
| 	display: block; | ||||
| 	position: relative; | ||||
| 	float: left; | ||||
| 	width: 106px; | ||||
| 	height: 106px; | ||||
| 	border: 1px solid silver; | ||||
| 	background: #ededed; | ||||
| 	margin: 2px; | ||||
| 	padding: 0; | ||||
| 	line-height: 0; | ||||
| 	overflow: hidden; | ||||
| } | ||||
| .highslide-gallery ul a { | ||||
| 	position: absolute; | ||||
| 	top: 50%; | ||||
| 	left: 50%; | ||||
| } | ||||
| .highslide-gallery ul img { | ||||
|  	position: relative; | ||||
| 	top: -50%; | ||||
| 	left: -50%; | ||||
| } | ||||
| html>/**/body .highslide-gallery ul li { | ||||
| 	display: table; | ||||
| 	text-align: center; | ||||
| } | ||||
| html>/**/body .highslide-gallery ul li { | ||||
| 	text-align: center; | ||||
| } | ||||
| html>/**/body .highslide-gallery ul a { | ||||
| 	position: static; | ||||
| 	display: table-cell; | ||||
| 	vertical-align: middle; | ||||
| } | ||||
| html>/**/body .highslide-gallery ul img { | ||||
| 	position: static; | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
| /* Controls for the galleries.											     */ | ||||
| /* Remove these if you are not using a gallery							     */ | ||||
| /*****************************************************************************/ | ||||
| .highslide-controls { | ||||
| 	width: 195px; | ||||
| 	height: 40px; | ||||
| 	background: url(graphics/controlbar-white.gif) 0 -90px no-repeat; | ||||
| 	margin: 20px 15px 10px 0; | ||||
| } | ||||
| .highslide-controls ul { | ||||
| 	position: relative; | ||||
| 	left: 15px; | ||||
| 	height: 40px; | ||||
| 	list-style: none; | ||||
| 	margin: 0; | ||||
| 	padding: 0; | ||||
| 	background: url(graphics/controlbar-white.gif) right -90px no-repeat; | ||||
|  | ||||
| } | ||||
| .highslide-controls li { | ||||
| 	float: left; | ||||
| 	padding: 5px 0; | ||||
| 	margin:0; | ||||
| 	list-style: none; | ||||
| } | ||||
| .highslide-controls a { | ||||
| 	background-image: url(graphics/controlbar-white.gif); | ||||
| 	display: block; | ||||
| 	float: left; | ||||
| 	height: 30px; | ||||
| 	width: 30px; | ||||
| 	outline: none; | ||||
| } | ||||
| .highslide-controls a.disabled { | ||||
| 	cursor: default; | ||||
| } | ||||
| .highslide-controls a.disabled span { | ||||
| 	cursor: default; | ||||
| } | ||||
| .highslide-controls a span { | ||||
| 	/* hide the text for these graphic buttons */ | ||||
| 	display: none; | ||||
| 	cursor: pointer; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* The CSS sprites for the controlbar - see http://www.google.com/search?q=css+sprites */ | ||||
| .highslide-controls .highslide-previous a { | ||||
| 	background-position: 0 0; | ||||
| } | ||||
| .highslide-controls .highslide-previous a:hover { | ||||
| 	background-position: 0 -30px; | ||||
| } | ||||
| .highslide-controls .highslide-previous a.disabled { | ||||
| 	background-position: 0 -60px !important; | ||||
| } | ||||
| .highslide-controls .highslide-play a { | ||||
| 	background-position: -30px 0; | ||||
| } | ||||
| .highslide-controls .highslide-play a:hover { | ||||
| 	background-position: -30px -30px; | ||||
| } | ||||
| .highslide-controls .highslide-play a.disabled { | ||||
| 	background-position: -30px -60px !important; | ||||
| } | ||||
| .highslide-controls .highslide-pause a { | ||||
| 	background-position: -60px 0; | ||||
| } | ||||
| .highslide-controls .highslide-pause a:hover { | ||||
| 	background-position: -60px -30px; | ||||
| } | ||||
| .highslide-controls .highslide-next a { | ||||
| 	background-position: -90px 0; | ||||
| } | ||||
| .highslide-controls .highslide-next a:hover { | ||||
| 	background-position: -90px -30px; | ||||
| } | ||||
| .highslide-controls .highslide-next a.disabled { | ||||
| 	background-position: -90px -60px !important; | ||||
| } | ||||
| .highslide-controls .highslide-move a { | ||||
| 	background-position: -120px 0; | ||||
| } | ||||
| .highslide-controls .highslide-move a:hover { | ||||
| 	background-position: -120px -30px; | ||||
| } | ||||
| .highslide-controls .highslide-full-expand a { | ||||
| 	background-position: -150px 0; | ||||
| } | ||||
| .highslide-controls .highslide-full-expand a:hover { | ||||
| 	background-position: -150px -30px; | ||||
| } | ||||
| .highslide-controls .highslide-full-expand a.disabled { | ||||
| 	background-position: -150px -60px !important; | ||||
| } | ||||
| .highslide-controls .highslide-close a { | ||||
| 	background-position: -180px 0; | ||||
| } | ||||
| .highslide-controls .highslide-close a:hover { | ||||
| 	background-position: -180px -30px; | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
| /* Styles for the HTML popups											     */ | ||||
| /* Remove these if you are not using Highslide HTML						     */ | ||||
| /*****************************************************************************/ | ||||
| .highslide-maincontent { | ||||
| 	display: none; | ||||
| } | ||||
| .highslide-html { | ||||
| 	background-color: white; | ||||
| } | ||||
| .mobile .highslide-html { | ||||
| 	border: 1px solid silver; | ||||
| } | ||||
| .highslide-html-content { | ||||
| 	display: none; | ||||
| 	width: 400px; | ||||
| 	padding: 0 5px 5px 5px; | ||||
| } | ||||
| .highslide-header { | ||||
| 	padding-bottom: 5px; | ||||
| } | ||||
| .highslide-header ul { | ||||
| 	margin: 0; | ||||
| 	padding: 0; | ||||
| 	text-align: right; | ||||
| } | ||||
| .highslide-header ul li { | ||||
| 	display: inline; | ||||
| 	padding-left: 1em; | ||||
| } | ||||
| .highslide-header ul li.highslide-previous, .highslide-header ul li.highslide-next { | ||||
| 	display: none; | ||||
| } | ||||
| .highslide-header a { | ||||
| 	font-weight: bold; | ||||
| 	color: gray; | ||||
| 	text-transform: uppercase; | ||||
| 	text-decoration: none; | ||||
| } | ||||
| .highslide-header a:hover { | ||||
| 	color: black; | ||||
| } | ||||
| .highslide-header .highslide-move a { | ||||
| 	cursor: move; | ||||
| } | ||||
| .highslide-footer { | ||||
| 	height: 16px; | ||||
| } | ||||
| .highslide-footer .highslide-resize { | ||||
| 	display: block; | ||||
| 	float: right; | ||||
| 	margin-top: 5px; | ||||
| 	height: 11px; | ||||
| 	width: 11px; | ||||
| 	background: url(graphics/resize.gif) no-repeat; | ||||
| } | ||||
| .highslide-footer .highslide-resize span { | ||||
| 	display: none; | ||||
| } | ||||
| .highslide-body { | ||||
| } | ||||
| .highslide-resize { | ||||
| 	cursor: nw-resize; | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
| /* Styles for the Individual wrapper class names.							 */ | ||||
| /* See www.highslide.com/ref/hs.wrapperClassName							 */ | ||||
| /* You can safely remove the class name themes you don't use				 */ | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| /* hs.wrapperClassName = 'draggable-header' */ | ||||
| .draggable-header .highslide-header { | ||||
| 	height: 18px; | ||||
| 	border-bottom: 1px solid #dddddd; | ||||
| } | ||||
| .draggable-header .highslide-heading { | ||||
| 	position: absolute; | ||||
| 	margin: 2px 0.4em; | ||||
| } | ||||
|  | ||||
| .draggable-header .highslide-header .highslide-move { | ||||
| 	cursor: move; | ||||
| 	display: block; | ||||
| 	height: 16px; | ||||
| 	position: absolute; | ||||
| 	right: 24px; | ||||
| 	top: 0; | ||||
| 	width: 100%; | ||||
| 	z-index: 1; | ||||
| } | ||||
| .draggable-header .highslide-header .highslide-move * { | ||||
| 	display: none; | ||||
| } | ||||
| .draggable-header .highslide-header .highslide-close { | ||||
| 	position: absolute; | ||||
| 	right: 2px; | ||||
| 	top: 2px; | ||||
| 	z-index: 5; | ||||
| 	padding: 0; | ||||
| } | ||||
| .draggable-header .highslide-header .highslide-close a { | ||||
| 	display: block; | ||||
| 	height: 16px; | ||||
| 	width: 16px; | ||||
| 	background-image: url(graphics/closeX.png); | ||||
| } | ||||
| .draggable-header .highslide-header .highslide-close a:hover { | ||||
| 	background-position: 0 16px; | ||||
| } | ||||
| .draggable-header .highslide-header .highslide-close span { | ||||
| 	display: none; | ||||
| } | ||||
| .draggable-header .highslide-maincontent { | ||||
| 	padding-top: 1em; | ||||
| } | ||||
|  | ||||
| /* hs.wrapperClassName = 'titlebar' */ | ||||
| .titlebar .highslide-header { | ||||
| 	height: 18px; | ||||
| 	border-bottom: 1px solid #dddddd; | ||||
| } | ||||
| .titlebar .highslide-heading { | ||||
| 	position: absolute; | ||||
| 	width: 90%; | ||||
| 	margin: 1px 0 1px 5px; | ||||
| 	color: #666666; | ||||
| } | ||||
|  | ||||
| .titlebar .highslide-header .highslide-move { | ||||
| 	cursor: move; | ||||
| 	display: block; | ||||
| 	height: 16px; | ||||
| 	position: absolute; | ||||
| 	right: 24px; | ||||
| 	top: 0; | ||||
| 	width: 100%; | ||||
| 	z-index: 1; | ||||
| } | ||||
| .titlebar .highslide-header .highslide-move * { | ||||
| 	display: none; | ||||
| } | ||||
| .titlebar .highslide-header li { | ||||
| 	position: relative; | ||||
| 	top: 3px; | ||||
| 	z-index: 2; | ||||
| 	padding: 0 0 0 1em; | ||||
| } | ||||
| .titlebar .highslide-maincontent { | ||||
| 	padding-top: 1em; | ||||
| } | ||||
|  | ||||
| /* hs.wrapperClassName = 'no-footer' */ | ||||
| .no-footer .highslide-footer { | ||||
| 	display: none; | ||||
| } | ||||
|  | ||||
| /* hs.wrapperClassName = 'wide-border' */ | ||||
| .wide-border { | ||||
| 	background: white; | ||||
| } | ||||
| .wide-border .highslide-image { | ||||
| 	border-width: 10px; | ||||
| } | ||||
| .wide-border .highslide-caption { | ||||
| 	padding: 0 10px 10px 10px; | ||||
| } | ||||
|  | ||||
| /* hs.wrapperClassName = 'borderless' */ | ||||
| .borderless .highslide-image { | ||||
| 	border: none; | ||||
| } | ||||
| .borderless .highslide-caption { | ||||
| 	border-bottom: 1px solid white; | ||||
| 	border-top: 1px solid white; | ||||
| 	background: silver; | ||||
| } | ||||
|  | ||||
| /* hs.wrapperClassName = 'outer-glow' */ | ||||
| .outer-glow { | ||||
| 	background: #444; | ||||
| } | ||||
| .outer-glow .highslide-image { | ||||
| 	border: 5px solid #444444; | ||||
| } | ||||
| .outer-glow .highslide-caption { | ||||
| 	border: 5px solid #444444; | ||||
| 	border-top: none; | ||||
| 	padding: 5px; | ||||
| 	background-color: gray; | ||||
| } | ||||
|  | ||||
| /* hs.wrapperClassName = 'colored-border' */ | ||||
| .colored-border { | ||||
| 	background: white; | ||||
| } | ||||
| .colored-border .highslide-image { | ||||
| 	border: 2px solid green; | ||||
| } | ||||
| .colored-border .highslide-caption { | ||||
| 	border: 2px solid green; | ||||
| 	border-top: none; | ||||
| } | ||||
|  | ||||
| /* hs.wrapperClassName = 'dark' */ | ||||
| .dark { | ||||
| 	background: #111; | ||||
| } | ||||
| .dark .highslide-image { | ||||
| 	border-color: black black #202020 black; | ||||
| 	background: gray; | ||||
| } | ||||
| .dark .highslide-caption { | ||||
| 	color: white; | ||||
| 	background: #111; | ||||
| } | ||||
| .dark .highslide-controls, | ||||
| .dark .highslide-controls ul, | ||||
| .dark .highslide-controls a { | ||||
| 	background-image: url(graphics/controlbar-black-border.gif); | ||||
| } | ||||
|  | ||||
| /* hs.wrapperClassName = 'floating-caption' */ | ||||
| .floating-caption .highslide-caption { | ||||
| 	position: absolute; | ||||
| 	padding: 1em 0 0 0; | ||||
| 	background: none; | ||||
| 	color: white; | ||||
| 	border: none; | ||||
| 	font-weight: bold; | ||||
| } | ||||
|  | ||||
| /* hs.wrapperClassName = 'controls-in-heading' */ | ||||
| .controls-in-heading .highslide-heading { | ||||
| 	color: gray; | ||||
| 	font-weight: bold; | ||||
| 	height: 20px; | ||||
| 	overflow: hidden; | ||||
| 	cursor: default; | ||||
| 	padding: 0 0 0 22px; | ||||
| 	margin: 0; | ||||
| 	background: url(graphics/icon.gif) no-repeat 0 1px; | ||||
| } | ||||
| .controls-in-heading .highslide-controls { | ||||
| 	width: 105px; | ||||
| 	height: 20px; | ||||
| 	position: relative; | ||||
| 	margin: 0; | ||||
| 	top: -23px; | ||||
| 	left: 7px; | ||||
| 	background: none; | ||||
| } | ||||
| .controls-in-heading .highslide-controls ul { | ||||
| 	position: static; | ||||
| 	height: 20px; | ||||
| 	background: none; | ||||
| } | ||||
| .controls-in-heading .highslide-controls li { | ||||
| 	padding: 0; | ||||
| } | ||||
| .controls-in-heading .highslide-controls a { | ||||
| 	background-image: url(graphics/controlbar-white-small.gif); | ||||
| 	height: 20px; | ||||
| 	width: 20px; | ||||
| } | ||||
|  | ||||
| .controls-in-heading .highslide-controls .highslide-move { | ||||
| 	display: none; | ||||
| } | ||||
|  | ||||
| .controls-in-heading .highslide-controls .highslide-previous a { | ||||
| 	background-position: 0 0; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-previous a:hover { | ||||
| 	background-position: 0 -20px; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-previous a.disabled { | ||||
| 	background-position: 0 -40px !important; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-play a { | ||||
| 	background-position: -20px 0; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-play a:hover { | ||||
| 	background-position: -20px -20px; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-play a.disabled { | ||||
| 	background-position: -20px -40px !important; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-pause a { | ||||
| 	background-position: -40px 0; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-pause a:hover { | ||||
| 	background-position: -40px -20px; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-next a { | ||||
| 	background-position: -60px 0; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-next a:hover { | ||||
| 	background-position: -60px -20px; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-next a.disabled { | ||||
| 	background-position: -60px -40px !important; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-full-expand a { | ||||
| 	background-position: -100px 0; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-full-expand a:hover { | ||||
| 	background-position: -100px -20px; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-full-expand a.disabled { | ||||
| 	background-position: -100px -40px !important; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-close a { | ||||
| 	background-position: -120px 0; | ||||
| } | ||||
| .controls-in-heading .highslide-controls .highslide-close a:hover { | ||||
| 	background-position: -120px -20px; | ||||
| } | ||||
|  | ||||
| /*****************************************************************************/ | ||||
| /* Styles for text based controls.						                     */ | ||||
| /* You can safely remove this if you don't use text based controls			 */ | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| .text-controls .highslide-controls { | ||||
| 	width: auto; | ||||
| 	height: auto; | ||||
| 	margin: 0; | ||||
| 	text-align: center; | ||||
| 	background: none; | ||||
| } | ||||
| .text-controls ul { | ||||
| 	position: static; | ||||
| 	background: none; | ||||
| 	height: auto; | ||||
| 	left: 0; | ||||
| } | ||||
| .text-controls .highslide-move { | ||||
| 	display: none; | ||||
| } | ||||
| .text-controls li { | ||||
|     background-image: url(graphics/controlbar-text-buttons.png); | ||||
| 	background-position: right top !important; | ||||
| 	padding: 0; | ||||
| 	margin-left: 15px; | ||||
| 	display: block; | ||||
| 	width: auto; | ||||
| } | ||||
| .text-controls a { | ||||
|     background: url(graphics/controlbar-text-buttons.png) no-repeat; | ||||
|     background-position: left top !important; | ||||
|     position: relative; | ||||
|     left: -10px; | ||||
| 	display: block; | ||||
| 	width: auto; | ||||
| 	height: auto; | ||||
| 	text-decoration: none !important; | ||||
| } | ||||
| .text-controls a span { | ||||
| 	background: url(graphics/controlbar-text-buttons.png) no-repeat; | ||||
|     margin: 1px 2px 1px 10px; | ||||
| 	display: block; | ||||
|     min-width: 4em; | ||||
|     height: 18px; | ||||
|     line-height: 18px; | ||||
| 	padding: 1px 0 1px 18px; | ||||
|     color: #333; | ||||
| 	font-family: "Trebuchet MS", Arial, sans-serif; | ||||
| 	font-size: 12px; | ||||
| 	font-weight: bold; | ||||
| 	white-space: nowrap; | ||||
| } | ||||
| .text-controls .highslide-next { | ||||
| 	margin-right: 1em; | ||||
| } | ||||
| .text-controls .highslide-full-expand a span { | ||||
| 	min-width: 0; | ||||
| 	margin: 1px 0; | ||||
| 	padding: 1px 0 1px 10px; | ||||
| } | ||||
| .text-controls .highslide-close a span { | ||||
| 	min-width: 0; | ||||
| } | ||||
| .text-controls a:hover span { | ||||
| 	color: black; | ||||
| } | ||||
| .text-controls a.disabled span { | ||||
| 	color: #999; | ||||
| } | ||||
|  | ||||
| .text-controls .highslide-previous span { | ||||
| 	background-position: 0 -40px; | ||||
| } | ||||
| .text-controls .highslide-previous a.disabled { | ||||
| 	background-position: left top !important; | ||||
| } | ||||
| .text-controls .highslide-previous a.disabled span { | ||||
| 	background-position: 0 -140px; | ||||
| } | ||||
| .text-controls .highslide-play span { | ||||
| 	background-position: 0 -60px; | ||||
| } | ||||
| .text-controls .highslide-play a.disabled { | ||||
| 	background-position: left top !important; | ||||
| } | ||||
| .text-controls .highslide-play a.disabled span { | ||||
| 	background-position: 0 -160px; | ||||
| } | ||||
| .text-controls .highslide-pause span { | ||||
| 	background-position: 0 -80px; | ||||
| } | ||||
| .text-controls .highslide-next span { | ||||
| 	background-position: 0 -100px; | ||||
| } | ||||
| .text-controls .highslide-next a.disabled { | ||||
| 	background-position: left top !important; | ||||
| } | ||||
| .text-controls .highslide-next a.disabled span { | ||||
| 	background-position: 0 -200px; | ||||
| } | ||||
| .text-controls .highslide-full-expand span { | ||||
| 	background: none; | ||||
| } | ||||
| .text-controls .highslide-full-expand a.disabled { | ||||
| 	background-position: left top !important; | ||||
| } | ||||
| .text-controls .highslide-close span { | ||||
| 	background-position: 0 -120px; | ||||
| } | ||||
|  | ||||
|  | ||||
| /*****************************************************************************/ | ||||
| /* Styles for the thumbstrip.							                     */ | ||||
| /* See www.highslide.com/ref/hs.addSlideshow    							 */ | ||||
| /* You can safely remove this if you don't use a thumbstrip 				 */ | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| .highslide-thumbstrip { | ||||
| 	height: 100%; | ||||
| 	direction: ltr; | ||||
| } | ||||
| .highslide-thumbstrip div { | ||||
| 	overflow: hidden; | ||||
| } | ||||
| .highslide-thumbstrip table { | ||||
| 	position: relative; | ||||
| 	padding: 0; | ||||
| 	border-collapse: collapse; | ||||
| } | ||||
| .highslide-thumbstrip td { | ||||
| 	padding: 1px; | ||||
| 	/*text-align: center;*/ | ||||
| } | ||||
| .highslide-thumbstrip a { | ||||
| 	outline: none; | ||||
| } | ||||
| .highslide-thumbstrip img { | ||||
| 	display: block; | ||||
| 	border: 1px solid gray; | ||||
| 	margin: 0 auto; | ||||
| } | ||||
| .highslide-thumbstrip .highslide-active-anchor img { | ||||
| 	visibility: visible; | ||||
| } | ||||
| .highslide-thumbstrip .highslide-marker { | ||||
| 	position: absolute; | ||||
| 	width: 0; | ||||
| 	height: 0; | ||||
| 	border-width: 0; | ||||
| 	border-style: solid; | ||||
| 	border-color: transparent; /* change this to actual background color in highslide-ie6.css */ | ||||
| } | ||||
| .highslide-thumbstrip-horizontal div { | ||||
| 	width: auto; | ||||
| 	/* width: 100% breaks in small strips in IE */ | ||||
| } | ||||
| .highslide-thumbstrip-horizontal .highslide-scroll-up { | ||||
| 	display: none; | ||||
| 	position: absolute; | ||||
| 	top: 3px; | ||||
| 	left: 3px; | ||||
| 	width: 25px; | ||||
| 	height: 42px; | ||||
| } | ||||
| .highslide-thumbstrip-horizontal .highslide-scroll-up div { | ||||
| 	margin-bottom: 10px; | ||||
| 	cursor: pointer; | ||||
| 	background: url(graphics/scrollarrows.png) left center no-repeat; | ||||
| 	height: 42px; | ||||
| } | ||||
| .highslide-thumbstrip-horizontal .highslide-scroll-down { | ||||
| 	display: none; | ||||
| 	position: absolute; | ||||
| 	top: 3px; | ||||
| 	right: 3px; | ||||
| 	width: 25px; | ||||
| 	height: 42px; | ||||
| } | ||||
| .highslide-thumbstrip-horizontal .highslide-scroll-down div { | ||||
| 	margin-bottom: 10px; | ||||
| 	cursor: pointer; | ||||
| 	background: url(graphics/scrollarrows.png) center right no-repeat; | ||||
| 	height: 42px; | ||||
| } | ||||
| .highslide-thumbstrip-horizontal table { | ||||
| 	margin: 2px 0 10px 0; | ||||
| } | ||||
| .highslide-viewport .highslide-thumbstrip-horizontal table { | ||||
| 	margin-left: 10px; | ||||
| } | ||||
| .highslide-thumbstrip-horizontal img { | ||||
| 	width: auto; | ||||
| 	height: 40px; | ||||
| } | ||||
| .highslide-thumbstrip-horizontal .highslide-marker { | ||||
| 	top: 47px; | ||||
| 	border-left-width: 6px; | ||||
| 	border-right-width: 6px; | ||||
| 	border-bottom: 6px solid gray; | ||||
| } | ||||
| .highslide-viewport .highslide-thumbstrip-horizontal .highslide-marker { | ||||
| 	margin-left: 10px; | ||||
| } | ||||
| .dark .highslide-thumbstrip-horizontal .highslide-marker, .highslide-viewport .highslide-thumbstrip-horizontal .highslide-marker { | ||||
| 	border-bottom-color: white !important; | ||||
| } | ||||
|  | ||||
| .highslide-thumbstrip-vertical-overlay { | ||||
| 	overflow: hidden !important; | ||||
| } | ||||
| .highslide-thumbstrip-vertical div { | ||||
| 	height: 100%; | ||||
| } | ||||
| .highslide-thumbstrip-vertical a { | ||||
| 	display: block; | ||||
| } | ||||
| .highslide-thumbstrip-vertical .highslide-scroll-up { | ||||
| 	display: none; | ||||
| 	position: absolute; | ||||
| 	top: 0; | ||||
| 	left: 0; | ||||
| 	width: 100%; | ||||
| 	height: 25px; | ||||
| } | ||||
| .highslide-thumbstrip-vertical .highslide-scroll-up div { | ||||
| 	margin-left: 10px; | ||||
| 	cursor: pointer; | ||||
| 	background: url(graphics/scrollarrows.png) top center no-repeat; | ||||
| 	height: 25px; | ||||
| } | ||||
| .highslide-thumbstrip-vertical .highslide-scroll-down { | ||||
| 	display: none; | ||||
| 	position: absolute; | ||||
| 	bottom: 0; | ||||
| 	left: 0; | ||||
| 	width: 100%; | ||||
| 	height: 25px; | ||||
| } | ||||
| .highslide-thumbstrip-vertical .highslide-scroll-down div { | ||||
| 	margin-left: 10px; | ||||
| 	cursor: pointer; | ||||
| 	background: url(graphics/scrollarrows.png) bottom center no-repeat; | ||||
| 	height: 25px; | ||||
| } | ||||
| .highslide-thumbstrip-vertical table { | ||||
| 	margin: 10px 0 0 10px; | ||||
| } | ||||
| .highslide-thumbstrip-vertical img { | ||||
| 	width: 60px; /* t=5481 */ | ||||
| } | ||||
| .highslide-thumbstrip-vertical .highslide-marker { | ||||
| 	left: 0; | ||||
| 	margin-top: 8px; | ||||
| 	border-top-width: 6px; | ||||
| 	border-bottom-width: 6px; | ||||
| 	border-left: 6px solid gray; | ||||
| } | ||||
| .dark .highslide-thumbstrip-vertical .highslide-marker, .highslide-viewport .highslide-thumbstrip-vertical .highslide-marker { | ||||
| 	border-left-color: white; | ||||
| } | ||||
|  | ||||
| .highslide-viewport .highslide-thumbstrip-float { | ||||
| 	overflow: auto; | ||||
| } | ||||
| .highslide-thumbstrip-float ul { | ||||
| 	margin: 2px 0; | ||||
| 	padding: 0; | ||||
| } | ||||
| .highslide-thumbstrip-float li { | ||||
| 	display: block; | ||||
| 	height: 60px; | ||||
| 	margin: 0 2px; | ||||
| 	list-style: none; | ||||
| 	float: left; | ||||
| } | ||||
| .highslide-thumbstrip-float img { | ||||
| 	display: inline; | ||||
| 	border-color: silver; | ||||
| 	max-height: 56px; | ||||
| } | ||||
| .highslide-thumbstrip-float .highslide-active-anchor img { | ||||
| 	border-color: black; | ||||
| } | ||||
| .highslide-thumbstrip-float .highslide-scroll-up div, .highslide-thumbstrip-float .highslide-scroll-down div { | ||||
| 	display: none; | ||||
| } | ||||
| .highslide-thumbstrip-float .highslide-marker { | ||||
| 	display: none; | ||||
| } | ||||
							
								
								
									
										53
									
								
								public/assets/javascript/highcharts-more.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,53 @@ | ||||
| /* | ||||
|  Highcharts JS v4.0.3 (2014-07-03) | ||||
|  | ||||
|  (c) 2009-2014 Torstein Honsi | ||||
|  | ||||
|  License: www.highcharts.com/license | ||||
| */ | ||||
| (function(l,C){function K(a,b,c){this.init.call(this,a,b,c)}var P=l.arrayMin,Q=l.arrayMax,s=l.each,F=l.extend,q=l.merge,R=l.map,o=l.pick,x=l.pInt,p=l.getOptions().plotOptions,g=l.seriesTypes,v=l.extendClass,L=l.splat,r=l.wrap,M=l.Axis,y=l.Tick,H=l.Point,S=l.Pointer,T=l.CenteredSeriesMixin,z=l.TrackerMixin,t=l.Series,w=Math,D=w.round,A=w.floor,N=w.max,U=l.Color,u=function(){};F(K.prototype,{init:function(a,b,c){var d=this,e=d.defaultOptions;d.chart=b;if(b.angular)e.background={};d.options=a=q(e,a); | ||||
| (a=a.background)&&s([].concat(L(a)).reverse(),function(a){var b=a.backgroundColor,a=q(d.defaultBackgroundOptions,a);if(b)a.backgroundColor=b;a.color=a.backgroundColor;c.options.plotBands.unshift(a)})},defaultOptions:{center:["50%","50%"],size:"85%",startAngle:0},defaultBackgroundOptions:{shape:"circle",borderWidth:1,borderColor:"silver",backgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,"#FFF"],[1,"#DDD"]]},from:-Number.MAX_VALUE,innerRadius:0,to:Number.MAX_VALUE,outerRadius:"105%"}}); | ||||
| var G=M.prototype,y=y.prototype,V={getOffset:u,redraw:function(){this.isDirty=!1},render:function(){this.isDirty=!1},setScale:u,setCategories:u,setTitle:u},O={isRadial:!0,defaultRadialGaugeOptions:{labels:{align:"center",x:0,y:null},minorGridLineWidth:0,minorTickInterval:"auto",minorTickLength:10,minorTickPosition:"inside",minorTickWidth:1,tickLength:10,tickPosition:"inside",tickWidth:2,title:{rotation:0},zIndex:2},defaultRadialXOptions:{gridLineWidth:1,labels:{align:null,distance:15,x:0,y:null}, | ||||
| maxPadding:0,minPadding:0,showLastLabel:!1,tickLength:0},defaultRadialYOptions:{gridLineInterpolation:"circle",labels:{align:"right",x:-3,y:-2},showLastLabel:!1,title:{x:4,text:null,rotation:90}},setOptions:function(a){a=this.options=q(this.defaultOptions,this.defaultRadialOptions,a);if(!a.plotBands)a.plotBands=[]},getOffset:function(){G.getOffset.call(this);this.chart.axisOffset[this.side]=0;this.center=this.pane.center=T.getCenter.call(this.pane)},getLinePath:function(a,b){var c=this.center,b=o(b, | ||||
| c[2]/2-this.offset);return this.chart.renderer.symbols.arc(this.left+c[0],this.top+c[1],b,b,{start:this.startAngleRad,end:this.endAngleRad,open:!0,innerR:0})},setAxisTranslation:function(){G.setAxisTranslation.call(this);if(this.center)this.transA=this.isCircular?(this.endAngleRad-this.startAngleRad)/(this.max-this.min||1):this.center[2]/2/(this.max-this.min||1),this.minPixelPadding=this.isXAxis?this.transA*this.minPointOffset:0},beforeSetTickPositions:function(){this.autoConnect&&(this.max+=this.categories&& | ||||
| 1||this.pointRange||this.closestPointRange||0)},setAxisSize:function(){G.setAxisSize.call(this);if(this.isRadial){this.center=this.pane.center=l.CenteredSeriesMixin.getCenter.call(this.pane);if(this.isCircular)this.sector=this.endAngleRad-this.startAngleRad;this.len=this.width=this.height=this.center[2]*o(this.sector,1)/2}},getPosition:function(a,b){return this.postTranslate(this.isCircular?this.translate(a):0,o(this.isCircular?b:this.translate(a),this.center[2]/2)-this.offset)},postTranslate:function(a, | ||||
| b){var c=this.chart,d=this.center,a=this.startAngleRad+a;return{x:c.plotLeft+d[0]+Math.cos(a)*b,y:c.plotTop+d[1]+Math.sin(a)*b}},getPlotBandPath:function(a,b,c){var d=this.center,e=this.startAngleRad,f=d[2]/2,h=[o(c.outerRadius,"100%"),c.innerRadius,o(c.thickness,10)],j=/%$/,k,m=this.isCircular;this.options.gridLineInterpolation==="polygon"?d=this.getPlotLinePath(a).concat(this.getPlotLinePath(b,!0)):(m||(h[0]=this.translate(a),h[1]=this.translate(b)),h=R(h,function(a){j.test(a)&&(a=x(a,10)*f/100); | ||||
| return a}),c.shape==="circle"||!m?(a=-Math.PI/2,b=Math.PI*1.5,k=!0):(a=e+this.translate(a),b=e+this.translate(b)),d=this.chart.renderer.symbols.arc(this.left+d[0],this.top+d[1],h[0],h[0],{start:a,end:b,innerR:o(h[1],h[0]-h[2]),open:k}));return d},getPlotLinePath:function(a,b){var c=this,d=c.center,e=c.chart,f=c.getPosition(a),h,j,k;c.isCircular?k=["M",d[0]+e.plotLeft,d[1]+e.plotTop,"L",f.x,f.y]:c.options.gridLineInterpolation==="circle"?(a=c.translate(a))&&(k=c.getLinePath(0,a)):(s(e.xAxis,function(a){a.pane=== | ||||
| c.pane&&(h=a)}),k=[],a=c.translate(a),d=h.tickPositions,h.autoConnect&&(d=d.concat([d[0]])),b&&(d=[].concat(d).reverse()),s(d,function(f,c){j=h.getPosition(f,a);k.push(c?"L":"M",j.x,j.y)}));return k},getTitlePosition:function(){var a=this.center,b=this.chart,c=this.options.title;return{x:b.plotLeft+a[0]+(c.x||0),y:b.plotTop+a[1]-{high:0.5,middle:0.25,low:0}[c.align]*a[2]+(c.y||0)}}};r(G,"init",function(a,b,c){var i;var d=b.angular,e=b.polar,f=c.isX,h=d&&f,j,k;k=b.options;var m=c.pane||0;if(d){if(F(this, | ||||
| h?V:O),j=!f)this.defaultRadialOptions=this.defaultRadialGaugeOptions}else if(e)F(this,O),this.defaultRadialOptions=(j=f)?this.defaultRadialXOptions:q(this.defaultYAxisOptions,this.defaultRadialYOptions);a.call(this,b,c);if(!h&&(d||e)){a=this.options;if(!b.panes)b.panes=[];this.pane=(i=b.panes[m]=b.panes[m]||new K(L(k.pane)[m],b,this),m=i);m=m.options;b.inverted=!1;k.chart.zoomType=null;this.startAngleRad=b=(m.startAngle-90)*Math.PI/180;this.endAngleRad=k=(o(m.endAngle,m.startAngle+360)-90)*Math.PI/ | ||||
| 180;this.offset=a.offset||0;if((this.isCircular=j)&&c.max===C&&k-b===2*Math.PI)this.autoConnect=!0}});r(y,"getPosition",function(a,b,c,d,e){var f=this.axis;return f.getPosition?f.getPosition(c):a.call(this,b,c,d,e)});r(y,"getLabelPosition",function(a,b,c,d,e,f,h,j,k){var m=this.axis,i=f.y,n=f.align,g=(m.translate(this.pos)+m.startAngleRad+Math.PI/2)/Math.PI*180%360;m.isRadial?(a=m.getPosition(this.pos,m.center[2]/2+o(f.distance,-25)),f.rotation==="auto"?d.attr({rotation:g}):i===null&&(i=m.chart.renderer.fontMetrics(d.styles.fontSize).b- | ||||
| d.getBBox().height/2),n===null&&(n=m.isCircular?g>20&&g<160?"left":g>200&&g<340?"right":"center":"center",d.attr({align:n})),a.x+=f.x,a.y+=i):a=a.call(this,b,c,d,e,f,h,j,k);return a});r(y,"getMarkPath",function(a,b,c,d,e,f,h){var j=this.axis;j.isRadial?(a=j.getPosition(this.pos,j.center[2]/2+d),b=["M",b,c,"L",a.x,a.y]):b=a.call(this,b,c,d,e,f,h);return b});p.arearange=q(p.area,{lineWidth:1,marker:null,threshold:null,tooltip:{pointFormat:'<span style="color:{series.color}">●</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'}, | ||||
| trackByArea:!0,dataLabels:{align:null,verticalAlign:null,xLow:0,xHigh:0,yLow:0,yHigh:0},states:{hover:{halo:!1}}});g.arearange=v(g.area,{type:"arearange",pointArrayMap:["low","high"],toYData:function(a){return[a.low,a.high]},pointValKey:"low",getSegments:function(){var a=this;s(a.points,function(b){if(!a.options.connectNulls&&(b.low===null||b.high===null))b.y=null;else if(b.low===null&&b.high!==null)b.y=b.high});t.prototype.getSegments.call(this)},translate:function(){var a=this.yAxis;g.area.prototype.translate.apply(this); | ||||
| s(this.points,function(b){var c=b.low,d=b.high,e=b.plotY;d===null&&c===null?b.y=null:c===null?(b.plotLow=b.plotY=null,b.plotHigh=a.translate(d,0,1,0,1)):d===null?(b.plotLow=e,b.plotHigh=null):(b.plotLow=e,b.plotHigh=a.translate(d,0,1,0,1))})},getSegmentPath:function(a){var b,c=[],d=a.length,e=t.prototype.getSegmentPath,f,h;h=this.options;var j=h.step;for(b=HighchartsAdapter.grep(a,function(a){return a.plotLow!==null});d--;)f=a[d],f.plotHigh!==null&&c.push({plotX:f.plotX,plotY:f.plotHigh});a=e.call(this, | ||||
| b);if(j)j===!0&&(j="left"),h.step={left:"right",center:"center",right:"left"}[j];c=e.call(this,c);h.step=j;h=[].concat(a,c);c[0]="L";this.areaPath=this.areaPath.concat(a,c);return h},drawDataLabels:function(){var a=this.data,b=a.length,c,d=[],e=t.prototype,f=this.options.dataLabels,h=f.align,j,k=this.chart.inverted;if(f.enabled||this._hasPointLabels){for(c=b;c--;)if(j=a[c],j.y=j.high,j._plotY=j.plotY,j.plotY=j.plotHigh,d[c]=j.dataLabel,j.dataLabel=j.dataLabelUpper,j.below=!1,k){if(!h)f.align="left"; | ||||
| f.x=f.xHigh}else f.y=f.yHigh;e.drawDataLabels&&e.drawDataLabels.apply(this,arguments);for(c=b;c--;)if(j=a[c],j.dataLabelUpper=j.dataLabel,j.dataLabel=d[c],j.y=j.low,j.plotY=j._plotY,j.below=!0,k){if(!h)f.align="right";f.x=f.xLow}else f.y=f.yLow;e.drawDataLabels&&e.drawDataLabels.apply(this,arguments)}f.align=h},alignDataLabel:function(){g.column.prototype.alignDataLabel.apply(this,arguments)},getSymbol:u,drawPoints:u});p.areasplinerange=q(p.arearange);g.areasplinerange=v(g.arearange,{type:"areasplinerange", | ||||
| getPointSpline:g.spline.prototype.getPointSpline});(function(){var a=g.column.prototype;p.columnrange=q(p.column,p.arearange,{lineWidth:1,pointRange:null});g.columnrange=v(g.arearange,{type:"columnrange",translate:function(){var b=this,c=b.yAxis,d;a.translate.apply(b);s(b.points,function(a){var f=a.shapeArgs,h=b.options.minPointLength,j;a.tooltipPos=null;a.plotHigh=d=c.translate(a.high,0,1,0,1);a.plotLow=a.plotY;j=d;a=a.plotY-d;a<h&&(h-=a,a+=h,j-=h/2);f.height=a;f.y=j})},trackerGroups:["group","dataLabelsGroup"], | ||||
| drawGraph:u,pointAttrToOptions:a.pointAttrToOptions,drawPoints:a.drawPoints,drawTracker:a.drawTracker,animate:a.animate,getColumnMetrics:a.getColumnMetrics})})();p.gauge=q(p.line,{dataLabels:{enabled:!0,defer:!1,y:15,borderWidth:1,borderColor:"silver",borderRadius:3,crop:!1,style:{fontWeight:"bold"},verticalAlign:"top",zIndex:2},dial:{},pivot:{},tooltip:{headerFormat:""},showInLegend:!1});z={type:"gauge",pointClass:v(H,{setState:function(a){this.state=a}}),angular:!0,drawGraph:u,fixedBox:!0,forceDL:!0, | ||||
| trackerGroups:["group","dataLabelsGroup"],translate:function(){var a=this.yAxis,b=this.options,c=a.center;this.generatePoints();s(this.points,function(d){var e=q(b.dial,d.dial),f=x(o(e.radius,80))*c[2]/200,h=x(o(e.baseLength,70))*f/100,j=x(o(e.rearLength,10))*f/100,k=e.baseWidth||3,m=e.topWidth||1,i=b.overshoot,n=a.startAngleRad+a.translate(d.y,null,null,null,!0);i&&typeof i==="number"?(i=i/180*Math.PI,n=Math.max(a.startAngleRad-i,Math.min(a.endAngleRad+i,n))):b.wrap===!1&&(n=Math.max(a.startAngleRad, | ||||
| Math.min(a.endAngleRad,n)));n=n*180/Math.PI;d.shapeType="path";d.shapeArgs={d:e.path||["M",-j,-k/2,"L",h,-k/2,f,-m/2,f,m/2,h,k/2,-j,k/2,"z"],translateX:c[0],translateY:c[1],rotation:n};d.plotX=c[0];d.plotY=c[1]})},drawPoints:function(){var a=this,b=a.yAxis.center,c=a.pivot,d=a.options,e=d.pivot,f=a.chart.renderer;s(a.points,function(c){var b=c.graphic,k=c.shapeArgs,e=k.d,i=q(d.dial,c.dial);b?(b.animate(k),k.d=e):c.graphic=f[c.shapeType](k).attr({stroke:i.borderColor||"none","stroke-width":i.borderWidth|| | ||||
| 0,fill:i.backgroundColor||"black",rotation:k.rotation}).add(a.group)});c?c.animate({translateX:b[0],translateY:b[1]}):a.pivot=f.circle(0,0,o(e.radius,5)).attr({"stroke-width":e.borderWidth||0,stroke:e.borderColor||"silver",fill:e.backgroundColor||"black"}).translate(b[0],b[1]).add(a.group)},animate:function(a){var b=this;if(!a)s(b.points,function(a){var d=a.graphic;d&&(d.attr({rotation:b.yAxis.startAngleRad*180/Math.PI}),d.animate({rotation:a.shapeArgs.rotation},b.options.animation))}),b.animate= | ||||
| null},render:function(){this.group=this.plotGroup("group","series",this.visible?"visible":"hidden",this.options.zIndex,this.chart.seriesGroup);t.prototype.render.call(this);this.group.clip(this.chart.clipRect)},setData:function(a,b){t.prototype.setData.call(this,a,!1);this.processData();this.generatePoints();o(b,!0)&&this.chart.redraw()},drawTracker:z&&z.drawTrackerPoint};g.gauge=v(g.line,z);p.boxplot=q(p.column,{fillColor:"#FFFFFF",lineWidth:1,medianWidth:2,states:{hover:{brightness:-0.3}},threshold:null, | ||||
| tooltip:{pointFormat:'<span style="color:{series.color}">●</span> <b> {series.name}</b><br/>Maximum: {point.high}<br/>Upper quartile: {point.q3}<br/>Median: {point.median}<br/>Lower quartile: {point.q1}<br/>Minimum: {point.low}<br/>'},whiskerLength:"50%",whiskerWidth:2});g.boxplot=v(g.column,{type:"boxplot",pointArrayMap:["low","q1","median","q3","high"],toYData:function(a){return[a.low,a.q1,a.median,a.q3,a.high]},pointValKey:"high",pointAttrToOptions:{fill:"fillColor",stroke:"color","stroke-width":"lineWidth"}, | ||||
| drawDataLabels:u,translate:function(){var a=this.yAxis,b=this.pointArrayMap;g.column.prototype.translate.apply(this);s(this.points,function(c){s(b,function(b){c[b]!==null&&(c[b+"Plot"]=a.translate(c[b],0,1,0,1))})})},drawPoints:function(){var a=this,b=a.points,c=a.options,d=a.chart.renderer,e,f,h,j,k,m,i,n,g,l,p,I,r,q,J,u,v,t,w,x,z,y,E=a.doQuartiles!==!1,B=parseInt(a.options.whiskerLength,10)/100;s(b,function(b){g=b.graphic;z=b.shapeArgs;p={};q={};u={};y=b.color||a.color;if(b.plotY!==C)if(e=b.pointAttr[b.selected? | ||||
| "selected":""],v=z.width,t=A(z.x),w=t+v,x=D(v/2),f=A(E?b.q1Plot:b.lowPlot),h=A(E?b.q3Plot:b.lowPlot),j=A(b.highPlot),k=A(b.lowPlot),p.stroke=b.stemColor||c.stemColor||y,p["stroke-width"]=o(b.stemWidth,c.stemWidth,c.lineWidth),p.dashstyle=b.stemDashStyle||c.stemDashStyle,q.stroke=b.whiskerColor||c.whiskerColor||y,q["stroke-width"]=o(b.whiskerWidth,c.whiskerWidth,c.lineWidth),u.stroke=b.medianColor||c.medianColor||y,u["stroke-width"]=o(b.medianWidth,c.medianWidth,c.lineWidth),u["stroke-linecap"]="round", | ||||
| i=p["stroke-width"]%2/2,n=t+x+i,l=["M",n,h,"L",n,j,"M",n,f,"L",n,k],E&&(i=e["stroke-width"]%2/2,n=A(n)+i,f=A(f)+i,h=A(h)+i,t+=i,w+=i,I=["M",t,h,"L",t,f,"L",w,f,"L",w,h,"L",t,h,"z"]),B&&(i=q["stroke-width"]%2/2,j+=i,k+=i,r=["M",n-x*B,j,"L",n+x*B,j,"M",n-x*B,k,"L",n+x*B,k]),i=u["stroke-width"]%2/2,m=D(b.medianPlot)+i,J=["M",t,m,"L",w,m],g)b.stem.animate({d:l}),B&&b.whiskers.animate({d:r}),E&&b.box.animate({d:I}),b.medianShape.animate({d:J});else{b.graphic=g=d.g().add(a.group);b.stem=d.path(l).attr(p).add(g); | ||||
| if(B)b.whiskers=d.path(r).attr(q).add(g);if(E)b.box=d.path(I).attr(e).add(g);b.medianShape=d.path(J).attr(u).add(g)}})}});p.errorbar=q(p.boxplot,{color:"#000000",grouping:!1,linkedTo:":previous",tooltip:{pointFormat:'<span style="color:{series.color}">●</span> {series.name}: <b>{point.low}</b> - <b>{point.high}</b><br/>'},whiskerWidth:null});g.errorbar=v(g.boxplot,{type:"errorbar",pointArrayMap:["low","high"],toYData:function(a){return[a.low,a.high]},pointValKey:"high",doQuartiles:!1,drawDataLabels:g.arearange? | ||||
| g.arearange.prototype.drawDataLabels:u,getColumnMetrics:function(){return this.linkedParent&&this.linkedParent.columnMetrics||g.column.prototype.getColumnMetrics.call(this)}});p.waterfall=q(p.column,{lineWidth:1,lineColor:"#333",dashStyle:"dot",borderColor:"#333",states:{hover:{lineWidthPlus:0}}});g.waterfall=v(g.column,{type:"waterfall",upColorProp:"fill",pointArrayMap:["low","y"],pointValKey:"y",init:function(a,b){b.stacking=!0;g.column.prototype.init.call(this,a,b)},translate:function(){var a= | ||||
| this.yAxis,b,c,d,e,f,h,j,k,m,i;b=this.options.threshold;g.column.prototype.translate.apply(this);k=m=b;d=this.points;for(c=0,b=d.length;c<b;c++){e=d[c];f=e.shapeArgs;h=this.getStack(c);i=h.points[this.index+","+c];if(isNaN(e.y))e.y=this.yData[c];j=N(k,k+e.y)+i[0];f.y=a.translate(j,0,1);e.isSum?(f.y=a.translate(i[1],0,1),f.height=a.translate(i[0],0,1)-f.y):e.isIntermediateSum?(f.y=a.translate(i[1],0,1),f.height=a.translate(m,0,1)-f.y,m=i[1]):k+=h.total;f.height<0&&(f.y+=f.height,f.height*=-1);e.plotY= | ||||
| f.y=D(f.y)-this.borderWidth%2/2;f.height=N(D(f.height),0.001);e.yBottom=f.y+f.height;f=e.plotY+(e.negative?f.height:0);this.chart.inverted?e.tooltipPos[0]=a.len-f:e.tooltipPos[1]=f}},processData:function(a){var b=this.yData,c=this.points,d,e=b.length,f,h,j,k,m,i;h=f=j=k=this.options.threshold||0;for(i=0;i<e;i++)m=b[i],d=c&&c[i]?c[i]:{},m==="sum"||d.isSum?b[i]=h:m==="intermediateSum"||d.isIntermediateSum?b[i]=f:(h+=m,f+=m),j=Math.min(h,j),k=Math.max(h,k);t.prototype.processData.call(this,a);this.dataMin= | ||||
| j;this.dataMax=k},toYData:function(a){if(a.isSum)return"sum";else if(a.isIntermediateSum)return"intermediateSum";return a.y},getAttribs:function(){g.column.prototype.getAttribs.apply(this,arguments);var a=this.options,b=a.states,c=a.upColor||this.color,a=l.Color(c).brighten(0.1).get(),d=q(this.pointAttr),e=this.upColorProp;d[""][e]=c;d.hover[e]=b.hover.upColor||a;d.select[e]=b.select.upColor||c;s(this.points,function(a){if(a.y>0&&!a.color)a.pointAttr=d,a.color=c})},getGraphPath:function(){var a=this.data, | ||||
| b=a.length,c=D(this.options.lineWidth+this.borderWidth)%2/2,d=[],e,f,h;for(h=1;h<b;h++)f=a[h].shapeArgs,e=a[h-1].shapeArgs,f=["M",e.x+e.width,e.y+c,"L",f.x,e.y+c],a[h-1].y<0&&(f[2]+=e.height,f[5]+=e.height),d=d.concat(f);return d},getExtremes:u,getStack:function(a){var b=this.yAxis.stacks,c=this.stackKey;this.processedYData[a]<this.options.threshold&&(c="-"+c);return b[c][a]},drawGraph:t.prototype.drawGraph});p.bubble=q(p.scatter,{dataLabels:{formatter:function(){return this.point.z},inside:!0,style:{color:"white", | ||||
| textShadow:"0px 0px 3px black"},verticalAlign:"middle"},marker:{lineColor:null,lineWidth:1},minSize:8,maxSize:"20%",states:{hover:{halo:{size:5}}},tooltip:{pointFormat:"({point.x}, {point.y}), Size: {point.z}"},turboThreshold:0,zThreshold:0});z=v(H,{haloPath:function(){return H.prototype.haloPath.call(this,this.shapeArgs.r+this.series.options.states.hover.halo.size)}});g.bubble=v(g.scatter,{type:"bubble",pointClass:z,pointArrayMap:["y","z"],parallelArrays:["x","y","z"],trackerGroups:["group","dataLabelsGroup"], | ||||
| bubblePadding:!0,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor"},applyOpacity:function(a){var b=this.options.marker,c=o(b.fillOpacity,0.5),a=a||b.fillColor||this.color;c!==1&&(a=U(a).setOpacity(c).get("rgba"));return a},convertAttribs:function(){var a=t.prototype.convertAttribs.apply(this,arguments);a.fill=this.applyOpacity(a.fill);return a},getRadii:function(a,b,c,d){var e,f,h,j=this.zData,k=[],m=this.options.sizeBy!=="width";for(f=0,e=j.length;f<e;f++)h=b-a,h= | ||||
| h>0?(j[f]-a)/(b-a):0.5,m&&h>=0&&(h=Math.sqrt(h)),k.push(w.ceil(c+h*(d-c))/2);this.radii=k},animate:function(a){var b=this.options.animation;if(!a)s(this.points,function(a){var d=a.graphic,a=a.shapeArgs;d&&a&&(d.attr("r",1),d.animate({r:a.r},b))}),this.animate=null},translate:function(){var a,b=this.data,c,d,e=this.radii;g.scatter.prototype.translate.call(this);for(a=b.length;a--;)c=b[a],d=e?e[a]:0,c.negative=c.z<(this.options.zThreshold||0),d>=this.minPxSize/2?(c.shapeType="circle",c.shapeArgs={x:c.plotX, | ||||
| y:c.plotY,r:d},c.dlBox={x:c.plotX-d,y:c.plotY-d,width:2*d,height:2*d}):c.shapeArgs=c.plotY=c.dlBox=C},drawLegendSymbol:function(a,b){var c=x(a.itemStyle.fontSize)/2;b.legendSymbol=this.chart.renderer.circle(c,a.baseline-c,c).attr({zIndex:3}).add(b.legendGroup);b.legendSymbol.isMarker=!0},drawPoints:g.column.prototype.drawPoints,alignDataLabel:g.column.prototype.alignDataLabel});M.prototype.beforePadding=function(){var a=this,b=this.len,c=this.chart,d=0,e=b,f=this.isXAxis,h=f?"xData":"yData",j=this.min, | ||||
| k={},m=w.min(c.plotWidth,c.plotHeight),i=Number.MAX_VALUE,n=-Number.MAX_VALUE,g=this.max-j,l=b/g,p=[];this.tickPositions&&(s(this.series,function(b){var h=b.options;if(b.bubblePadding&&(b.visible||!c.options.chart.ignoreHiddenSeries))if(a.allowZoomOutside=!0,p.push(b),f)s(["minSize","maxSize"],function(a){var b=h[a],f=/%$/.test(b),b=x(b);k[a]=f?m*b/100:b}),b.minPxSize=k.minSize,b=b.zData,b.length&&(i=o(h.zMin,w.min(i,w.max(P(b),h.displayNegative===!1?h.zThreshold:-Number.MAX_VALUE))),n=o(h.zMax,w.max(n, | ||||
| Q(b))))}),s(p,function(a){var b=a[h],c=b.length,m;f&&a.getRadii(i,n,k.minSize,k.maxSize);if(g>0)for(;c--;)typeof b[c]==="number"&&(m=a.radii[c],d=Math.min((b[c]-j)*l-m,d),e=Math.max((b[c]-j)*l+m,e))}),p.length&&g>0&&o(this.options.min,this.userMin)===C&&o(this.options.max,this.userMax)===C&&(e-=b,l*=(b+d-e)/b,this.min+=d/l,this.max+=e/l))};(function(){function a(a,b,c){a.call(this,b,c);if(this.chart.polar)this.closeSegment=function(a){var b=this.xAxis.center;a.push("L",b[0],b[1])},this.closedStacks= | ||||
| !0}function b(a,b){var c=this.chart,d=this.options.animation,e=this.group,i=this.markerGroup,n=this.xAxis.center,g=c.plotLeft,l=c.plotTop;if(c.polar){if(c.renderer.isSVG)d===!0&&(d={}),b?(c={translateX:n[0]+g,translateY:n[1]+l,scaleX:0.001,scaleY:0.001},e.attr(c),i&&i.attr(c)):(c={translateX:g,translateY:l,scaleX:1,scaleY:1},e.animate(c,d),i&&i.animate(c,d),this.animate=null)}else a.call(this,b)}var c=t.prototype,d=S.prototype,e;c.toXY=function(a){var b,c=this.chart,d=a.plotX;b=a.plotY;a.rectPlotX= | ||||
| d;a.rectPlotY=b;d=(d/Math.PI*180+this.xAxis.pane.options.startAngle)%360;d<0&&(d+=360);a.clientX=d;b=this.xAxis.postTranslate(a.plotX,this.yAxis.len-b);a.plotX=a.polarPlotX=b.x-c.plotLeft;a.plotY=a.polarPlotY=b.y-c.plotTop};c.orderTooltipPoints=function(a){if(this.chart.polar&&(a.sort(function(a,b){return a.clientX-b.clientX}),a[0]))a[0].wrappedClientX=a[0].clientX+360,a.push(a[0])};g.area&&r(g.area.prototype,"init",a);g.areaspline&&r(g.areaspline.prototype,"init",a);g.spline&&r(g.spline.prototype, | ||||
| "getPointSpline",function(a,b,c,d){var e,i,n,g,l,p,o;if(this.chart.polar){e=c.plotX;i=c.plotY;a=b[d-1];n=b[d+1];this.connectEnds&&(a||(a=b[b.length-2]),n||(n=b[1]));if(a&&n)g=a.plotX,l=a.plotY,b=n.plotX,p=n.plotY,g=(1.5*e+g)/2.5,l=(1.5*i+l)/2.5,n=(1.5*e+b)/2.5,o=(1.5*i+p)/2.5,b=Math.sqrt(Math.pow(g-e,2)+Math.pow(l-i,2)),p=Math.sqrt(Math.pow(n-e,2)+Math.pow(o-i,2)),g=Math.atan2(l-i,g-e),l=Math.atan2(o-i,n-e),o=Math.PI/2+(g+l)/2,Math.abs(g-o)>Math.PI/2&&(o-=Math.PI),g=e+Math.cos(o)*b,l=i+Math.sin(o)* | ||||
| b,n=e+Math.cos(Math.PI+o)*p,o=i+Math.sin(Math.PI+o)*p,c.rightContX=n,c.rightContY=o;d?(c=["C",a.rightContX||a.plotX,a.rightContY||a.plotY,g||e,l||i,e,i],a.rightContX=a.rightContY=null):c=["M",e,i]}else c=a.call(this,b,c,d);return c});r(c,"translate",function(a){a.call(this);if(this.chart.polar&&!this.preventPostTranslate)for(var a=this.points,b=a.length;b--;)this.toXY(a[b])});r(c,"getSegmentPath",function(a,b){var c=this.points;if(this.chart.polar&&this.options.connectEnds!==!1&&b[b.length-1]===c[c.length- | ||||
| 1]&&c[0].y!==null)this.connectEnds=!0,b=[].concat(b,[c[0]]);return a.call(this,b)});r(c,"animate",b);r(c,"setTooltipPoints",function(a,b){this.chart.polar&&F(this.xAxis,{tooltipLen:360});return a.call(this,b)});if(g.column)e=g.column.prototype,r(e,"animate",b),r(e,"translate",function(a){var b=this.xAxis,c=this.yAxis.len,d=b.center,e=b.startAngleRad,i=this.chart.renderer,g,l;this.preventPostTranslate=!0;a.call(this);if(b.isRadial){b=this.points;for(l=b.length;l--;)g=b[l],a=g.barX+e,g.shapeType="path", | ||||
| g.shapeArgs={d:i.symbols.arc(d[0],d[1],c-g.plotY,null,{start:a,end:a+g.pointWidth,innerR:c-o(g.yBottom,c)})},this.toXY(g),g.tooltipPos=[g.plotX,g.plotY],g.ttBelow=g.plotY>d[1]}}),r(e,"alignDataLabel",function(a,b,d,e,g,i){if(this.chart.polar){a=b.rectPlotX/Math.PI*180;if(e.align===null)e.align=a>20&&a<160?"left":a>200&&a<340?"right":"center";if(e.verticalAlign===null)e.verticalAlign=a<45||a>315?"bottom":a>135&&a<225?"top":"middle";c.alignDataLabel.call(this,b,d,e,g,i)}else a.call(this,b,d,e,g,i)}); | ||||
| r(d,"getIndex",function(a,b){var c,d=this.chart,e;d.polar?(e=d.xAxis[0].center,c=b.chartX-e[0]-d.plotLeft,d=b.chartY-e[1]-d.plotTop,c=180-Math.round(Math.atan2(c,d)/Math.PI*180)):c=a.call(this,b);return c});r(d,"getCoordinates",function(a,b){var c=this.chart,d={xAxis:[],yAxis:[]};c.polar?s(c.axes,function(a){var e=a.isXAxis,f=a.center,g=b.chartX-f[0]-c.plotLeft,f=b.chartY-f[1]-c.plotTop;d[e?"xAxis":"yAxis"].push({axis:a,value:a.translate(e?Math.PI-Math.atan2(g,f):Math.sqrt(Math.pow(g,2)+Math.pow(f, | ||||
| 2)),!0)})}):d=a.call(this,b);return d})})()})(Highcharts); | ||||
							
								
								
									
										9
									
								
								public/assets/javascript/highslide-full.min.js
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
							
								
								
									
										12
									
								
								public/assets/javascript/highslide.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,12 @@ | ||||
| /** | ||||
| *	Site-specific configuration settings for Highslide JS | ||||
| */ | ||||
| hs.graphicsDir = 'assets/css/graphics/'; | ||||
| hs.outlineType = 'rounded-white'; | ||||
| hs.wrapperClassName = 'draggable-header'; | ||||
| hs.captionEval = 'this.a.title'; | ||||
| hs.showCredits = false; | ||||
| hs.marginTop = 20; | ||||
| hs.marginRight = 20; | ||||
| hs.marginBottom = 20; | ||||
| hs.marginLeft = 20; | ||||
							
								
								
									
										9
									
								
								public/assets/javascript/highslide.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										9
									
								
								public/assets/javascript/highslide.min.js
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						| @@ -1,60 +1,149 @@ | ||||
| google.load('visualization', '1.0', {'packages': ['corechart']}); | ||||
| google.setOnLoadCallback(chartCallback); | ||||
| var accountChart; | ||||
| $(function () { | ||||
|  | ||||
| function chartCallback() { | ||||
|     drawAccountChart(); | ||||
|     drawExtraCharts(); | ||||
|  | ||||
|     /** | ||||
|      * get data from controller for home charts: | ||||
|      */ | ||||
|     $.getJSON('chart/home/account').success(function (data) { | ||||
|         var options = { | ||||
|             chart: { | ||||
|                 renderTo: 'chart', | ||||
|                 type: 'line' | ||||
|             }, | ||||
|  | ||||
|             series: data, | ||||
|             title: { | ||||
|                 text: 'All accounts' | ||||
|             }, | ||||
|             yAxis: { | ||||
|                 formatter: function () { | ||||
|                     return '$' + Highcharts.numberFormat(this.y, 0); | ||||
|                 } | ||||
|  | ||||
| function drawAccountChart() { | ||||
|  | ||||
|  | ||||
|     $.each($('.homeChart'), function (i, v) { | ||||
|         var obj = $(v); | ||||
|         var accountID = obj.data('id').toString(); | ||||
|         var holderID = $(v).attr('id').toString(); | ||||
|         console.log('AccountID: ' + accountID + ', ' + 'holderID ' + holderID); | ||||
|         var URL = 'chart/home/account/' + accountID; | ||||
|         console.log('URL: ' + URL); | ||||
|  | ||||
|  | ||||
|         var opt = { | ||||
|             curveType: 'function', | ||||
|             legend: { | ||||
|                 position: 'none' | ||||
|             }, | ||||
|             chartArea: { | ||||
|                 left: 50, | ||||
|                 top: 10, | ||||
|                 width: '90%', | ||||
|                 height: 180 | ||||
|  | ||||
|             xAxis: { | ||||
|                 floor: 0, | ||||
|                 type: 'datetime', | ||||
|                 dateTimeLabelFormats: { | ||||
|                     day: '%e %b', | ||||
|                     year: '%b' | ||||
|                 }, | ||||
|             height: 230, | ||||
|             lineWidth: 1 | ||||
|                 title: { | ||||
|                     text: 'Date' | ||||
|                 } | ||||
|             }, | ||||
|             tooltip: { | ||||
|                 shared: true, | ||||
|                 crosshairs: false, | ||||
|                 formatter: function () { | ||||
|                     var str = '<span style="font-size:80%;">' + Highcharts.dateFormat("%A, %e %B", this.x) + '</span><br />'; | ||||
|                     for (x in this.points) { | ||||
|                         var point = this.points[x]; | ||||
|                         var colour = point.point.pointAttr[''].fill; | ||||
|                         str += '<span style="color:' + colour + '">' + point.series.name + '</span>: € ' + Highcharts.numberFormat(point.y, 2) + '<br />'; | ||||
|                     } | ||||
|                     //console.log(); | ||||
|                     return str; | ||||
|                     return '<span style="font-size:80%;">' + this.series.name + ' on ' + Highcharts.dateFormat("%e %B", this.x) + ':</span><br /> € ' + Highcharts.numberFormat(this.y, 2); | ||||
|                 } | ||||
|             }, | ||||
|             plotOptions: { | ||||
|                 line: { | ||||
|                     shadow: true | ||||
|                 }, | ||||
|                 series: { | ||||
|                     cursor: 'pointer', | ||||
|                     negativeColor: '#FF0000', | ||||
|                     threshold: 0, | ||||
|                     lineWidth: 1, | ||||
|                     marker: { | ||||
|                         radius: 2 | ||||
|                     }, | ||||
|                     point: { | ||||
|                         events: { | ||||
|                             click: function (e) { | ||||
|                                 hs.htmlExpand(null, { | ||||
|                                         src: 'chart/home/info/' + this.series.name + '/' + Highcharts.dateFormat("%d/%m/%Y", this.x), | ||||
|                                         pageOrigin: { | ||||
|                                             x: e.pageX, | ||||
|                                             y: e.pageY | ||||
|                                         }, | ||||
|                                         objectType: 'ajax', | ||||
|                                         headingText: this.series.name, | ||||
|                                         width: 250 | ||||
|                                     } | ||||
|                                 ) | ||||
|                                 ; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             credits: { | ||||
|                 enabled: false | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|  | ||||
|         // draw it! | ||||
|         drawChart('#' + holderID, URL, 'LineChart', opt); | ||||
|         $('#chart').highcharts(options); | ||||
|     }); | ||||
|  | ||||
|     //var URL = 'chart/home'; | ||||
|     //drawChart('#chart',URL,opt); | ||||
|     /** | ||||
|      * Get chart data for categories chart: | ||||
|      */ | ||||
|     $.getJSON('chart/home/categories').success(function (data) { | ||||
|         $('#categories').highcharts({ | ||||
|             chart: { | ||||
|                 type: 'column' | ||||
|             }, | ||||
|             title: { | ||||
|                 text: 'Expenses for each categorie' | ||||
|             }, | ||||
|             credits: { | ||||
|                 enabled: false | ||||
|             }, | ||||
|             xAxis: { | ||||
|                 type: 'category', | ||||
|                 labels: { | ||||
|                     rotation: -45, | ||||
|                     style: { | ||||
|                         fontSize: '12px', | ||||
|                         fontFamily: 'Verdana, sans-serif' | ||||
|                     } | ||||
|  | ||||
| function drawExtraCharts() { | ||||
|  | ||||
|     var opt = { | ||||
|                 } | ||||
|             }, | ||||
|             yAxis: { | ||||
|                 min: 0, | ||||
|                 title: { | ||||
|                     text: 'Expense (€)' | ||||
|                 } | ||||
|             }, | ||||
|             legend: { | ||||
|             position: 'none' | ||||
|                 enabled: false | ||||
|             }, | ||||
|         chartArea: { | ||||
|             width: 300, | ||||
|             height: 300 | ||||
|             tooltip: { | ||||
|                 pointFormat: 'Total expense: <strong>€ {point.y:.2f}</strong>', | ||||
|             }, | ||||
|     }; | ||||
|  | ||||
|     drawChart('#budgetChart', 'chart/home/budgets', 'PieChart', opt); | ||||
|     drawChart('#categoryChart', 'chart/home/categories','PieChart', opt); | ||||
|     drawChart('#beneficiaryChart', 'chart/home/beneficiaries','PieChart', opt); | ||||
|             plotOptions: { | ||||
|                 column: { | ||||
|                     cursor: 'pointer' | ||||
|                 } | ||||
|             }, | ||||
|             series: [ | ||||
|                 { | ||||
|                     name: 'Population', | ||||
|                     data: data, | ||||
|  | ||||
|                     events: { | ||||
|                         click: function (e) { | ||||
|                             alert('klik!'); | ||||
|                         } | ||||
|                     }, | ||||
|                     dataLabels: { | ||||
|                         enabled: false | ||||
|                     } | ||||
|                 } | ||||
|             ] | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
| }); | ||||
| @@ -1,119 +0,0 @@ | ||||
| $(function () { | ||||
|  | ||||
|  | ||||
|     var charts = new Array; | ||||
|     /** | ||||
|      * get data from controller for home charts: | ||||
|      */ | ||||
|     $.each($('.homeChart'), function (i, v) { | ||||
|         var obj = $(v); | ||||
|         $.getJSON('chart/home/account/' + obj.data('id')).success(function (data) { | ||||
|             var options = { | ||||
|                 chart: { | ||||
|                     renderTo: obj.attr('id'), | ||||
|                     type: 'line' | ||||
|                 }, | ||||
|                 title: { | ||||
|                     text: obj.data('title') | ||||
|                 }, | ||||
|                 yAxis: { | ||||
|                     title: { | ||||
|                         text: 'Balance (€)' | ||||
|                     }, | ||||
|                     formatter: function () { | ||||
|                         return '$' + Highcharts.numberFormat(this.y, 0); | ||||
|                     } | ||||
|                 }, | ||||
|  | ||||
|                 xAxis: { | ||||
|                     floor: 0, | ||||
|                     type: 'datetime', | ||||
|                     dateTimeLabelFormats: { | ||||
|                         month: '%e %b', | ||||
|                         year: '%b' | ||||
|                     }, | ||||
|                     title: { | ||||
|                         text: 'Date' | ||||
|                     } | ||||
|                 }, | ||||
|                 tooltip: { | ||||
|                     valuePrefix: '€ ', | ||||
|                     formatter: function () { | ||||
|                         return '€ ' + Highcharts.numberFormat(this.y, 2); | ||||
|                     } | ||||
|                 }, | ||||
|                 plotOptions: { | ||||
|  | ||||
|                     line: { | ||||
|                         negativeColor: '#FF0000', | ||||
|                         threshold: 0, | ||||
|                         lineWidth: 1, | ||||
|                         marker: { | ||||
|                             radius: 2 | ||||
|                         } | ||||
|                     } | ||||
|                 }, | ||||
|                 series: data | ||||
|             }; | ||||
|  | ||||
|             charts[i] = new Highcharts.Chart(options); | ||||
|  | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     // draw bene / bud / cat: | ||||
|     var options = { | ||||
|         chart: { | ||||
|             renderTo: 'nothing', | ||||
|             type: 'pie' | ||||
|         }, | ||||
|         title: { | ||||
|             text: 'No title yet' | ||||
|         }, | ||||
|  | ||||
|         xAxis: { | ||||
|             type: 'datetime' | ||||
|         }, | ||||
|         tooltip: { | ||||
|             valuePrefix: '€ ' | ||||
|         }, | ||||
|         plotOptions: { | ||||
|             pie: { | ||||
|                 allowPointSelect: false, | ||||
|                 dataLabels: { | ||||
|                     enabled: false | ||||
|                 }, | ||||
|                 showInLegend: false | ||||
|             } | ||||
|         }, | ||||
|         series: [] | ||||
|     }; | ||||
|     // now get some data: | ||||
|     $.getJSON('chart/home/beneficiaries').success(function (data) { | ||||
|         var opt = options; | ||||
|         opt.series = data; | ||||
|         opt.chart.renderTo = 'beneficiaryChart'; | ||||
|         opt.title.text = 'Beneficiaries'; | ||||
|         charts.push(new Highcharts.Chart(opt)); | ||||
|     }); | ||||
|  | ||||
|     // now get some more data! | ||||
|     $.getJSON('chart/home/categories').success(function (data) { | ||||
|         var opt = options; | ||||
|         opt.series = data; | ||||
|         opt.chart.renderTo = 'categoryChart'; | ||||
|         opt.title.text = 'Categories'; | ||||
|         charts.push(new Highcharts.Chart(opt)); | ||||
|     }); | ||||
|  | ||||
|     // now get some even more data! | ||||
|     $.getJSON('chart/home/budgets').success(function (data) { | ||||
|         var opt = options; | ||||
|         opt.series = data; | ||||
|         opt.chart.renderTo = 'budgetChart'; | ||||
|         opt.title.text = 'Budgets'; | ||||
|         charts.push(new Highcharts.Chart(opt)); | ||||
|     }); | ||||
|  | ||||
|  | ||||
| }); | ||||