app.js 321 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341
  1. if (!window.console || !window.console.log || !window.console.error) {
  2. window.console = { log: function(x) { myalert(x) }, error: function(x) { myalert(x) } };
  3. }
  4. function array_diff(arr1, arr2) {
  5. var diff = [];
  6. for (var i = 0; i < arr1.length; i++) {
  7. if (!in_array(arr2, arr1[i])) {
  8. diff.push(arr1[i]);
  9. }
  10. }
  11. return diff;
  12. }
  13. function array_equal(arr1, arr2) {
  14. if (is_array(arr1) && is_array(arr2)) {
  15. if (arr1.length != arr2.length) return false;
  16. for (var i = 0; i < arr1.length; i++) {
  17. if (!array_equal(arr1[i], arr2[i])) {
  18. return false;
  19. }
  20. }
  21. return true;
  22. } else {
  23. return arr1 == arr2;
  24. }
  25. }
  26. function in_array(arr, value) {
  27. for (var i = 0; i < arr.length; i++) {
  28. if (array_equal(arr[i], value)) return true;
  29. }
  30. return false;
  31. }
  32. //*没有用到
  33. // function playmusic(url) {
  34. // var id = "__music__embed__player__";
  35. // var obj = document.getElementById(id);
  36. // url = __baseurl__ + "js/music/" + encodeURI(url);
  37. // if (obj == null) {
  38. // var oDiv = document.createElement("DIV");
  39. // oDiv.id = id;
  40. // oDiv.style.position = "absolute";
  41. // oDiv.style.width = "1px";
  42. // oDiv.style.height = "1px";
  43. // oDiv.style.top = "-2000px";
  44. // document.body.appendChild(oDiv);
  45. // obj = oDiv;
  46. // }
  47. // if (url.match(new RegExp("\\.wav$", 'ig'))) {
  48. // playwav(obj, url);
  49. // } else {
  50. // playmp3swf(obj, url);
  51. // }
  52. // }
  53. function isIE() {
  54. var ua = navigator.userAgent.toLowerCase();
  55. var s;
  56. if (ua.match(new RegExp("msie\\s+([\\d.]+)", "ig"))) {
  57. return true;
  58. }
  59. return false;
  60. }
  61. // function playwav(obj, url) {
  62. // var html;
  63. // if (isIE()) {
  64. // html = '<embed name="music" height="1px" width="1px" src="' + url + '" />';
  65. // } else {
  66. // html = '<audio height="1px" width="1px" autoplay="true">';
  67. // html += '<source name="music" src="' + url + '" type="audio/x-wav" />';
  68. // html += '</audio>';
  69. // }
  70. // obj.innerHTML = html;
  71. // }
  72. // function playmp3swf(obj, url) {
  73. // var url = escape(url);
  74. // var html = '<embed type="application/x-shockwave-flash" wmode="transparent" ' + 'src="' + __baseurl__ + 'js/audio-player.swf" flashvars="audioUrl=' + url + '&autoPlay=true" height="1px" width="1px"></embed>';
  75. // obj.innerHTML = html;
  76. // }
  77. function myalert(text) {
  78. if (__javascript_debug__) {
  79. //alert(text);
  80. }
  81. }
  82. function GetText(value, unit) {
  83. if (unit < 1) {
  84. unit = -Math.floor(Math.log(unit) / Math.LN10);
  85. var text = FormatNumber(value, unit);
  86. } else if (unit == 1) {
  87. var text = Math.floor(value) + ".0";
  88. } else {
  89. var text = value;
  90. }
  91. return text;
  92. }
  93. function triggerKeydown(code) {
  94. var e = jQuery.Event("keydown");
  95. e.keyCode = code;
  96. $(document).trigger(e);
  97. }
  98. /*
  99. function Alert(obj, showFunction)
  100. {
  101. var str = "";
  102. var key;
  103. if (typeof showFunction == "undefined")
  104. {
  105. showFunction = true;
  106. }
  107. if (typeof obj == 'object')
  108. {
  109. for (key in obj)
  110. {
  111. if (typeof key == 'string')
  112. {
  113. if (typeof obj[key] == 'function')
  114. {
  115. if (showFunction)
  116. {
  117. str += key +" => (\n "+Alert(obj[key])+"\n)\n";
  118. }
  119. } else {
  120. str += key +" => (\n "+Alert(obj[key])+"\n)\n";
  121. }
  122. }
  123. }
  124. return str;
  125. } else {
  126. if (typeof obj === "undefined")
  127. {
  128. return "undefined";
  129. } else if (obj === null) {
  130. return "null";
  131. } else {
  132. return obj.toString();
  133. }
  134. }
  135. }
  136. */
  137. /*没有用到
  138. function url_concat(base, str)
  139. {
  140. var last = base.charAt(base.length - 1);
  141. if (base.indexOf("?") != -1)
  142. {
  143. if(last != "?") {
  144. return base + "&" + str;
  145. } else {
  146. return base + str;
  147. }
  148. } else {
  149. return base + "?" + str;
  150. }
  151. }*/
  152. //controller里面作为判断
  153. function is_undefined(obj) {
  154. return typeof obj === "undefined";
  155. }
  156. //object copy复制一份数据
  157. function object_copy(obj, copy_array) {
  158. var newobj = {};
  159. if (is_array(obj)) {
  160. if (copy_array) {
  161. return array_copy(obj);
  162. } else {
  163. return obj;
  164. }
  165. }
  166. if (typeof obj == 'object') {
  167. for (var key in obj) {
  168. newobj[key] = object_copy(obj[key]);
  169. }
  170. } else {
  171. return obj;
  172. }
  173. return newobj;
  174. }
  175. //深度拷贝
  176. function array_copy(arr) {
  177. var copy = new Array(arr.length);
  178. for (var i = 0; i < arr.length; i++) {
  179. if (is_array(arr[i])) {
  180. copy[i] = array_copy(arr[i]);
  181. } else {
  182. copy[i] = arr[i];
  183. }
  184. }
  185. return copy;
  186. }
  187. //判断是否是数组
  188. function is_array(a) {
  189. return Object.prototype.toString.call(a) === "[object Array]";
  190. }
  191. function ClassExtend(sub, base) {
  192. //before:
  193. //alert("before");
  194. //alert(Alert(oparnet.prototype));
  195. for (var property in base.prototype) {
  196. sub.prototype[property] = base.prototype[property];
  197. }
  198. sub.prototype.constructor = sub;
  199. //获得基类
  200. sub.__parent = base;
  201. if (!base.__sub) {
  202. base.__sub = [];
  203. }
  204. //保存继承它的子类
  205. base.__sub.push(sub);
  206. }
  207. function ClassNew(classname) {
  208. var args = Array.prototype.slice.call(arguments, 1);
  209. var _this = this;
  210. function F() {
  211. _this.parent = classname.apply(_this, args);
  212. return _this.parent;
  213. }
  214. F.prototype = classname.prototype;
  215. return new F();
  216. }
  217. function getClassName(obj) {
  218. var str = obj.constructor.toString();
  219. var regexp = new RegExp("function(\\s+)([^\\(]+)", "ig");
  220. str = regexp.exec(str);
  221. return $.trim(str[2]);
  222. }
  223. function sup(_this) {
  224. var args = Array.prototype.slice.call(arguments, 1);
  225. if (_this.constructor && _this.constructor.__parent) {
  226. if (typeof _this.__counter === 'undefined') {
  227. // It has not... perform the initilization
  228. _this.__counter = 0;
  229. }
  230. _this.__counter++;
  231. if (_this.__counter > 1) //不是第一次调用继承
  232. {
  233. var _parent = _this.constructor.__parent;
  234. for (var i = 1; i < _this.__counter; i++) {
  235. _parent = _parent.__parent;
  236. }
  237. args.unshift(_parent);
  238. ClassNew.apply(_this, args);
  239. } else {
  240. args.unshift(_this.constructor.__parent);
  241. ClassNew.apply(_this, args);
  242. }
  243. }
  244. }
  245. function Point(x, y, z) {
  246. this.x = x;
  247. this.y = y;
  248. if (z !== undefined || z !== null) {
  249. this.z = z;
  250. }
  251. }
  252. function FormatNumber(srcStr, nAfterDot) {
  253. var nten = Math.pow(10, nAfterDot);
  254. srcStr = Math.round(parseFloat(srcStr) * nten) / nten;
  255. srcStr = srcStr.toString();
  256. var arr = srcStr.split(".");
  257. if (arr[1] == null) {
  258. return srcStr + "." + bulidZero(nAfterDot);
  259. }
  260. if (arr[1].length < nAfterDot) {
  261. var offset = nAfterDot - arr[1].length;
  262. srcStr += bulidZero(offset);
  263. }
  264. return srcStr;
  265. }
  266. function bulidZero(num) {
  267. var srcStr = '';
  268. for (var i = 0; i < num; i++) {
  269. srcStr += "0";
  270. }
  271. return srcStr;
  272. }
  273. function array_copy1d(arr) {
  274. var copy = new Array(arr.length);
  275. for (var i = 0; i < arr.length; i++) {
  276. copy[i] = arr[i];
  277. }
  278. return copy;
  279. }
  280. function array_copy2d(arr) {
  281. var copy = new Array(arr.length);
  282. for (var i = 0; i < arr.length; i++) {
  283. var len = arr[i].length;
  284. copy[i] = new Array(len);
  285. for (var j = 0; j < len; j++) {
  286. copy[i][j] = arr[i][j];
  287. }
  288. }
  289. return copy;
  290. }
  291. //得到最大最小值
  292. function minmax(data, start_index, end_index) {
  293. if (!start_index) start_index = 0;
  294. if (!end_index) end_index = data.length - 1;
  295. if (is_array(data[start_index])) {
  296. return _minmax2d(data, start_index, end_index);
  297. } else {
  298. return _minmax1d(data, start_index, end_index);
  299. }
  300. }
  301. //辅助minmax
  302. function _minmax2d(data, start_index, end_index) {
  303. var max = -Infinity;
  304. var min = Infinity;
  305. var maxIndex="";
  306. var minIndex="";
  307. for (var i = start_index; i <= end_index; i++) {
  308. for (var j = 0; j < data[i].length; j++) {
  309. if (data[i][j] >= max) {
  310. max = data[i][j];
  311. maxIndex=[i,j];
  312. }
  313. if (data[i][j] < min){
  314. min = data[i][j];
  315. minIndex=[i,j]
  316. }
  317. }
  318. }
  319. return [min, max,minIndex,maxIndex];
  320. }
  321. //辅助minmax
  322. function _minmax1d(data, start_index, end_index) {
  323. var max = -Infinity;
  324. var min = Infinity;
  325. var maxIndex="";
  326. var minIndex="";
  327. for (var i = start_index; i <= end_index; i++) {
  328. if (data[i] >= max) {
  329. max = data[i];
  330. maxIndex=i;
  331. }
  332. if (data[i] < min) {
  333. min = data[i];
  334. minIndex=i;
  335. }
  336. }
  337. return [min, max,minIndex,maxIndex];
  338. }
  339. //画行
  340. function drawRow(ctx, point, len, color, width) {
  341. var x = point.x;
  342. var y = point.y;
  343. if (isNaN(y)) {
  344. debug("draw row y nan");
  345. }
  346. ctx.beginPath();
  347. if (width) ctx.lineWidth = width;
  348. if (color) ctx.strokeStyle = color;
  349. ctx.moveTo(x, y + 0.5);
  350. ctx.lineTo(x + len, y + 0.5);
  351. ctx.closePath();
  352. ctx.stroke();
  353. }
  354. //画列
  355. function drawCol(ctx, point, len, color, width) {
  356. var x = point.x;
  357. var y = point.y;
  358. ctx.beginPath();
  359. if (width) ctx.lineWidth = width;
  360. if (color) ctx.strokeStyle = color;
  361. ctx.moveTo(x + 0.5, y);
  362. ctx.lineTo(x + 0.5, y + len);
  363. ctx.closePath();
  364. ctx.stroke();
  365. }
  366. //时间转换成日期格式
  367. function timeToDate(time, format, timezone) {
  368. if (!format) format = "Y-m-d H:i:s";
  369. if (!timezone) timezone = 0;
  370. var date = new Date();
  371. if (format.indexOf(".") == -1) // time no msecond
  372. {
  373. time *= 1000;
  374. }
  375. time += (date.getTimezoneOffset() + timezone * 60) * 60 * 1000;
  376. date.setTime(time);
  377. var y = date.getFullYear();
  378. var m = date.getMonth() + 1;
  379. var d = date.getDate();
  380. var h = date.getHours();
  381. var i = date.getMinutes();
  382. var s = date.getSeconds();
  383. var u = date.getMilliseconds();
  384. format = time_replace(format, "Y", y);
  385. format = time_replace(format, "m", m);
  386. format = time_replace(format, "d", d);
  387. format = time_replace(format, "H", h);
  388. format = time_replace(format, "i", i);
  389. format = time_replace(format, "s", s);
  390. format = time_replace(format, "u", u, 3);
  391. return format;
  392. }
  393. //时间标准模式
  394. function formatTime(time, p) {
  395. var conf = Config.getInstance()
  396. var unit = conf.Global.xunit[p]
  397. if (unit) {
  398. unit = unit * 60;
  399. return Math.floor(time / unit) * unit
  400. }
  401. return time
  402. }
  403. //formatTime 辅助函数
  404. function time_replace(format, search, n, zero_number) {
  405. if (typeof zero_number === "undefined") {
  406. zero_number = 2;
  407. }
  408. if (n < 10) n = padingZero(n, zero_number) + n;
  409. return format.replace(search, n);
  410. }
  411. //time_replace 辅助函数
  412. function padingZero(n, zero_number) {
  413. if (n < 0) {
  414. return n;
  415. }
  416. var zn = zero_number - 1;
  417. if (n > 0) {
  418. var zero_current_num = Math.floor(Math.log(n) / Math.LN10) + 1;
  419. zn = zero_number - zero_current_num;
  420. }
  421. var zero = "";
  422. for (var i = 0; i < zn; i++) {
  423. zero += "0";
  424. }
  425. return zero;
  426. }
  427. //在k线图上写内容
  428. function writeText(ctx, point, text, color, font) {
  429. //console.log(window.do_drawText);
  430. if (isIPhone() && window.do_drawText) {
  431. //手机内容设置
  432. text = text.toString();
  433. if (color) ctx.strokeStyle = color;
  434. do_drawText.call(ctx, text, point.x, point.y - 10, 9);
  435. } //电脑内容设置
  436. else if (ctx.fillText) {
  437. if (color) ctx.fillStyle = color;
  438. if (font) { ctx.font = font; } else { ctx.font = "normal small-caps normal 1.1em Arial" }
  439. ctx.fillText(text, point.x, point.y);
  440. } else {
  441. if (color) ctx.strokeStyle = color;
  442. if (font) { ctx.font = font; } else { ctx.font = "normal small-caps normal 1.1em Arial" }
  443. ctx.strokeText(text, point.x, point.y);
  444. }
  445. }
  446. /*
  447. * 画带箭头的虚线
  448. */
  449. function drawWithArrowheads(x1,y1,x2,y2,ctx){
  450. // arbitrary styling
  451. ctx.strokeStyle="#ff6600";
  452. ctx.fillStyle="#ff6600";
  453. ctx.lineWidth=1;
  454. // draw the line
  455. ctx.beginPath();
  456. ctx.moveTo(x1,y1);
  457. ctx.lineTo(x2,y2);
  458. ctx.stroke();
  459. // draw the starting arrowhead
  460. var startRadians=Math.atan((y2-y1)/(x2-x1));
  461. startRadians+=((x2>x1)?-90:90)*Math.PI/180;
  462. this.drawArrowhead(ctx,x1,y1,startRadians);
  463. // draw the ending arrowhead
  464. var endRadians=Math.atan((y2-y1)/(x2-x1));
  465. endRadians+=((x2>x1)?90:-90)*Math.PI/180;
  466. drawArrowhead(ctx,x2,y2,endRadians);
  467. }
  468. function drawArrowhead(ctx,x,y,radians){
  469. ctx.save();
  470. ctx.beginPath();
  471. ctx.translate(x,y);
  472. ctx.rotate(radians);
  473. ctx.moveTo(0,0);
  474. ctx.lineTo(3,10);
  475. ctx.lineTo(-3,10);
  476. ctx.closePath();
  477. ctx.restore();
  478. ctx.fill();
  479. }
  480. /*
  481. * 画虚线
  482. *
  483. */
  484. function drawDashLine(context,x1,y1,x2,y2,pattern)
  485. {
  486. pattern = pattern === undefined ? 5 : pattern;
  487. //得到斜边的总长度
  488. // calculate the delta x and delta y
  489. var dx = (x2 - x1);
  490. var dy = (y2 - y1);
  491. var distance = Math.floor(Math.sqrt(dx*dx + dy*dy));
  492. var dashlineInteveral = (pattern <= 0) ? distance : (distance/pattern);
  493. var deltay = (dy/distance) * pattern;
  494. var deltax = (dx/distance) * pattern;
  495. // draw dash line
  496. context.beginPath();
  497. context.lineWidth=0.7;
  498. context.strokeStyle="#333";
  499. for(var dl=0; dl<dashlineInteveral; dl++) {
  500. if(dl%2) {
  501. context.lineTo(x1 + dl*deltax, y1 + dl*deltay);
  502. } else {
  503. context.moveTo(x1 + dl*deltax, y1 + dl*deltay);
  504. }
  505. }
  506. context.stroke();
  507. }
  508. //画canvas层的分割线 折线
  509. function drawLever(ctx,x,y,color,width,heigh){
  510. ctx.beginPath();
  511. ctx.strokeStyle = color;
  512. //设置路径起点坐标
  513. ctx.moveTo(x, y);
  514. //定义中间点坐标1
  515. ctx.lineTo(x+width, y);
  516. //定义中间点坐标2
  517. ctx.lineTo(x+width, y-heigh);
  518. //按照绘制路径顺序连接各个坐标点
  519. ctx.stroke();
  520. //关闭绘制路径
  521. ctx.closePath();
  522. }
  523. //画线
  524. function drawLine(ctx, X, Y, color, width) {
  525. ctx.beginPath();
  526. if (width) ctx.lineWidth = width;
  527. if (color) ctx.strokeStyle = color;
  528. ctx.moveTo(X[0], Y[0]);
  529. var prevx = X[0];
  530. var prevy = Y[0];
  531. for (var i = 1; i < X.length; i++) {
  532. if (prevx == X[i] && prevy == Y[i]) {
  533. continue;
  534. }
  535. prevx = X[i];
  536. prevy = Y[i];
  537. ctx.lineTo(X[i], Y[i]);
  538. }
  539. ctx.stroke();
  540. }
  541. //plotLine plot画线
  542. function plotLine(ctx, p1, p2, color, width) {
  543. ctx.beginPath();
  544. if (width) ctx.lineWidth = width;
  545. if (color) ctx.strokeStyle = color;
  546. ctx.moveTo(p1.x, p1.y);
  547. ctx.lineTo(p2.x, p2.y);
  548. ctx.closePath();
  549. ctx.stroke();
  550. }
  551. //debug打印信息
  552. function debug(msg) {
  553. var d = $("#debug");
  554. if (d) {
  555. var time = (new Date()).getTime();
  556. var msecond = time % 1000;
  557. time = Math.floor(time / 1000);
  558. d.append(time + "(" + msecond + ")" + ": " + msg + "<br />");
  559. }
  560. }
  561. /*貌似没有用到
  562. function debugx(msg)
  563. {
  564. var d = $("#debugx");
  565. if (d)
  566. {
  567. var time = (new Date()).getTime();
  568. var msecond = time % 1000;
  569. time = Math.floor(time / 1000);
  570. d.append(time + "("+ msecond +")" + ": " + msg + "<br />");
  571. }
  572. }*/
  573. //得到当前时间
  574. function getTime() {
  575. return (new Date()).getTime();
  576. }
  577. /*/从小到大排列的数组 没有使用
  578. function find_first_big(arr, match)
  579. {
  580. //结束条件是:match >= arr[mid] && match <= arr[mid + 1], 也就是在 mid 和 mid + 1 的之间, 这样,mid + 1 就是first big
  581. var start = 0;
  582. var end = arr.length - 1;
  583. while (start <= end)
  584. {
  585. mid = Math.floor((end - start) / 2) + start;
  586. if (mid + 1 > arr.length -1) //越界了, 只有在 start == end 的时候会发生,这个时候 mid = arr.length - 1
  587. {
  588. if (arr.length > 1)
  589. {
  590. if (arr[mid -1] >= match) //判断一下前面一个数字
  591. {
  592. return mid - 1;
  593. }
  594. }
  595. return arr[mid] >= match ? mid : -1;
  596. }
  597. if (match >= arr[mid] && match <= arr[mid + 1]) {
  598. return match == arr[mid] ? mid : mid + 1;
  599. } else if (arr[mid] < match) {
  600. start = mid + 1;
  601. } else { //macth
  602. end = mid - 1
  603. }
  604. }
  605. return -1;
  606. }*/
  607. ////查找到第一个点
  608. function find_first_big_r(arr, match) {
  609. //结束条件是:match >= arr[mid - 1] && match <= arr[mid + 1], 也就是在 mid 和 mid + 1 的之间, 这样,mid + 1 就是first big
  610. var start = 0;
  611. var end = arr.length - 1;
  612. if (arr[end] > match) {
  613. return end;
  614. }
  615. while (start <= end) {
  616. mid = Math.floor((end - start) / 2) + start;
  617. if (mid - 1 < 0) //最多有两个数据 start = 0, end = 0, 1
  618. {
  619. if (arr.length > 1) {
  620. if (arr[1] >= match) {
  621. return 1;
  622. }
  623. }
  624. return arr[0] >= match ? 0 : -1;
  625. }
  626. if (match >= arr[mid] && match <= arr[mid - 1]) {
  627. return match == arr[mid] ? mid : mid - 1;
  628. } else if (arr[mid] < match) {
  629. end = mid - 1;
  630. } else { //macth
  631. start = mid + 1
  632. }
  633. }
  634. return -1;
  635. }
  636. ////判断兼容性 手机 pc的兼容性
  637. function check_textRender(canvas) {
  638. //判断是否是iPhone 或者 ipad
  639. if (isIPhone()) {
  640. return false;
  641. }
  642. if (!canvas.get(0).getContext) {
  643. return true;
  644. }
  645. var ctx = canvas.get(0).getContext('2d');
  646. // ctx.drawImage('static/img/klogo.png',this.width, this.height);
  647. if (typeof ctx.strokeText == 'function' || ctx.fillText == 'function') {
  648. return true
  649. } else {
  650. return false
  651. }
  652. }
  653. //判断是否是iPhone 或者 ipad
  654. function isIPhone() //如果是iPhone,那么采用js库绘制, 已知的bug
  655. {
  656. var agent = navigator.userAgent;
  657. //agent = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_3 like Mac OS X; zh-cn) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7E18 Safari/528.16";
  658. if (agent.toLowerCase().indexOf("iphone") >= 0 || agent.toLowerCase().indexOf("ipad") >= 0) {
  659. return true;
  660. }
  661. return false;
  662. }
  663. //初始化标志位 对于空值做处理
  664. function init_obj(obj, c, p, default_value) {
  665. if (typeof obj === "undefined") {
  666. obj = {};
  667. }
  668. if (typeof obj[c] === "undefined") {
  669. obj[c] = {};
  670. }
  671. if (typeof obj[c][p] === "undefined") {
  672. obj[c][p] = default_value;
  673. }
  674. return obj;
  675. }
  676. //判断是否为object类型
  677. function is_object(obj, key) {
  678. if (key) {
  679. if (typeof obj[key] == "object") {
  680. return true;
  681. }
  682. return false;
  683. }
  684. return (typeof obj == "object");
  685. }
  686. //FzmCookie cookie 内容
  687. FzmCookie = {};
  688. //FzmCookie读函数 从cookie拿数据
  689. FzmCookie.read = function(name) {
  690. var cookieValue = "",
  691. search = name + "=";
  692. if (document.cookie.length > 0) {
  693. offset = document.cookie.indexOf(search);
  694. if (offset != -1) {
  695. if (offset > 0) {
  696. //去除空格部分
  697. var myoffset = offset;
  698. while (myoffset > 0 && document.cookie.charAt(--myoffset) == ' ');
  699. if (myoffset > 0 && document.cookie.charAt(myoffset) != ';') {
  700. return '';
  701. }
  702. }
  703. offset += search.length;
  704. end = document.cookie.indexOf(";", offset);
  705. if (end == -1) {
  706. end = document.cookie.length;
  707. }
  708. cookieValue = unescape(document.cookie.substring(offset, end))
  709. }
  710. }
  711. return cookieValue;
  712. };
  713. //当前时间
  714. function now() {
  715. return (new Date()).getTime();
  716. }
  717. //写cookie
  718. FzmCookie.write = function(name, value, hours, path, domain, secure) {
  719. var expire = "";
  720. if (domain == null) {
  721. /*
  722. domain = document.domain;
  723. if (domain.indexOf(".") == -1) {
  724. domain = '';
  725. } else {
  726. domain = "." + domain;
  727. }
  728. domain = domain ? "; domain=" + domain : "";
  729. */
  730. }
  731. path = path ? path : "/";
  732. if (hours != null) {
  733. expire = new Date(now() + hours * 3600000);
  734. expire = "; expires=" + expire.toGMTString();
  735. }
  736. document.cookie = name + "=" + escape(value) + expire + domain + "; path=" + path + ";";
  737. };
  738. //
  739. FzmCookie.del = function(name, domain, path) {
  740. var expire = "";
  741. if (domain == null) {
  742. domain = domainName();
  743. if (domain.indexOf(".") == -1) {
  744. domain = '';
  745. } else {
  746. domain = "." + domain;
  747. }
  748. domain = domain ? "; domain=" + domain : "";
  749. }
  750. path = path ? path : "/";
  751. value = "";
  752. hours = "-10";
  753. if (hours != null) {
  754. expire = new Date(Fzm.clientTime() + hours * 3600000);
  755. expire = "; expires=" + expire.toGMTString();
  756. }
  757. document.cookie = name + "=" + escape(value) + expire + domain + "; path=" + path + ";";
  758. };
  759. //更新cookie
  760. FzmCookie.update = function(name, value, hours, path, domain, secure) {
  761. var v = Guidv4.get(name); //以guid中保存的值为准
  762. if (!v) v = FzmCookie.read(name);
  763. if (v == '') {
  764. v = value;
  765. }
  766. Guidv4.update(name, v);
  767. FzmCookie.write(name, v, hours, path, domain, secure);
  768. return v;
  769. };
  770. //设置plot_area基本样式
  771. function set_style(name) {
  772. var conf = Config.getInstance();
  773. if (!name) {
  774. name = conf.Global.style;
  775. } else {
  776. conf.Global.style = name;
  777. }
  778. conf.merge("Global.Candle.public", "Global.Candle." + name);
  779. conf.merge("Global.Grid.public", "Global.Grid." + name);
  780. //设置plot_area的背景颜色
  781. $(conf.Global.canvasID).css("background", conf.Global.Grid.public.bgColor);
  782. // $(conf.Global.canvasID).css("background-image","url('static/img/Klogo.png')");
  783. // $(conf.Global.canvasID).css("background-repeat","no-repeat");
  784. }
  785. /*//create_canvas创建canvas层 没有用
  786. function create_canvas()
  787. {
  788. //
  789. var conf = Config.getInstance();
  790. var count = conf.Global.maxCanvasCount;
  791. for (var i = 0; i < count; i++)
  792. {
  793. var id = conf.Global.canvasIDPerfix + i;
  794. var tmp = $("<canvas id='"+id+"'></canvas>");
  795. tmp.get(0).height = 1;
  796. $(conf.Global.canvasID).append(tmp);
  797. }
  798. }
  799. */
  800. //显示加载
  801. function show_loading() {
  802. var conf = Config.getInstance();
  803. var id = conf.Global.ajaxloadingID;
  804. var view = HTML5StockChartAPI.API.controller.view;
  805. var plotWidth = view.plotWidth;
  806. var offsetHeight = $("#plot_area").offset().top;
  807. var offsetWidth = $("#plot_area").offset().left;
  808. var plotHeight = view.plotHeight;
  809. $(id).css("top", offsetHeight + plotHeight / 2 - $(id).width() / 2);
  810. $(id).css("left", offsetWidth + plotWidth / 2 - $(id).width() / 2);
  811. $(id).show();
  812. $("#background").css("top", offsetHeight + plotHeight / 2 - $(id).width() / 2-130);
  813. $("#background").css("left", offsetWidth+ plotWidth / 2 - $(id).width() / 2-130 );
  814. // $(id).show();
  815. }
  816. //隐藏加载
  817. function hide_loading() {
  818. var conf = Config.getInstance();
  819. var id = conf.Global.ajaxloadingID;
  820. $(id).hide();
  821. }
  822. //原来是放了一个矩形框在那里显示内容,现在做成六边形输入框update by fangxiao from 2016/7/1 次方法主要是为了价格标线来设置的
  823. function writeTextOption(ctx, point, value, option) {
  824. if (option) {
  825. if (option.bg) {
  826. if(option.type=="price"){
  827. ctx.fillStyle = option.bg.fillcolor;
  828. ctx.fillRect(point.x+8,point.y-11,80,20);
  829. ctx.fill();
  830. }
  831. else{
  832. //画线
  833. //做个六边形
  834. ctx.strokeStyle = option.bg.color;
  835. //ctx.strokeRect(point.x, point.y - option.bg.height / 2, option.bg.width , option.bg.height);
  836. ctx.fillStyle = option.fillcolor;
  837. ctx.lineWidth = 0.6; //设置线宽
  838. var a = option.bg.width;
  839. var b = option.bg.width / 2 * 0.3; //左小测
  840. //ctx.strokeStyle=gradient;
  841. //console.log(point.x);
  842. //console.log(point.y);
  843. // ctx.strokeText(value, point.x+3,point.y+2.8,option.bg.width);
  844. //ctx.translate(point.x+option.bg.width/2,point.y);
  845. ctx.moveTo(point.x, point.y);//左边第一个点
  846. ctx.lineTo(point.x + b, point.y + option.bg.height / 2);//左上角第一个点
  847. ctx.lineTo(point.x + a - b, point.y + option.bg.height / 2);
  848. ctx.lineTo(point.x + a, point.y);
  849. ctx.lineTo(point.x + a - b, point.y - option.bg.height / 2);
  850. ctx.lineTo(point.x + b, point.y - option.bg.height / 2);
  851. ctx.lineTo(point.x, point.y);
  852. // ctx.fillText(text, point.x, point.y);
  853. ctx.closePath();
  854. ctx.stroke();
  855. ctx.fill();
  856. // ctx.fillRect(point.x, point.y - option.bg.height / 2, option.bg.width , option.bg.height);
  857. // point.y += option.bg.height / 2;
  858. }
  859. }
  860. if (option.unit < 1) {
  861. value = FormatNumber(value, -Math.floor(Math.log(option.unit) / Math.LN10));
  862. }
  863. }
  864. point.y += 5;
  865. point.x += 12;
  866. writeText(ctx, point, value, option.color, option.font);
  867. }
  868. //为了光标设置的样式
  869. function writeTextOptionFortoollist(ctx, point, value, option) {
  870. ctx.strokeStyle = "#000";
  871. //ctx.strokeRect(point.x, point.y - option.bg.height / 2, option.bg.width , option.bg.height);
  872. //ctx.fillStyle = "#000";
  873. ctx.lineWidth = 1; //设置线宽
  874. var a = option.bg.width;
  875. var b = option.bg.width / 2 * 0.3; //左小测
  876. //ctx.strokeStyle=gradient;
  877. //console.log(point.x);
  878. //console.log(point.y);
  879. ctx.strokeText(value, point.x + 3, point.y + 2.8, option.bg.width);
  880. //ctx.translate(point.x+option.bg.width/2,point.y);
  881. ctx.moveTo(point.x, point.y);
  882. ctx.lineTo(point.x + b, point.y + option.bg.height / 2);
  883. ctx.lineTo(point.x + a - b, point.y + option.bg.height / 2);
  884. ctx.lineTo(point.x + a, point.y);
  885. ctx.lineTo(point.x + a - b, point.y - option.bg.height / 2);
  886. ctx.lineTo(point.x + b, point.y - option.bg.height / 2);
  887. ctx.lineTo(point.x, point.y);
  888. // ctx.fillText(text, point.x, point.y);
  889. ctx.closePath();
  890. ctx.stroke();
  891. }
  892. //start 大, end 小的情况 二分法找寻value值位置
  893. function binsearch_r(arr, value, start, end) {
  894. if (typeof start === "undefined") {
  895. start = 0;
  896. }
  897. if (typeof end === "undefined") {
  898. end = arr.length - 1;
  899. }
  900. var mid;
  901. while (start <= end) {
  902. mid = parseInt((start + end) / 2);
  903. if (arr[mid] == value) {
  904. return mid;
  905. } else if (arr[mid] > value) {
  906. start = mid + 1;
  907. } else if (arr[mid] < value) {
  908. end = mid - 1;
  909. }
  910. }
  911. return -1;
  912. }
  913. //最后大于find最大的点的位置
  914. function find_last_little_r(x, find) {
  915. index = find_first_big_r(x, find); //第一个最大值点位置
  916. if (index == -1) //没有找到
  917. {
  918. if (x[0] <= find) {
  919. return 0;
  920. } else {
  921. return -1;
  922. }
  923. } else {
  924. if (x[index] == find) { //找寻到
  925. return index;
  926. } else {
  927. index++;
  928. if (index >= x.length) return -1;
  929. return index;
  930. }
  931. }
  932. }
  933. //找到相邻的find位置
  934. function find_near(x, find) {
  935. var index = find_first_big_r(x, find);
  936. if (index == -1) return 0;
  937. if (index < x.length - 1 && (x[index] - find > find - x[index + 1])) {
  938. index++;
  939. }
  940. return index;
  941. }
  942. //旋转得到的新坐标
  943. //point是在原来坐标系内的坐标
  944. //cta 是新坐标系旋转的角度
  945. //ab 是新坐标系的远点,在原来坐标系中的坐标
  946. function axis_translate(point, cta, ab) {
  947. var newpoint = {};
  948. newpoint.x = (point.x - ab.x) * Math.cos(cta) + (point.y - ab.y) * Math.sin(cta);
  949. newpoint.y = (ab.x - point.x) * Math.sin(cta) + (point.y - ab.y) * Math.cos(cta);
  950. return newpoint;
  951. }
  952. //获取flash版本
  953. function get_flash_version() {
  954. var UNDEF = "undefined",
  955. OBJECT = "object",
  956. SHOCKWAVE_FLASH = "Shockwave Flash",
  957. SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
  958. FLASH_MIME_TYPE = "application/x-shockwave-flash",
  959. EXPRESS_INSTALL_ID = "SWFObjectExprInst";
  960. var playerVersion = [0, 0, 0];
  961. var d = null;
  962. if (typeof navigator.plugins != UNDEF && typeof navigator.plugins[SHOCKWAVE_FLASH] == OBJECT) {
  963. d = navigator.plugins[SHOCKWAVE_FLASH].description;
  964. if (d && !(typeof navigator.mimeTypes != UNDEF && navigator.mimeTypes[FLASH_MIME_TYPE] && !navigator.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) {
  965. plugin = true;
  966. d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
  967. playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
  968. playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
  969. playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
  970. }
  971. } else if (typeof window.ActiveXObject != UNDEF) {
  972. try {
  973. var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
  974. if (a) { // a will return null when ActiveX is disabled
  975. d = a.GetVariable("$version");
  976. if (d) {
  977. ie = true; // cascaded feature detection for Internet Explorer
  978. d = d.split(" ")[1].split(",");
  979. playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
  980. }
  981. }
  982. } catch (e) {
  983. return playerVersion;
  984. }
  985. }
  986. return playerVersion;
  987. }
  988. //是否支持websocket
  989. function support_websocket() {
  990. var version = get_flash_version();
  991. if (version[0] >= 9) {
  992. return true;
  993. }
  994. if (window.WebSocket) {
  995. return true;
  996. }
  997. return false;
  998. }
  999. /*未使用
  1000. function init_websocket()
  1001. {
  1002. if (window.WebSocket) {
  1003. return true;
  1004. }
  1005. if (get_flash_version()[0] >= 9)
  1006. {
  1007. include(__baseurl__ + "js/swfobject.js");
  1008. include(__baseurl__ + "js/web_socket.js");
  1009. return true;
  1010. }
  1011. return false;
  1012. }*/
  1013. //设置宽度
  1014. function set_width(obj, w) {
  1015. if (typeof obj.get == "function" && obj.get(0)) {
  1016. obj.get(0).width = w;
  1017. obj.width(w);
  1018. } else {
  1019. obj.width = w;
  1020. }
  1021. }
  1022. //设置高度
  1023. function set_height(obj, h) {
  1024. // if(h>1){
  1025. // if(obj.attr('id')=="plot_canvas_00"||obj.attr('id')=="plot_canvas_01"||obj.attr('id')=="plot_canvas_02"){
  1026. // h=h-60;
  1027. // }
  1028. // }
  1029. if (typeof obj.get == "function" && obj.get(0)) {
  1030. obj.get(0).height = h;
  1031. obj.height(h);
  1032. } else {
  1033. obj.height = h;
  1034. }
  1035. }
  1036. /*未使用
  1037. function __indicator__name__change(obj)
  1038. {
  1039. indicator.load(indicator.tab, $(obj).val());
  1040. }*/
  1041. //从search位置开始
  1042. function start_with(search, obj) {
  1043. return obj.indexOf(search) == 0
  1044. }
  1045. //HTML5StockChartAPI函数
  1046. function HTML5StockChartAPI(id) {
  1047. this.isinit = false;
  1048. this.id = id;
  1049. this.tplParams = {};
  1050. this.container = $("#" + this.id);
  1051. // this.container.html( __tpl__base__ + __tpl__indwin__);
  1052. this.config = Config.getInstance();
  1053. //console.log(DataReaderTrendLine.getYminmax());
  1054. this.option = {
  1055. debug: __debug__,
  1056. jsdebug: __javascript_debug__,
  1057. datasource: __datasource__,
  1058. datafile: __datafile__,
  1059. pair: __symbol__list__,
  1060. runtime_load: __runtime_load__,
  1061. staticChat: __static__,
  1062. startTime: __start_time__,
  1063. "toolbar.isenable": false,
  1064. plot_area: $("#plot_container"),
  1065. ind: [this.config.mainName]
  1066. };
  1067. if (!this.read('model')) this.write("model", "active");
  1068. var _this = this;
  1069. if (window["FlashCanvas"]) {
  1070. FlashCanvas.ready = function() {
  1071. FlashCanvas.init();
  1072. _this.init();
  1073. }
  1074. } else {
  1075. $(document).ready(function() {
  1076. _this.init();
  1077. });
  1078. }
  1079. }
  1080. HTML5StockChartAPI.prototype.setTPLParams = function(key, val) {
  1081. this.tplParams[key] = val;
  1082. }
  1083. HTML5StockChartAPI.prototype.init = function() {
  1084. if (this.isinit) {
  1085. return;
  1086. }
  1087. this.isinit = true;
  1088. this.controller = new Controller(this);
  1089. if (!is_undefined(this.option["controller.staticChat"])) {
  1090. this.controller.staticChat = this.option["controller.staticChat"];
  1091. }
  1092. //为了兼容以前的版本,添加了这个全局变量
  1093. /*this.indicator = indicator = new WinAjax("indicator.add", "指标管理", 700, 500,this);
  1094. this.indicator.createWindow("__indicator__");
  1095. this.order = order = new WinAjax("order.order","订单",320,240,this);
  1096. this.order.createWindow("__order__");*/
  1097. //////////////////////////
  1098. if (this.c && this.p) {
  1099. this.setPair(this.c, this.p);
  1100. }
  1101. }
  1102. HTML5StockChartAPI.prototype.destroyed=function(){
  1103. this.isinit = false;
  1104. this.controller.deinit();
  1105. this.controller = null;
  1106. }
  1107. HTML5StockChartAPI.prototype.setStaticChart = function(isstatic) {
  1108. //alert(typeof isstatic === "undefined");
  1109. var p = (typeof isstatic === "undefined") ? true : isstatic;
  1110. if (this.isinit) {
  1111. this.controller.staticChat = p;
  1112. } else {
  1113. this.set("controller.staticChat", p);
  1114. }
  1115. }
  1116. HTML5StockChartAPI.prototype.setSymbolList = function(pair) {
  1117. return this.set("pair", pair);
  1118. }
  1119. HTML5StockChartAPI.prototype.setIndicatorConf = function(indicator) {
  1120. if (typeof indicator !== "string") {
  1121. indicator = indicator.join(":");
  1122. }
  1123. indicator = indicator.toLowerCase();
  1124. this.write("ind", indicator);
  1125. this.set("ind", indicator);
  1126. // this.isinit=false;
  1127. if (this.isinit) {
  1128. window.location.reload();
  1129. // this.isinit = false;
  1130. // this.controller.deinit();
  1131. // this.controller = null;
  1132. // this.isinit = false;
  1133. // this.init();
  1134. }
  1135. }
  1136. HTML5StockChartAPI.prototype.initSignal = function() {
  1137. var signal_id = this.read("signal");
  1138. //固定一个策略
  1139. if (signal_id < 4) {
  1140. signal_id = 5;
  1141. }
  1142. if (signal_id) {
  1143. this.config.Global.signal = signal_id;
  1144. } else {
  1145. signal_id = this.config.Global.signal;
  1146. }
  1147. return signal_id;
  1148. }
  1149. HTML5StockChartAPI.prototype.setModel = function(model) {
  1150. this.write("model", model);
  1151. this.config.Global.app_model = model;
  1152. if (this.isinit) {
  1153. window.location.href = "";
  1154. }
  1155. }
  1156. HTML5StockChartAPI.prototype.setSignal = function(signal_id) {
  1157. this.write("signal", signal_id);
  1158. this.config.Global.signal = signal_id;
  1159. if (this.isinit) {
  1160. window.location.href = "";
  1161. }
  1162. }
  1163. HTML5StockChartAPI.prototype.set = function(name, value) {
  1164. this.option[name] = value;
  1165. return this;
  1166. }
  1167. HTML5StockChartAPI.prototype.setPair = function(c, p) {
  1168. this.c = c;
  1169. this.p = p;
  1170. if (!this.isinit) {
  1171. return;
  1172. }
  1173. this.write("symbol", c);
  1174. $.cookie("symbol",c);
  1175. $.cookie("period",p)
  1176. // sessionStorage.setItem('period',p);
  1177. this.write("period", p);
  1178. this.controller.set(this.c, this.p);
  1179. if (typeof this.option["paircb"] === "function") {
  1180. this.option["paircb"](this.c, this.p);
  1181. }
  1182. // console.log(DataReaderbdensity.prototype.getYminmax());
  1183. }
  1184. HTML5StockChartAPI.prototype.toolbarEnable = function() {
  1185. this.set("toolbar.isenable", true);
  1186. if (!this.isinit) {
  1187. return;
  1188. }
  1189. this.controller.toolbar.enable();
  1190. }
  1191. HTML5StockChartAPI.prototype.toolbarDisable = function() {
  1192. this.set("toolbar.isenable", false);
  1193. $("#toolbar").hide();
  1194. if (!this.isinit) {
  1195. return;
  1196. }
  1197. this.controller.toolbar.disable();
  1198. }
  1199. HTML5StockChartAPI.prototype.read = function(name) {
  1200. return FzmCookie.read(name);
  1201. }
  1202. HTML5StockChartAPI.prototype.write = function(name, data) {
  1203. if (typeof data === "string") {
  1204. return FzmCookie.write(name, data, 10000);
  1205. }
  1206. console.error("cookie write error");
  1207. return false;
  1208. }
  1209. HTML5StockChartAPI.prototype.initInd = function(def) {
  1210. var name = this.read("ind");
  1211. if (!name) {
  1212. name = def;
  1213. }
  1214. this.setInd(name);
  1215. }
  1216. HTML5StockChartAPI.prototype.setConfig = function(key, val) {
  1217. return this.config.set(key, val);
  1218. }
  1219. HTML5StockChartAPI.prototype.setInd = function(name) {
  1220. if (name == "tick_price" || name.indexOf("tick_source") === 0) {
  1221. this.p = "TICK";
  1222. } else {
  1223. if (this.p == "TICK") {
  1224. this.p = "H1";
  1225. $.cookie('period','H1');
  1226. // sessionStorage.setItem('period','H1');
  1227. }
  1228. }
  1229. this.setIndicatorConf(name);
  1230. }
  1231. HTML5StockChartAPI.prototype.clearCookie = function() {
  1232. this.write("period", "");
  1233. $.cookie('period','H1');
  1234. this.write("ind", "");
  1235. }
  1236. HTML5StockChartAPI.prototype.initPair = function(c, p, ignore) {
  1237. var symbol = this.read("symbol");
  1238. symbol = symbol ? symbol : c;
  1239. var period = this.read("period");
  1240. period = period ? period : p;
  1241. if (period == ignore) {
  1242. period = "H1";
  1243. $.cookie('period','H1');
  1244. }
  1245. this.setPair(symbol, period);
  1246. }
  1247. //坐标轴的设计按照通用配置的形式来设计。
  1248. //
  1249. //输入:
  1250. //
  1251. //1. POINT(SCALE): 描点形式:需要,model读出的数据.
  1252. //2. EXTEND(NOMAL): 扩展的方式,需要指定扩展对应的数据。
  1253. //3. MIAN: 需要提供主图的数据
  1254. //4. SCALE: 按照比例进行,这个需要提供的是最大值,最小值
  1255. //
  1256. //坐标值的密集阵值:一般指定多小像素内一个坐标,然后根据高度计算大概需要多少个坐标。
  1257. //但是这个值不是精确的,而是有弹性的,为了计算一个最佳的坐标值。
  1258. //
  1259. //设计流程:
  1260. //
  1261. //首先是:[point 还是 scale]
  1262. //
  1263. //如果是scale 给出最大值,最小值 就可以进行计算了。调用 Axis_Scale
  1264. //
  1265. //如果是point: 那么闲判断主图有没有计算,如果没有计算,那么先计算主图。
  1266. //
  1267. //计算主图的过程是这样的:闲判断是否需要 扩展,如果需要扩展,那么
  1268. //按照主图数据,进行扩展。这个时候,要知道主图是 p是多少。这样就可以扩展了。
  1269. //
  1270. //Axis_ExtendByMain
  1271. //Axis_ExtendByTime
  1272. //
  1273. //主图扩展完成后(注意,这里要把Y的数据进行扩展,所以,要计算X的坐标,再计算Y的坐标),
  1274. //那就计算扩展后主图的坐标。扩展完成后调用 Axis_Point, 进行描点处理。
  1275. //
  1276. //对于副图。
  1277. //如果配置不是按照主图进行绘制的,那么直接报错。暂时不支持这样的情况。
  1278. //
  1279. //如果是按照主图进行扩展,那么
  1280. //调用 Axis_ExtendByMain 扩展。
  1281. //
  1282. //最后调用 Axis_PointBYMain 获取坐标数据。
  1283. //
  1284. //
  1285. //main 是主图坐标,因为附图可能和主图相关,所以要加这个值。
  1286. //对于主图的坐标系,这个main值是null
  1287. function Axis(main) {
  1288. this.main = main;
  1289. this.config = Config.getInstance();
  1290. }
  1291. Axis.POINT = 1;
  1292. Axis.MAIN = 1 << 1;
  1293. Axis.TIME = 1 << 2;
  1294. Axis.BIG2SMALL = 1 << 3;
  1295. Axis.BIG2BIG = 1 << 4;
  1296. Axis.SCALE = 1 << 5;
  1297. Axis.CUSTOM = 1 << 6;
  1298. Axis.CUSTOM_DATA = 1 << 7;
  1299. Axis.prototype.setViewConfig = function(viewconfig) {
  1300. if (viewconfig) this.viewconfig = viewconfig;
  1301. }
  1302. Axis.prototype.setData = function(data) {
  1303. if (data) {
  1304. this.data = data;
  1305. this.c = data.c;
  1306. this.p = data.p;
  1307. $.cookie('period',data.p);
  1308. }
  1309. }
  1310. Axis.prototype.clearData = function() {
  1311. this.data = null;
  1312. this.viewconfig = null;
  1313. }
  1314. Axis.prototype.getData = function() {
  1315. this.calc();
  1316. var ret = { data: this.data, axis: this.viewconfig };
  1317. return ret;
  1318. }
  1319. Axis.prototype.calc = function() {
  1320. //viewconfig 按canvas的ID进行组织,主图默认在序号为 0 的配置里面
  1321. //按照数据,现在刚刚传入的数据,每个图还是有关系的.我们要分离这样的关系。
  1322. //
  1323. //1. 读取每个 指标 计算坐标的标准配置
  1324. //2. 获取最大最小指。
  1325. //
  1326. //计算主图
  1327. var maxY = -Infinity;
  1328. var maxX = -Infinity;
  1329. var minX = Infinity;
  1330. var minY = Infinity;
  1331. for (var j = 0; j < this.viewconfig.plot.length; j++) {
  1332. var name = this.viewconfig.plot[j];
  1333. //判断是否参与计算
  1334. var vc = this.config.Global.View[name];
  1335. if (name != this.config.mainName && typeof vc["disable_axis_area"] !== 'undefined' && vc["disable_axis_area"]) {
  1336. continue;
  1337. }
  1338. if (this.data[name].maxX > maxX) maxX = this.data[name].maxX;
  1339. if (this.data[name].minX < minX) minX = this.data[name].minX;
  1340. if (this.data[name].maxY > maxY) maxY = this.data[name].maxY;
  1341. if (this.data[name].minY < minY) minY = this.data[name].minY;
  1342. }
  1343. this.viewconfig.x.max = maxX;
  1344. this.viewconfig.x.min = minX;
  1345. this.viewconfig.y.max = maxY;
  1346. this.viewconfig.y.min = minY;
  1347. if (this.main == null) {
  1348. this.calcMain();
  1349. this.main = this;
  1350. }
  1351. for (j = 0; j < this.viewconfig.plot.length; j++) {
  1352. name = this.viewconfig.plot[j];
  1353. if (name == this.config.mainName) continue;
  1354. this.calcOne(name);
  1355. }
  1356. }
  1357. Axis.prototype.calcOne = function(name) {
  1358. this.getAxis(name, "x");
  1359. this.getAxis(name, "y");
  1360. }
  1361. Axis.prototype.calcMain = function() {
  1362. //下面的数据时扩展过的数据,这样。
  1363. this.getAxisMainX();
  1364. this.getAxis(this.config.mainName, "y");
  1365. }
  1366. Axis.prototype.getAxis = function(name, tag) {
  1367. //tag 标记是 x 轴还是 y轴,取数据的时候用的到。
  1368. var data = this.data[name][tag];
  1369. if (!data || data.length == 0) return;
  1370. var plot = this.viewconfig[tag]; //在tag下面的配置
  1371. var axisconfig = this.config.Global.Axis[name][tag];
  1372. var unit = this.data[name][tag + "unit"];
  1373. if (axisconfig & Axis.POINT) {
  1374. if (plot.axis) debug("plot axis has set.");
  1375. var data = this.pointAxisValue(data, plot.beg, plot.end, this.viewconfig.one, plot.n, axisconfig);
  1376. plot.axis = data.axis;
  1377. plot.axis_option = {};
  1378. plot.axis_option.style = axisconfig;
  1379. plot.axis_option.unit = unit;
  1380. this.viewconfig[tag] = plot;
  1381. this.data[name][tag] = data.data;
  1382. //描点,计算坐标轴的值
  1383. } else if (axisconfig & Axis.MAIN) {
  1384. //通过主图计算
  1385. this.pointByMain(name); //这个不需要什么配置了
  1386. //不需要生成什么坐标的信息,坐标在主图中生成。
  1387. } else if (axisconfig & Axis.SCALE) {
  1388. //通过比例进行计算,每个都要生成坐标的信息。
  1389. if (!plot.axis) {
  1390. //计算坐标轴的值[比例计算的坐标轴]
  1391. var scalevalue = this.getScaleValue(plot.min, plot.max, unit, plot.n, axisconfig);
  1392. var data = this.scaleAxisValue(data, scalevalue, plot.beg, plot.end, axisconfig);
  1393. plot.axis = data.axis;
  1394. plot.axis_option = {};
  1395. plot.axis_option.style = axisconfig;
  1396. plot.axis_option.unit = unit;
  1397. this.viewconfig[tag] = plot;
  1398. this.data[name][tag] = data.data;
  1399. } else {
  1400. if (axisconfig & Axis.CUSTOM) {
  1401. this.data[name][tag] = this.customTranslate(name, data, plot.axis);
  1402. } else {
  1403. this.data[name][tag] = this.lineTranslate(data, plot.axis);
  1404. }
  1405. }
  1406. }
  1407. if (axisconfig & Axis.CUSTOM_DATA) {
  1408. if (this.viewconfig.x.axis && this.viewconfig.y.axis) {
  1409. for (var type in this.data[name].data) {
  1410. this.data[name].data[type].x = this.lineTranslate(this.data[name].data[type].x, this.viewconfig.x.axis);
  1411. this.data[name].data[type].y = this.lineTranslate(this.data[name].data[type].y, this.viewconfig.y.axis);
  1412. }
  1413. }
  1414. }
  1415. }
  1416. Axis.prototype.customTranslate = function(name, data, axis) {
  1417. var param = this.lineGetAxisParam(axis);
  1418. if (!param) {
  1419. return data;
  1420. }
  1421. var a = param[0];
  1422. var b = param[1];
  1423. if (name == "profit" || start_with("profit|", name)) {
  1424. for (var i = 0; i < data.length; i++) {
  1425. for (var j = 0; j < data[i].length; j++) {
  1426. data[i][j][1] = a * data[i][j][1] + b;
  1427. }
  1428. }
  1429. return data;
  1430. } else if (name == "kshapetest" || start_with("kshapetest|", name)) {
  1431. for (var i = 0; i < data.length; i++) {
  1432. data[i][0] = a * data[i][0] + b;
  1433. }
  1434. return data;
  1435. } else if (name == "fractals" || start_with("fractals|", name) || name == "advfractals" || start_with("advfractals|", name)) {
  1436. for (var i = 0; i < data.length; i++) {
  1437. data[i][1] = a * data[i][1] + b;
  1438. }
  1439. return data;
  1440. } else if (name == "bolling_desity") {
  1441. for (var i = 0; i < data.length; i++) {
  1442. for (var j = 0; j < data[i].length; j += 2) {
  1443. if (data[i][j] == -1) {
  1444. continue;
  1445. }
  1446. data[i][j] = a * data[i][j] + b;
  1447. }
  1448. }
  1449. return data;
  1450. }
  1451. if (name == "wdesity") {
  1452. for (var i = 0; i < data.length; i++) {
  1453. for (var j = 0; j < data[i].length; j++) {
  1454. if (data[i][j] == 0) {
  1455. data[i][j] = 0;
  1456. continue;
  1457. }
  1458. data[i][j] = a * data[i][j] + b;
  1459. }
  1460. }
  1461. return data;
  1462. } else if (name == "trend_line") {
  1463. //计算曲线的斜率
  1464. var axis = this.viewconfig.y.axis;
  1465. dy = -(axis[0].key - axis[1].key) / (axis[0].value - axis[1].value);
  1466. dx = this.viewconfig.one;
  1467. var group = {};
  1468. for (i = 0; i < data.length; i++) {
  1469. var g = data[i][4];
  1470. if (g > 0) {
  1471. if (typeof group[g] === "undefined") {
  1472. group[g] = 0;
  1473. } else {
  1474. group[g] += 0;
  1475. }
  1476. } else {
  1477. group[g] = 0;
  1478. }
  1479. //斜率
  1480. data[i][1] = dy * (data[i][1] - data[i][0]) / dx
  1481. //位置
  1482. data[i][0] = a * data[i][0] + b + group[g];
  1483. data[i][7] = a * data[i][7] + b + group[g];
  1484. data[i][6] = this.main.axisMap[data[i][6]];
  1485. }
  1486. return data;
  1487. }
  1488. }
  1489. //beg 是坐标的开始值,这里的data必须是一维数组。
  1490. Axis.prototype.pointAxisValue = function(data, beg, end, one, n, axisconfig) {
  1491. var index = 0;
  1492. var j = 0;
  1493. var data_axis = [];
  1494. var axis = [];
  1495. var total_pixel = beg - end;
  1496. var plot_number = Math.ceil(total_pixel / one);
  1497. if (n > plot_number) {
  1498. var mod = 1;
  1499. } else {
  1500. var mod = Math.round(plot_number / n);
  1501. }
  1502. //这里还有的一个问题是:大坐标表示小数据,还是大坐标,表示大数据,默认是大坐标表示大数据
  1503. if (axisconfig & Axis.BIG2SMALL) { //小的排在前面
  1504. if (data.length > 1 && data[data.length - 1] < data[0]) data = data.reverse();
  1505. }
  1506. for (var i = 0; i < data.length; i++) {
  1507. data_axis[i] = beg;
  1508. if (i % mod == 0) {
  1509. axis[j] = { key: beg, value: data[i] };
  1510. j++;
  1511. }
  1512. beg -= one;
  1513. }
  1514. var ret = { data: data_axis, axis: axis };
  1515. return ret;
  1516. }
  1517. Axis.prototype.scaleAxisValue = function(data, scalevalue, beg, end, axisconfig) {
  1518. var data_axis = [];
  1519. var axis = [];
  1520. if (!scalevalue) {
  1521. debug("error scalevalue.");
  1522. return { data: [], axis: [] };
  1523. }
  1524. var n = scalevalue.length;
  1525. //坐标大小问题,1. 大的坐标表示小的数字,2. 小的坐标表示大的数字
  1526. if (axisconfig & Axis.BIG2SMALL) { //小的排在前面
  1527. if (n > 1 && scalevalue[n - 1] < scalevalue[0]) {
  1528. scalevalue = scalevalue.reverse();
  1529. }
  1530. } else { //Axis.BIG2BIG
  1531. if (n > 1 && scalevalue[n - 1] > scalevalue[0]) {
  1532. scalevalue = scalevalue.reverse();
  1533. }
  1534. }
  1535. var one = Math.floor((beg - end) / (n - 1));
  1536. var index = 0;
  1537. while (beg >= end && index < n) {
  1538. axis.push({ key: beg, value: scalevalue[index++] });
  1539. beg -= one;
  1540. }
  1541. //下面开始转换数据,这里的data可以是一维,也可以是二维
  1542. data = this.lineTranslate(data, axis);
  1543. var ret = { data: data, axis: axis };
  1544. return ret;
  1545. }
  1546. Axis.prototype.getXValue = function(x, mode, axis) {
  1547. /*if (!axis) axis = this;
  1548. var _axis = axis.viewconfig.x.axis; //从小到大排列
  1549. */
  1550. //查找x的值
  1551. var current = null;
  1552. var offset = null;
  1553. var min = Infinity;
  1554. for (var time in this.main.axisMap) {
  1555. var pos = this.main.axisMap[time];
  1556. if (typeof pos == "number") {
  1557. offset = Math.abs(pos - x);
  1558. if (offset < min) {
  1559. min = offset;
  1560. current = time;
  1561. }
  1562. }
  1563. }
  1564. return parseInt(current);
  1565. //return this.getValue(x, _axis, mode);
  1566. }
  1567. Axis.prototype.getValue = function(key, axis, mode) {
  1568. if (typeof axis === "undefined") return false;
  1569. var index = this.findNear(axis, key);
  1570. if (mode == PlotGrid.NEAR) {
  1571. return axis[index].value;
  1572. } else if (mode == PlotGrid.INTERPOLATION) {
  1573. return this.getInterpolation(key, index, axis);
  1574. }
  1575. return false;
  1576. }
  1577. Axis.prototype.getInterpolation = function(find, index, axis) {
  1578. //寻找两个差值点:
  1579. var newaxis = [];
  1580. var start, end;
  1581. if (axis.length <= 1) {
  1582. return axis[index].value;
  1583. }
  1584. if (index == 0) {
  1585. start = 0;
  1586. end = 1;
  1587. } else if (index == axis.length - 1) {
  1588. start = axis.length - 2;
  1589. end = axis.length - 1;
  1590. } else {
  1591. if (axis[index].key > find) {
  1592. start = index;
  1593. end = index + 1;
  1594. } else {
  1595. start = index - 1;
  1596. end = index;
  1597. }
  1598. }
  1599. newaxis.push({ key: axis[start].value, value: axis[start].key });
  1600. newaxis.push({ key: axis[end].value, value: axis[end].key });
  1601. return this.lineTranslate(find, newaxis, true);
  1602. }
  1603. Axis.prototype.findNear = function(axis, find) {
  1604. for (var i = 0; i < axis.length; i++) {
  1605. if (axis[i].key < find) { // find 在 i 和 i - 1 之间
  1606. if (i == 0) return 0;
  1607. if (find - axis[i].key < axis[i - 1].key - find) {
  1608. return i;
  1609. } else {
  1610. return i - 1;
  1611. }
  1612. }
  1613. }
  1614. return axis.length - 1;
  1615. }
  1616. Axis.prototype.getYValue = function(y, mode, axis) {
  1617. if (!axis) axis = this;
  1618. var _axis = axis.viewconfig.y.axis; //从小到大排列
  1619. return this.getValue(y, _axis, mode);
  1620. }
  1621. Axis.prototype.getX = function(data) {
  1622. return this.lineTranslate(data, this.viewconfig.x.axis);
  1623. }
  1624. Axis.prototype.getY = function(data) {
  1625. return this.lineTranslate(data, this.viewconfig.y.axis);
  1626. }
  1627. Axis.prototype.lineTranslate = function(data, axis, noround) {
  1628. if (axis.length == 0) return data;
  1629. if (axis.length == 1) {
  1630. var a = 0;
  1631. var b = axis[0].key;
  1632. } else {
  1633. var a = (axis[0].key - axis[axis.length - 1].key) / (axis[0].value - axis[axis.length - 1].value);
  1634. var b = axis[0].key - a * axis[0].value;
  1635. }
  1636. var is1d = is_array(data);
  1637. var is2d = is_array(data[0]);
  1638. if (is1d) {
  1639. for (var i = 0; i < data.length; i++) {
  1640. if (is2d) {
  1641. for (var j = 0; j < data[i].length; j++) {
  1642. data[i][j] = Math.round(a * data[i][j] + b);
  1643. }
  1644. } else {
  1645. data[i] = Math.round(a * data[i] + b);
  1646. }
  1647. }
  1648. } else {
  1649. if (noround) {
  1650. data = a * data + b;
  1651. } else {
  1652. data = Math.round(a * data + b);
  1653. }
  1654. }
  1655. return data;
  1656. }
  1657. Axis.prototype.lineGetAxisParam = function(axis) {
  1658. if (axis.length == 0) return false;
  1659. if (axis.length == 1) {
  1660. var a = 0;
  1661. var b = axis[0].key;
  1662. } else {
  1663. var a = (axis[0].key - axis[axis.length - 1].key) / (axis[0].value - axis[axis.length - 1].value);
  1664. var b = axis[0].key - a * axis[0].value;
  1665. }
  1666. return [a, b];
  1667. }
  1668. Axis.prototype.getScaleValue = function(start, end, unit, n, axis_style) {
  1669. //浮动:这个n是建议的数目
  1670. var number = Math.ceil((end - start) / unit) / n;
  1671. if (number <= 0) {
  1672. if (start == end) {
  1673. var vals = [start];
  1674. return this.standarAxisValue(vals, start, end, axis_style);
  1675. }
  1676. return null;
  1677. }
  1678. var closest;
  1679. if (number <= 1) {
  1680. closest = unit;
  1681. } else {
  1682. var low = Math.pow(10, Math.floor(Math.log(number) / Math.LN10));
  1683. var high = low * 10;
  1684. var i = 0;
  1685. if (low >= 10) {
  1686. if (axis_style & Axis.TIME) {
  1687. var lookup = [1, 1.5, 2, 3.0, 4.5, 6.0, 10];
  1688. } else {
  1689. var lookup = [1, 1.5, 2, 2.5, 4, 5, 8, 10];
  1690. }
  1691. for (i = 0; i < lookup.length; i++) {
  1692. lookup[i] *= low;
  1693. }
  1694. } else {
  1695. if (axis_style & Axis.TIME) {
  1696. var lookup = [1, 2, 3, 4, 6, 10];
  1697. } else {
  1698. var lookup = [1, 2, 4, 5, 8, 10];
  1699. }
  1700. }
  1701. var min_value = Number.MAX_VALUE;
  1702. var min_index = 0;
  1703. for (i = 0; i < lookup.length; i++) {
  1704. var tmp = Math.abs(lookup[i] - number);
  1705. if (min_value > tmp) {
  1706. min_value = tmp;
  1707. min_index = i;
  1708. }
  1709. }
  1710. var closest = unit * lookup[min_index];
  1711. }
  1712. var minindex = Math.floor(start / closest);
  1713. var maxindex = Math.ceil(end / closest);
  1714. vals = [];
  1715. for (var j = minindex; j <= maxindex; j++) {
  1716. vals.push(j * closest);
  1717. }
  1718. return this.standarAxisValue(vals, start, end, axis_style);
  1719. }
  1720. Axis.prototype.standarAxisValue = function(axis, beg, end, axis_style) {
  1721. var abeg = axis[0];
  1722. var aend = axis[axis.length - 1];
  1723. var delta = 0;
  1724. if (axis_style & Axis.FIX_BEG) {
  1725. delta = abeg - beg;
  1726. } else if (axis_style & Axis.FIX_END) {
  1727. delta = aend - end;
  1728. }
  1729. for (var i = 0; i < axis.length; i++) {
  1730. axis[i] -= delta;
  1731. }
  1732. //下面开始计算坐标的值
  1733. return axis;
  1734. }
  1735. Axis.prototype.getAxisMainX = function() {
  1736. //计算之前复制一份:
  1737. var x = this.data[this.config.mainName].x;
  1738. this.getAxis(this.config.mainName, "x");
  1739. //这个是X轴坐标的映射,其他的坐标要靠这个来计算。
  1740. this.axisMap = {};
  1741. for (var i = 0; i < x.length; i++) {
  1742. this.axisMap[x[i]] = this.data[this.config.mainName].x[i];
  1743. }
  1744. //这样时间和坐标成了一一对应
  1745. }
  1746. Axis.prototype.pointByMain = function(name) {
  1747. //这里主要去除一些毛刺数据,所以统一又处理了一次。
  1748. //这个部分,以后如果要调节性能,还要进行修改。
  1749. var x = [];
  1750. var y = [];
  1751. var index = 0;
  1752. var data = this.data[name];
  1753. for (var i = 0; i < data.x.length; i++) {
  1754. var item = this.main.axisMap[data.x[i]];
  1755. if (item) {
  1756. //查找到坐标,那么就采用这个坐标
  1757. x[index] = item;
  1758. y[index] = data.y[i];
  1759. index++;
  1760. } else {
  1761. if (typeof item === "undefined") {
  1762. continue;
  1763. } else {
  1764. x[index] = item;
  1765. y[index] = data.y[i];
  1766. index++;
  1767. }
  1768. }
  1769. }
  1770. this.data[name].x = x;
  1771. this.data[name].y = y;
  1772. }
  1773. //配置画图的属性
  1774. //1. 类映射
  1775. //绘制图形的时候,是根据绘图的名称,来绘制的。
  1776. //main 是主图,这个是固定的名字。
  1777. //其他的是指标图,用各自的名字。每个画图对象通过两个方面来控制。
  1778. //1. 是数据读取部分,我们把缓存在内存的数据看成是一个数据库,这个读取
  1779. //虽然是千篇一律,但是还是有规律可循。
  1780. //
  1781. //2. 是数据的显示控制,我们会根据plotset的情况,最后转换成坐标的值。通过
  1782. //这个坐标的值,来绘制不同的图形。
  1783. //
  1784. //3. 还有一个对象控制数据保存的过程。比如,数据下载怎么处理,
  1785. // 下载后怎么保存,新数据怎么处理,新数据怎么保存等问题。
  1786. // 处理读写数据的模块应该是要和 数据更新模块分离的。
  1787. //
  1788. //update by fangxiao from 2016/6/29 17:17
  1789. function Config() {
  1790. //浏览器测试
  1791. this.getBrowserInfo();
  1792. this.name = "Config";
  1793. this.mainName = "main";
  1794. this.main = { reader: DataReaderCandle, writer: DataWriterCandle, plot: PlotCandle, data: DataReader.EXTEND, downdata: 1, newdata: 1 };
  1795. //扩展数据。必须有扩展的接口。否则会直接忽略这个选项。
  1796. //通过主图读取数据,主图会传入一个时间范围,然后通过函数读取数据,通过主图扩展数据
  1797. this.volumes = { reader: DataReadervolumes, writer: DataWriter, plot: Plotvolumes };
  1798. this.volumes2 = { reader: DataReadervolumes2, writer: DataWriter, plot: Plotvolumes2 };
  1799. // console.log(""+DataReadervolumes.getYminmax);
  1800. this.ma = { reader: DataReaderIndicatorsMa, writer: null, plot: PlotLine };
  1801. this.macd = { reader: DataReaderIndicatorsMacd, writer: null, plot: PlotMacd };
  1802. this.bolling = { reader: DataReaderIndicatorsBolling, writer: null, plot: PlotBolling };
  1803. this.kdj = { reader: DataReaderIndicatorsKDJ, writer: null, plot: PlotBolling };
  1804. //this.order = {reader:DataReaderIndicatorsOrder,write:null,plot:PlotOrder};
  1805. this.Global = {};
  1806. //这个DataWriter 的基类处理通用的读写。
  1807. this.Global.downloadCount = 600;
  1808. this.Global.maxStoreChunk = 20; // store max = 5 * this.Global.downloadCount
  1809. this.Global.lowMark = 300;
  1810. this.Global.Interval = 20;
  1811. this.Global.newDisable = false;
  1812. this.Global.boxwidth = 1;
  1813. this.Global.trend_line_selected = [];
  1814. this.Global.xunit = {
  1815. // YMD:1440,
  1816. //S5:1/12,
  1817. M1: 1,
  1818. M2: 2,
  1819. M3: 3,
  1820. M3: 4,
  1821. M5: 5,
  1822. M15: 15,
  1823. M30: 30,
  1824. H1: 60,
  1825. H2: 120,
  1826. H4: 240,
  1827. D1: 1440,
  1828. W1: 10080,
  1829. MN1: 4320
  1830. };
  1831. this.Global.styleName = { "hx": "中国经典", "mt": "MT4" };
  1832. //时间选择坐标的时间格式
  1833. this.Global.timeformat = {
  1834. YMD: "Y-m-d",
  1835. TICK: "i:s.u",
  1836. //S5:"m-d H:i:s",
  1837. M1: "m-d H:i",
  1838. M2: "m-d H:i",
  1839. M3: "m-d H:i",
  1840. M5: "m-d H:i",
  1841. M15: "m-d H:i",
  1842. M30: "m-d H:i",
  1843. H1: "m-d H:i",
  1844. H2: "m-d H:i",
  1845. H4: "m-d H:i",
  1846. D1: "m-d",
  1847. W1: "m-d",
  1848. MN1: "m-d"
  1849. };
  1850. this.Global.ajaxloadingID = "#loading";
  1851. this.Global.yunit = {};
  1852. this.Global.yunit.default_value = 0.00001;
  1853. this.Global.maxstep = 1 * 3600; //最大没有数据的时间
  1854. this.Global.maxCanvasCount = 8;
  1855. this.Global.forcePoll = true;
  1856. if (!this.Global.forcePoll && support_websocket()) {
  1857. this.Global.modelName = ModelShortWS;
  1858. this.Global.WSHost = __broadcast_server_active__;
  1859. this.Global.WSPort = "2003";
  1860. this.Global.pingTime = 5; //如果5s没有数据,就ping一下
  1861. this.Global.maxNOData = 10; //如果10s内都没有数据, 那么就close掉。//最好是ping time 的整数倍。也就是 10s 以上
  1862. } else {
  1863. this.Global.modelName = ModelShortPoll;
  1864. }
  1865. if (FzmCookie.read('model') == 'passive_mode') {
  1866. this.Global.modelName = ModelNode;
  1867. }
  1868. this.Global.viewName = View;
  1869. this.Global.canvasID = "#plot_area";
  1870. this.Global.canvasIDPerfix = "plot_canvas_";
  1871. this.Global.PollInterval = 3000; //30ms 判断一次
  1872. this.Global.maxConnectAliveTime = 12; //轮询的链接最多存活的时间
  1873. this.Global.DataAPIDB ="https://kdata.fxee.com/kdata?datafile=" + __datafile__;
  1874. if (__dbreset__) {
  1875. this.Global.DataAPIDB += "&dbreset=" + __dbreset__
  1876. }
  1877. this.Global.DataAPIUpload = "static.php?datafile=" + __datafile__;
  1878. if (__dbreset__) {
  1879. this.Global.DataAPIUpload += "&dbreset=" + __dbreset__
  1880. }
  1881. if (__datasource__ == "db") {
  1882. this.Global.DataAPI = this.Global.DataAPIDB; //一定要加上这个callbac=?否则json无法调用
  1883. } else if (__datasource__ == "upload") {
  1884. this.Global.DataAPI = this.Global.DataAPIUpload; //一定要加上这个callbac=?否则json无法调用
  1885. }
  1886. if (__refererhost__ != __apihost__) {
  1887. this.Global.PollMode = "jsonp";
  1888. } else {
  1889. this.Global.PollMode = "json";
  1890. }
  1891. if (this.Global.PollMode == "jsonp") {
  1892. /* $.ajaxSetup({
  1893. //'jsonp' : false,
  1894. 'jsonpCallback': "_jsonp_"
  1895. });
  1896. */
  1897. }
  1898. //view 模块相关的配置
  1899. this.Global.View = {
  1900. main: { NXPixel: 100, NYPixel: 50, sep: 0 },
  1901. sin: { NXPixel: 100, NYPixel: 50, sep: 0 },
  1902. cos: { NXPixel: 100, NYPixel: 50, sep: 0 },
  1903. tick_source: { NXPixel: 100, NYPixel: 50, sep: 0 },
  1904. profit_line: { NXPixel: 100, NYPixel: 50, sep: 0 },
  1905. volumes: { sep: 1, height: 0.2 },
  1906. volumes2: { sep: 1, height: 0.2 },
  1907. ma: { sep: 0, height: 0.5 },
  1908. //order:{sep:0,height:0.5},
  1909. macd: { sep: 1, height: 0.2 },
  1910. bolling: { sep: 0, height: 0.5 },
  1911. kdj: { sep: 1, height: 0.2 },
  1912. };
  1913. this.Global.TPL = {
  1914. signal: 'main:profit',
  1915. mac2: 'main:volumes:volumes2:ma|main|10|color=red:ma|main|20|color=green:ma|main|50|color=yellow:ma|main|100|color=white:macd|main|12,26,9|color=white-lime:kdj|main|9|color=Red-blue-green:',
  1916. mac: "main:volumes",
  1917. bty: "main:volumes",
  1918. eth: "main:volumes",
  1919. ma: 'ma|main|10|color=red:ma|main|20|color=green:ma|main|50|color=yellow:ma|main|100|color=white:',
  1920. volumes:'volumes:',
  1921. macd: 'macd|main|12,26,9|color=white-lime:',
  1922. bolling: 'bolling|main|20,2|color=green-green-green:',
  1923. kdj: 'kdj|main|9|color=Red-blue-green:',
  1924. ssi: "main:easyforex:fxtrade:" +
  1925. "ma|main|10|color=red:" +
  1926. "ma|easyforex|10|color=red:" +
  1927. "ma|fxtrade|10|color=red:" +
  1928. "ma|main|50|color=yellow:" +
  1929. "ma|easyforex|50|color=yellow:" +
  1930. "ma|fxtrade|50|color=yellow:" +
  1931. "ma|main|100:" +
  1932. "ma|easyforex|100:" +
  1933. "ma|fxtrade|100:" +
  1934. "matrend|main|10,20,30,50|color=red:" +
  1935. "<matrend|main|50,80,120,180|color=yellow:" +
  1936. "matrend|easyforex|10,20,30,50|color=red:" +
  1937. "<matrend|easyforex|50,80,120,180|color=yellow:" +
  1938. "matrend|fxtrade|10,20,30,50|color=red:" +
  1939. "<matrend|fxtrade|50,80,120,180|color=yellow:" +
  1940. "rsi|easyforex,main|14:" +
  1941. "rsi|fxtrade,main|14",
  1942. bolling_desity: "main:bolling_desity:profit",
  1943. sin_cos: "sin||-10,10,1000|color=red:cos||-10,10,1000|color=green",
  1944. profit: "profit_line||{ajax_path}|color=red",
  1945. tick_price: "tick_source||bid-ask/20/1,fxdd,exness,fxcm|fxdd_color=green,fxpro_color=red,exness_color=blue,fxcm_color=yellow,fxdd_flag=true"
  1946. };
  1947. this.Global.arrow = {};
  1948. this.Global.arrow[DataWriterProfit.BUY_OPEN] = {
  1949. height: 15,
  1950. width: 1,
  1951. boder: "white",
  1952. fill: "red",
  1953. cta: (5 * Math.PI / 4),
  1954. incta: (5 * Math.PI / 4)
  1955. };
  1956. this.Global.arrow[DataWriterProfit.BUY_CLOSE] = {
  1957. height: 15,
  1958. width: 1,
  1959. boder: "pink",
  1960. fill: "pink",
  1961. cta: (Math.PI / 4),
  1962. incta: (Math.PI / 4)
  1963. };
  1964. this.Global.arrow[DataWriterProfit.SELL_OPEN] = {
  1965. height: 15,
  1966. width: 1,
  1967. boder: "aqua",
  1968. fill: "aqua",
  1969. cta: Math.PI * 7 / 4,
  1970. incta: Math.PI * 3 / 4
  1971. };
  1972. this.Global.arrow[DataWriterProfit.SELL_CLOSE] = {
  1973. height: 15,
  1974. width: 1,
  1975. boder: "yellow",
  1976. fill: "yellow",
  1977. cta: Math.PI * 3 / 4,
  1978. incta: Math.PI * 7 / 4
  1979. };
  1980. this.Global.autoScroll = false;
  1981. this.Global.signal = 3; //default signal id
  1982. this.Global.WinTplID = "#__wintplid__";
  1983. //this.Global.WinOrderTplID= "#__winordertplid__";
  1984. this.Global.WinAPI = "http://" + __apihost__ + "/window.php";
  1985. //this.Global.WinOrder = "http://" + __orderhost__+"/order";
  1986. //alert(__apihost__);
  1987. this.Global.Win = {};
  1988. this.Global.Win.__indicator__ = {
  1989. tab: {
  1990. add: "添加指标",
  1991. manage: "管理指标"
  1992. }
  1993. };
  1994. /*this.Global.Win.__order__ ={
  1995. tab:{
  1996. order:"下单"
  1997. }
  1998. };*/
  1999. this.Global.style = "hx";
  2000. this.Global.Model = {};
  2001. this.Global.timezone = 8;
  2002. this.Global.overPadding = 3;
  2003. this.Global.hoverTime = 400;
  2004. //坐标轴相关的配置
  2005. //对于坐标轴,有下面的配置模式:
  2006. //1. 按照比例显示绘制数据。比如Y轴上的数据,为了对比,一般采用这样的方式。
  2007. //2.
  2008. //按照点进行排列。从我们外汇的图表来说,还可以把数据扩充成线性连续的模式。
  2009. //K线图往往会缺乏数据。但是,有些时候,为了对比,或者绘制图形方便,扩充成连续的模式是非常的有必要的。
  2010. //但是,扩充的时候要非常的注意非交易日的判断。一般来说,非交易日的没有数据的时间一般大于12个小时,而这
  2011. //在交易日的情况下,基本不可能出现,所以,补充数据可以简单的判断没有数据的时间是否超过12个小时。
  2012. //
  2013. //3.
  2014. //主图可以按照连续的方式扩充。附图的扩充方式增加了一种新的方式,那就是按照主图进行扩充。
  2015. //
  2016. //这些主要在搜索坐标数据的时候非常有用。
  2017. //
  2018. //
  2019. this.Global.Axis = {
  2020. main: { x: Axis.POINT | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL }, //扩展,也可以是 AXIS_NOMAL ,
  2021. sin: { x: Axis.SCALE, y: Axis.SCALE | Axis.BIG2SMALL },
  2022. cos: { x: Axis.SCALE, y: Axis.SCALE | Axis.BIG2SMALL },
  2023. tick_source: { x: Axis.SCALE | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL | Axis.CUSTOM_DATA },
  2024. profit_line: { x: Axis.POINT | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
  2025. ma: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
  2026. macd: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
  2027. bolling: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
  2028. kdj: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
  2029. volumes: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
  2030. volumes2: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL },
  2031. //并采用描点法。也就是不按照比例进行计算坐标
  2032. easyforex: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL }, //扩展,以主图的形式。着就是说,
  2033. //主图没有的点,这个也进行扩展。
  2034. //order:{x:Axis.MAIN | Axis.TIME, y:Axis.SCALE | Axis.BIG2SMALL| Axis.CUSTOM},
  2035. profit: { x: Axis.MAIN | Axis.TIME, y: Axis.SCALE | Axis.BIG2SMALL | Axis.CUSTOM }
  2036. };
  2037. //default grid config
  2038. this.Global.Grid = {
  2039. //全局私有配置,这部分配置是每个对象私有的。暂时,我们只支持全局公共配置。
  2040. private: {
  2041. },
  2042. //全局公共配置
  2043. public: {
  2044. marginTop: [60, 80, 15, 1],
  2045. margin: [20, 65, 15, 1],
  2046. paddingX: 30, //绘制坐标的时候,要用到padding的值。
  2047. paddingY: 0,
  2048. NX: 10, //推荐的数目,但是按照现行算法可能会产生 50%左右的浮动(8-15)都有可能
  2049. NY: 10, //推荐的数目,但是按照现行算法可能会产生 50%左右的浮动
  2050. ledgeLen: 5,
  2051. crossXMode: PlotGrid.NEAR, //采用寻找最近的点的模式
  2052. crossYMode: PlotGrid.INTERPOLATION, //采用差值法
  2053. bgColor: "white",
  2054. axisColor: "rgb(225, 225, 225)",
  2055. gridColor: "rgb(128, 0, 0)",
  2056. fontColor: "rgba(225,225,225,0.4)",
  2057. font: '',
  2058. crossX: //光标画x轴线的颜色设置
  2059. {
  2060. bg: {
  2061. color: "#999",
  2062. width: 100,
  2063. height: 14
  2064. },
  2065. font: "12px Arial",
  2066. color: "#999",
  2067. lineColor: "#999",
  2068. fillcolor:"#0a0a0a"
  2069. },
  2070. crossY: {
  2071. bg: //光标画Y轴线的颜色设置
  2072. {
  2073. color: "#999",
  2074. width: 80,
  2075. height: 20
  2076. },
  2077. font: "12px Arial",
  2078. color: "#999",
  2079. lineColor: "#999",
  2080. fillcolor:"rgb(10,10,10)"
  2081. },
  2082. headText: {
  2083. font: "",
  2084. color: "rgb(200,0,0)"
  2085. }
  2086. },
  2087. hx: {
  2088. bgColor : "#0a0a0a",
  2089. // background:url('../../../assets/img/Klogo.png') no-repeat,
  2090. // background-size: 100%,
  2091. axisColor : "#555",
  2092. gridColor : "#555",//水平刻度移动端
  2093. fontColor : "#555",
  2094. xstyle_axis : 0,
  2095. xstyle_grid : PlotGrid.NO_GRID,
  2096. ystyle_axis : 0,
  2097. ystyle_grid : PlotGrid.NO_GRID,
  2098. xname : 10,
  2099. yname : 10,
  2100. // fontColor : "rgb(110,110,110)",
  2101. font: "12px Arial"
  2102. },
  2103. mt: {
  2104. bgColor: "black",
  2105. axisColor: "rgb(225, 225, 225)",
  2106. gridColor: "LightSlateGray",
  2107. fontColor: "rgba(225,225,225,0.4)", //字体颜色
  2108. xstyle_axis: 0,
  2109. xstyle_grid: PlotGrid.NO_GRID,
  2110. ystyle_axis: 0,
  2111. ystyle_grid: 0,
  2112. xname: 10,
  2113. yname: 10,
  2114. fontColor: "rgba(225,225,225,0.4)",
  2115. font: "1.2em Arial"
  2116. }
  2117. };
  2118. this.Global.volumes = {//volumn颜色修改
  2119. public: {
  2120. //lineColor:["red","green"]
  2121. lineColor:["rgb(176,0,0)","rgb(24,179,75)"]//红涨绿卖
  2122. }
  2123. };
  2124. this.Global.volumes2 = {
  2125. public: {
  2126. lineColor: ["rgb(176,0,0)", "rgb(220,43,43)"]
  2127. }
  2128. };
  2129. this.Global.Line = {
  2130. public: {
  2131. lineColor: "pink"
  2132. }
  2133. };
  2134. /*this.Global.Order = {
  2135. public:{
  2136. fontcolor:["red","aqua" ],
  2137. linecolor:["red","aqua"],
  2138. font:"1px Georgia",
  2139. width : 1,
  2140. size:20,
  2141. tradersize:60,
  2142. midsize:30
  2143. }
  2144. };*/
  2145. this.Global.Candle = {
  2146. public: {
  2147. box_pixel: 4,
  2148. space_pixel: 4,
  2149. close: {
  2150. bg: {
  2151. color: "#ff6600",
  2152. fillcolor:"#0a0a0a",
  2153. width: 55,
  2154. height: 14
  2155. },
  2156. type:"price",
  2157. font: "",
  2158. color: "#ff6600",
  2159. lineColor: "rgb(225,225,225)"
  2160. }
  2161. },
  2162. mt: {
  2163. open_big_color: "white",
  2164. open_small_color: "black",
  2165. ob_border_color: "rgb(220,43,43)",
  2166. os_border_color: "rgb(220,43,43)",
  2167. grid: "mt"
  2168. },
  2169. hx: {//红涨绿卖
  2170. open_big_color : "rgb(24,179,75)",/*红色"rgb(176,0,0)"*/
  2171. open_small_color : "rgb(10,10,10)",
  2172. ob_border_color : "rgb(24,179,75)",/*红色*/
  2173. os_border_color :"rgb(176,0,0)" ,/*绿色"rgb(24,179,75)"*/
  2174. grid: 'hx'
  2175. }
  2176. };
  2177. }
  2178. Config.obj = null;
  2179. //单件模式
  2180. Config.getInstance = function() {
  2181. if (Config.obj == null) {
  2182. Config.obj = new Config();
  2183. //以下进行测试
  2184. }
  2185. return Config.obj;
  2186. }
  2187. Config.prototype.get = function(key, _default) {
  2188. key = key.split(".");
  2189. var _tmp = this;
  2190. if (key.length == 0) return _default;
  2191. for (var i = 0; i < key.length; i++) {
  2192. if (typeof _tmp[key[i]] === "undefined") {
  2193. return _default;
  2194. } else {
  2195. _tmp = _tmp[key[i]]
  2196. }
  2197. }
  2198. return _tmp;
  2199. }
  2200. Config.prototype.getBrowserInfo = function() {
  2201. var ua = navigator.userAgent.toLowerCase();
  2202. var s;
  2203. if (s = ua.match(/msie\s+([\d.]+)/)) {
  2204. this.browser = "ie";
  2205. this.bversion = s[1].split(".");
  2206. } else if (s = ua.match(/firefox\/([\d.]+)/)) {
  2207. this.browser = "firefox";
  2208. this.bversion = s[1].split(".");
  2209. } else if (s = ua.match(/chrome\/([\d.]+)/)) {
  2210. this.browser = "chrome";
  2211. this.bversion = s[1].split(".");
  2212. } else if (s = ua.match(/opera.([\d.]+)/)) {
  2213. this.browser = "opera";
  2214. this.bversion = s[1].split(".");
  2215. } else if (s = ua.match(/version\/([\d.]+).*safari/)) {
  2216. this.browser = "safari";
  2217. this.bversion = s[1].split(".");
  2218. } else {
  2219. this.browser = "other";
  2220. this.bversion = [0, 0, 0];
  2221. }
  2222. if (!is_array(this.bversion) || this.bversion.length == 0) {
  2223. this.bversion = [0, 0, 0];
  2224. }
  2225. for (var i = 0; i < this.bversion.length; i++) {
  2226. this.bversion[i] = parseInt(this.bversion[i]);
  2227. }
  2228. //因为ie6的问题比较多,所以,添加一个专门的变量识别IE6
  2229. this.isIE6 = (this.browser == "ie" && this.bversion[0] <= 6) ? true : false;
  2230. }
  2231. Config.prototype.set = function(key, value) {
  2232. key = key.split(".");
  2233. _tmp = this;
  2234. if (key.length == 0) return this;
  2235. var last = key.pop();
  2236. for (var i = 0; i < key.length; i++) {
  2237. if (typeof _tmp[key[i]] === "undefined") {
  2238. _tmp[key[i]] = {};
  2239. }
  2240. _tmp = _tmp[key[i]];
  2241. }
  2242. _tmp[last] = value;
  2243. return this;
  2244. }
  2245. Config.prototype.merge = function(key1, key2) {
  2246. var dkey1 = this.get(key1);
  2247. var dkey2 = this.get(key2);
  2248. if (is_object(dkey1) && is_object(dkey2)) {
  2249. for (var key in dkey2) {
  2250. if (typeof key === "string" && typeof dkey2[key] !== "function") {
  2251. dkey1[key] = dkey2[key];
  2252. }
  2253. }
  2254. }
  2255. this.set(key1, dkey1);
  2256. }
  2257. //控制器主要的工作是初始化整个工作环境。
  2258. //1. canvas : Config.Global.MaxCanvasCount = 10 每个页面图形个数应该是有限制的,canvas太多,往往也看不清楚。
  2259. //2. 选择正确的model Config.Global.ModelName = "ModelShortPoll"
  2260. //3. 兼容性判断
  2261. //
  2262. //增加indicator。减少indicator的接口。
  2263. //绘图接口
  2264. //绘图更新接口
  2265. //
  2266. var periods = {
  2267. // S5: 5,
  2268. M1: 60,
  2269. M2: 60 * 2,
  2270. M3: 60 * 3,
  2271. M4: 60 * 4,
  2272. M5: 60 * 5,
  2273. H1: 60 * 60,
  2274. H2: 60 * 60 * 2,
  2275. D1: 60 * 60 * 24,
  2276. W1: 60 * 60 * 24 * 7,
  2277. MN1: 60 * 60 * 24 * 30
  2278. };
  2279. function get_period_second(name) {
  2280. var name = name.toUpperCase();
  2281. var ratios = { S: 1, M: 60, H: 3600, D: 3600 * 24, W: 3600 * 24 * 7 };
  2282. if (name == "MN1") {
  2283. return periods[name];
  2284. }
  2285. var perfix = name.charAt(0);
  2286. if (ratios[perfix] && ratios[perfix] > 0) {
  2287. var base = parseInt(name.substr(1));
  2288. if (isNaN(base)) return 0;
  2289. return base * ratios[perfix];
  2290. }
  2291. return 0;
  2292. }
  2293. function Controller(api) {
  2294. this.config = Config.getInstance();
  2295. this.api = api;
  2296. // console.log("api"+this.api);
  2297. var opt = this.api.option;
  2298. var indicators;
  2299. this.plot_area = opt.plot_area;
  2300. this.staticChat = opt.staticChat;
  2301. this.startTime = opt.startTime;
  2302. this.pair = opt.pair;
  2303. this.toolbar = new ToolBar(this);
  2304. this.initInd(opt.ind);
  2305. this.runtime_load = opt.runtime_load;
  2306. this.isinit = false;
  2307. for (var key in this.pair) {
  2308. if (is_object(this.pair[key])) {
  2309. this.config.Global.yunit[key] = this.pair[key].yunit;
  2310. }
  2311. }
  2312. this.timerID = null;
  2313. this.intervalEvent = {};
  2314. this.recall = {};
  2315. if (this.api.option["toolbar.isenable"]) {
  2316. this.toolbar.enable();
  2317. } else {
  2318. this.toolbar.disable();
  2319. }
  2320. this.model = this.getModel();
  2321. this.view = this.getView();
  2322. if (!this.runtime_load) {
  2323. this.initChat();
  2324. }
  2325. this.isinit = false;
  2326. this.init();
  2327. }
  2328. Controller.prototype.deinit = function() {
  2329. this.model.deinit();
  2330. this.view.deinit();
  2331. this.toolbar.deinit();
  2332. this.model = null;
  2333. this.view = null;
  2334. this.toolbar = null;
  2335. }
  2336. Controller.prototype.initChat = function() {
  2337. this.indicators = this.api.indicators;
  2338. var prevlist = [];
  2339. var notseplist = [];
  2340. for (var key in this.ind) {
  2341. if (is_object(this.ind[key])) {
  2342. name = key;
  2343. if (this.ind[name].prev) {
  2344. prevlist.push(name);
  2345. continue;
  2346. }
  2347. if (!this.view.isSeperatePlot(name)) {
  2348. notseplist.push(name);
  2349. continue;
  2350. }
  2351. // if(name.split('"').length==2){
  2352. // name=name.split('"')[1];
  2353. // }
  2354. this.registerChat(name, null, true);
  2355. }
  2356. //注册prev 形式的图
  2357. }
  2358. //对prevlist,首先它必须依赖一个 sep 的图。因为,每个not sep 都是,都是依赖某个sep放到某个sep上的。
  2359. for (var i = 0; i < prevlist.length; i++) {
  2360. var name = prevlist[i];
  2361. var index = this.view.plotindex[this.ind[name].prev];
  2362. if (typeof index === "undefined") {
  2363. continue;
  2364. }
  2365. this.registerChat(name, index);
  2366. }
  2367. //对于非seplist的图表,这个性质是固有的,依赖某个图。
  2368. for (var i = 0; i < notseplist.length; i++) {
  2369. var name = notseplist[i];
  2370. if (!this.ind[name].param) {
  2371. index = 0;
  2372. } else {
  2373. var index = this.view.plotindex[this.ind[name].param[0][0]];
  2374. if (typeof index === "undefined") {
  2375. index = 0;
  2376. }
  2377. }
  2378. this.registerChat(name, index);
  2379. }
  2380. }
  2381. Controller.prototype.getIndParam = function(name) {
  2382. if (this.ind[name] && this.ind[name].param) {
  2383. return this.ind[name].param;
  2384. }
  2385. return false;
  2386. }
  2387. Controller.prototype.getIndList = function() {
  2388. var ind = {};
  2389. for (var key in this.ind) {
  2390. ind[key] = 1;
  2391. }
  2392. return ind;
  2393. }
  2394. Controller.prototype.indTpl = function(indicator) {
  2395. //判断是不是tpl
  2396. //alert(disable_selected);
  2397. if (this.config.Global.TPL[indicator]) {
  2398. ToolBar.tplselect(indicator);
  2399. indicator = this.config.Global.TPL[indicator];
  2400. for (var key in HTML5StockChartAPI.API.tplParams) {
  2401. var data = HTML5StockChartAPI.API.tplParams[key];
  2402. if (typeof data === "string" || typeof data === "number") {
  2403. indicator = indicator.replace(key, data);
  2404. }
  2405. }
  2406. } else {
  2407. ToolBar.tplselect("none");
  2408. }
  2409. // indicator =JSON.stringify(indicator).split(":");
  2410. // console.log("indicator:"+indicator.split);
  2411. if(indicator.split==undefined){
  2412. return indicator
  2413. }
  2414. else{
  2415. }
  2416. if(indicator.split==undefined){
  2417. return indicator;
  2418. }
  2419. indicator =indicator.split(':');
  2420. return indicator;
  2421. }
  2422. Controller.prototype.initInd = function(indlist, disable_parse) {
  2423. //ind 的结构进行调整:
  2424. //区别对待下载数据,但是不显示的情况
  2425. var indlist = this.indTpl(indlist);
  2426. this.config.mainName = indlist[0];
  2427. // if(this.config.mainName.split('"').length==2){
  2428. // this.config.mainName=this.config.mainName.split('"')[1];
  2429. // }
  2430. // this.config.mainName=indlist[0]+'"';
  2431. //alert(this.config.mainName);
  2432. if (disable_parse) {
  2433. var param_ind = indlist;
  2434. } else {
  2435. var param_ind = this.parseInd(indlist);
  2436. }
  2437. for (var i = 0; i < param_ind.length; i++) {
  2438. var ind = param_ind[i];
  2439. var name = param_ind[i].join("|");
  2440. var ind_name = ind[0];
  2441. //注册新的指标值,复制配置。
  2442. if (ind[1]) {
  2443. var depends = ind[1].split(",");
  2444. for (var j = 0; j < depends.length; j++) {
  2445. if (depends[j] == this.config.mainName || depends[j] == "null" || this.ind[depends[j]]) {
  2446. //donothing
  2447. continue;
  2448. }
  2449. if (this.config.Global.View[depends[j]]) {
  2450. this.ind[depends[j]] = { name: depends[j], view: 0, prev: false };
  2451. }
  2452. }
  2453. }
  2454. ind.shift(); //shift 名称
  2455. ind.shift(); //shift depends
  2456. if (depends) {
  2457. ind.unshift(depends);
  2458. } else {
  2459. ind.unshift("none");
  2460. }
  2461. this.ind[name].param = ind;
  2462. this.config[name] = this.config[ind_name];
  2463. this.config.Global.View[name] = this.config.Global.View[ind_name];
  2464. this.config.Global.Axis[name] = this.config.Global.Axis[ind_name];
  2465. }
  2466. }
  2467. Controller.prototype.parseInd = function(indlist) {
  2468. var curperiod = get_period_second(this.api.p);
  2469. this.ind = {};
  2470. var param_ind = [];
  2471. for (var i = 0; i < indlist.length; i++) {
  2472. //判断是否是prev类型的
  2473. var prev = false;
  2474. var name = indlist[i];
  2475. if (indlist[i].charAt(0) == "<") //prev
  2476. {
  2477. prev = this.config.mainName;
  2478. if (i > 0) {
  2479. for (var j = i - 1; j >= 0; j--) {
  2480. if (indlist[j][0] != "<") {
  2481. prev = indlist[j];
  2482. break;
  2483. }
  2484. }
  2485. }
  2486. name = name.substr(1);
  2487. }
  2488. var ind = name.split("|");
  2489. var index = ind[0].indexOf(",");
  2490. var tper, tname;
  2491. if (index != -1) {
  2492. tname = ind[0].substring(0, index);
  2493. tper = ind[0].substring(index + 1);
  2494. name = tname + name.substring(ind[0].length);
  2495. ind[0] = tname;
  2496. if (tper != curperiod) {
  2497. continue;
  2498. }
  2499. }
  2500. if (ind.length > 1) {
  2501. param_ind.push(ind);
  2502. }
  2503. this.ind[name] = {
  2504. name: name,
  2505. view: 1,
  2506. prev: prev
  2507. };
  2508. }
  2509. return param_ind;
  2510. }
  2511. Controller.prototype.addIntervalEvent = function(name, obj, recall) {
  2512. this.intervalEvent[name] = obj;
  2513. if (recall) {
  2514. this.recall[name] = obj;
  2515. }
  2516. }
  2517. Controller.prototype.removeIntervalEvent = function(name) {
  2518. this.intervalEvent[name] = null;
  2519. if (this.recall[name]) {
  2520. this.recall[name] = null;
  2521. }
  2522. }
  2523. Controller.prototype.recallEvent = function() {
  2524. for (var key in this.recall) {
  2525. if (this.recall[key] && is_object(this.recall[key])) {
  2526. this.recall[key].recall(this);
  2527. }
  2528. }
  2529. }
  2530. Controller.prototype.init = function() {
  2531. if (this.isinit) {
  2532. return;
  2533. }
  2534. this.isinit = true;
  2535. this.toolbar.init();
  2536. this.view.init();
  2537. this.setGlobalInterval();
  2538. return true;
  2539. }
  2540. Controller.prototype.set = function(c, p) {
  2541. // console.log('p:'+p)
  2542. if (c && p) {
  2543. this.c = c.toUpperCase();
  2544. this.p = p.toUpperCase();
  2545. $.cookie('period',this.p);
  2546. this.init();
  2547. if (this.model) {
  2548. this.model.set(this.c, this.p);
  2549. this.model.init();
  2550. }
  2551. }
  2552. }
  2553. Controller.prototype.setGlobalInterval = function() {
  2554. var time = this.config.Global.Interval;
  2555. if (time < 20) {
  2556. time = 20;
  2557. } //以20ms为单位
  2558. //规则为:要实现一个功能,就分装一个函数在此处执行
  2559. if (this.timerID !== null) {
  2560. return;
  2561. }
  2562. var _this = this;
  2563. this.timerID = window.setInterval(function() {
  2564. var events = _this.intervalEvent;
  2565. for (var key in events) {
  2566. if (events[key] != null && is_object(events[key])) {
  2567. events[key].run(_this);
  2568. }
  2569. }
  2570. }, time);
  2571. }
  2572. Controller.prototype.flag = function(type) {
  2573. debug(type);
  2574. if (type == "new") {
  2575. this.draw();
  2576. this.recallEvent();
  2577. if (this.config.Global.autoScroll) {
  2578. triggerKeydown(Key.KEY_END);
  2579. }
  2580. } else if (type == "down") {
  2581. this.draw();
  2582. this.recallEvent();
  2583. }
  2584. }
  2585. Controller.prototype.getModel = function() {
  2586. var ModelClass = this.config.Global.modelName;
  2587. //以后要加入兼容性的判断,最后选择一个正确的model
  2588. return new ModelClass(this);
  2589. }
  2590. Controller.prototype.getView = function() {
  2591. var ViewClass = this.config.Global.viewName;
  2592. return new ViewClass(this);
  2593. }
  2594. Controller.prototype.registerChat = function(name, index, has_plot_area) {
  2595. var indinfo = this.ind[name];
  2596. if (indinfo.view) //如果没有view ,不会注册显示对象
  2597. {
  2598. this.view.registerPlot(name, index, has_plot_area, indinfo.param);
  2599. }
  2600. this.model.registerData(name);
  2601. }
  2602. Controller.prototype.unregisetChat = function(name) {
  2603. this.view.unregisetData(name);
  2604. this.view.unregisetPlot(name);
  2605. }
  2606. Controller.prototype.draw = function() {
  2607. if(this.model==undefined)return;
  2608. if (!this.model.ready) return;
  2609. var viewconfig = this.view.getAxisConfig(); //view 的图形分布情况
  2610. //然后。model要根据这个配置,生成相应的坐标数据。
  2611. //坐标配置:
  2612. // (绘图区域)
  2613. // canvas_id => [width, height, 对应的图形名称:main, ma, easyforex ...]
  2614. //
  2615. // 返回的格式:图形名称 => 坐标数据
  2616. //
  2617. //主图要绘制的个数
  2618. if (viewconfig.length <= 0) return;
  2619. //清除原来的view数据
  2620. this.view.clearData();
  2621. this.model.clearData();
  2622. debug("draw_data_init");
  2623. var data = this.model.getData(viewconfig);
  2624. for (var i = 0; i < data.length; i++) {
  2625. //debug("get_data_beg");
  2626. //获取数据内部进行封装:我们只调整这一块。
  2627. //对画图来说,是自己计算的,还是服务器下载的是没有差别的。
  2628. //这样就不会让问题扩大化。
  2629. //debug("get_data_end");
  2630. this.view.updateData(data[i], i); //加入数据
  2631. //debug("calc_axis");
  2632. }
  2633. debug("draw_data_end");
  2634. this.view.draw();
  2635. //检查是否要下载数据
  2636. this.model.downloadData();
  2637. debug("draw_end");
  2638. }
  2639. Controller.prototype.startSet = function(name) {
  2640. var one = this.view.plot[this.config.mainName].getOneSize();
  2641. var area = this.view.grid[0].getPlotArea();
  2642. if (name == "Next") {
  2643. this.model.point(this.model.point() - Math.round(30 / one));
  2644. } else if (name == "Prev") {
  2645. this.model.point(this.model.point() + Math.round(30 / one));
  2646. } else if (name == "PageDown") {
  2647. this.model.point(this.model.point() + Math.round((area.x.beg - area.x.end) / one));
  2648. } else if (name == "PageUp") {
  2649. this.model.point(this.model.point() - Math.round((area.x.beg - area.x.end) / one));
  2650. } else if (name == "Home") {
  2651. this.model.point(this.model.endPos());
  2652. this.model.state = 'home';
  2653. } else if (name == "End") {
  2654. this.model.point(0);
  2655. this.model.state = 'end';
  2656. }
  2657. return this.model.point();
  2658. }
  2659. Controller.prototype.startOffset = function(offset) {
  2660. var start = this.model.point();
  2661. this.model.point(start + offset);
  2662. }
  2663. Controller.prototype.zoomIn = function() {
  2664. this.view.plot[this.config.mainName].zoomIn();
  2665. this.draw();
  2666. }
  2667. Controller.prototype.zoomOut = function() {
  2668. this.view.plot[this.config.mainName].zoomOut();
  2669. this.draw();
  2670. }
  2671. function Data() {
  2672. }
  2673. Data.OPEN = 0;
  2674. Data.HIGH = 1;
  2675. Data.LOW = 2;
  2676. Data.CLOSE = 3;
  2677. Data.VOLUMES = 4;
  2678. //controller 中有一个接口会增加这个
  2679. //事件,它提供一个接口给客户端
  2680. //setVal()
  2681. //getVal()
  2682. //提供给controller 的接口是
  2683. //run
  2684. function IntervalEvent(count, callback, zerocall) {
  2685. this.count = count;
  2686. if (this.count <= 0) {
  2687. this.count = 1;
  2688. }
  2689. this.current = 0;
  2690. this.callback = callback;
  2691. this.value = 0;
  2692. this.prev = null;
  2693. if (!zerocall) {
  2694. this.zerocall = 0;
  2695. } else {
  2696. this.zerocall = zerocall;
  2697. }
  2698. }
  2699. IntervalEvent.prototype.run = function(controller) {
  2700. this.current++;
  2701. if (this.count == this.current) {
  2702. this.current = 0;
  2703. if (this.zerocall) {
  2704. this.prev = this.value;
  2705. this.callback.call(this, controller);
  2706. } else {
  2707. if (this.value != 0) {
  2708. this.prev = this.value;
  2709. this.callback.call(this, controller);
  2710. this.value = 0;
  2711. }
  2712. }
  2713. }
  2714. }
  2715. IntervalEvent.prototype.getVal = function() {
  2716. return this.value;
  2717. }
  2718. IntervalEvent.prototype.recall = function(controller) {
  2719. this.value = this.prev;
  2720. if (this.zerocall) {
  2721. this.callback.call(this, controller, true);
  2722. } else {
  2723. if (this.value != 0) {
  2724. this.callback.call(this, controller, true);
  2725. this.value = 0;
  2726. }
  2727. }
  2728. }
  2729. IntervalEvent.prototype.setVal = function(val) {
  2730. this.value = val;
  2731. return this;
  2732. }
  2733. //数据更新部分:
  2734. //广播服务器的设计是集中式的。我们要广播所有的数据,所以需要进行更新。
  2735. //这个部分将会分为两个部分:下载K线,更新最新的数据
  2736. //
  2737. // 管理tick图:
  2738. // 根据货币对k线,会注册一系列的K线,指标。
  2739. // 更新或者下载的数据都有下面的属性:
  2740. // 1. 货币对/时间/名称
  2741. // 2. 绘图提供更新接口:
  2742. // plot = plot_list[currency][time][name];
  2743. // updateNew(data);
  2744. // download(data);
  2745. //
  2746. //data.registerPlot(c, p, name, plot);
  2747. //data.unregisetPlot(c, p, name, plot);
  2748. //
  2749. //采用广播协议的数据
  2750. function Model(controller) {
  2751. this.data = {};
  2752. this.maindata = {};
  2753. this.dataObj = {};
  2754. this.realname = {};
  2755. this.flagset = {};
  2756. this.ready = false;
  2757. //保存数据指针。标志当前图形读取的位置。
  2758. this.datapoint = {};
  2759. this.config = Config.getInstance();
  2760. this.controller = controller;
  2761. this.registerData(this.config.mainName); // 注册主图
  2762. //alert(this.config.mainName);
  2763. this.main = this.dataObj[this.config.mainName];
  2764. this.downOptions = {};
  2765. //这个由数据层来更新
  2766. this.leftoffset = 0;
  2767. this.rightoffset = 0;
  2768. this.state = '';
  2769. }
  2770. Model.prototype.init = function() {
  2771. //初始化数据
  2772. if (this.c && this.p) {
  2773. //判断是否这个货币对的数据已经初始化过了
  2774. if (this.flag(Model.INITED)) {
  2775. hide_loading();
  2776. this.controller.draw();
  2777. if (this.config.Global.newDisable || this.config[this.config.mainName].newdata) {
  2778. this.newData();
  2779. }
  2780. } else if (this.flag(Model.INITING)) {
  2781. return;
  2782. } else {
  2783. this.flag(Model.FIRST_NEW, 1);
  2784. show_loading();
  2785. this.flag(Model.INITING, 1);
  2786. //alert(this.config.mainName);
  2787. if (this.config['main'].downdata) {
  2788. this.initData();
  2789. } else {
  2790. this.flag(Model.INITED, 1);
  2791. this.init();
  2792. }
  2793. }
  2794. }
  2795. }
  2796. Model.prototype.deinit = function() {
  2797. //释放socket 资源
  2798. }
  2799. Model.NEW = 1;
  2800. Model.DOWN = 1 << 1;
  2801. Model.NEW_DATA = 1 << 2;
  2802. Model.DOWN_DATA = 1 << 3;
  2803. Model.INITED = 1 << 4;
  2804. Model.INITING = 1 << 5;
  2805. Model.NEW_DISABLE = 1 << 6;
  2806. Model.DOWN_END = 1 << 7;
  2807. Model.FIRST_NEW = 1 << 8;
  2808. Model.UPDATE = 1 << 9;
  2809. Model.prototype.registerData = function(name) {
  2810. // console.log("name:"+name);
  2811. if(this.config[name] && !this.dataObj[name]) {
  2812. var newname = name.split("|", 2);
  2813. if (newname.length == 2) {
  2814. this.realname[newname[0]] = name;
  2815. }
  2816. var Reader = this.config[name].reader;
  2817. var Writer = this.config[name].writer;
  2818. this.dataObj[name] = {};
  2819. if (Writer) {
  2820. this.dataObj[name].writer = new Writer(this, name);
  2821. }
  2822. if (Reader) {
  2823. this.dataObj[name].reader = new Reader(this, this.dataObj[name].writer, name);
  2824. }
  2825. //reader 要引用write
  2826. }
  2827. }
  2828. Model.prototype.clearData = function() {
  2829. for (var key in this.dataObj) {
  2830. if (is_object(this.dataObj[key])) {
  2831. this.dataObj[key].writer.clear();
  2832. this.dataObj[key].reader.clear();
  2833. }
  2834. }
  2835. }
  2836. Model.prototype.getDataReader = function(name) {
  2837. return this.dataObj[name].reader;
  2838. }
  2839. Model.prototype.unregisetData = function(name) {
  2840. this.dataObj[name] = null;
  2841. }
  2842. Model.prototype.set = function(c, p) {
  2843. if (this.c != c || this.p != p) {
  2844. if (this.newDataXHR) this.newDataXHR.abort();
  2845. //标记不在更新数据
  2846. this.isNewing = false;
  2847. if (this.subscribe) {
  2848. this.subscribe();
  2849. }
  2850. this.downOptions = {};
  2851. }
  2852. this.c = c;
  2853. this.p = p;
  2854. $.cookie('period',p);
  2855. //初始化标志位
  2856. this.flagset = init_obj(this.flagset, this.c, this.p, 0);
  2857. this.datapoint = init_obj(this.datapoint, this.c, this.p, 0);
  2858. //set 所有的reader对象
  2859. for (var key in this.dataObj) {
  2860. if (is_object(this.dataObj[key])) {
  2861. this.dataObj[key].reader.set();
  2862. }
  2863. }
  2864. }
  2865. Model.prototype.clearData = function() {
  2866. this.data = {};
  2867. }
  2868. Model.prototype.getShift = function(plot) {
  2869. var maxshift = -Infinity;
  2870. for (var i = 0; i < plot.length; i++) {
  2871. var name = plot[i];
  2872. var shift = this.dataObj[name].reader.getShift();
  2873. if (shift > maxshift) {
  2874. maxshift = shift;
  2875. }
  2876. }
  2877. return maxshift;
  2878. }
  2879. Model.prototype.getData = function(viewconfig) {
  2880. //all plot list.
  2881. var plot = [];
  2882. this.plotnum = viewconfig[0].plotnum;
  2883. for (var i = 0; i < viewconfig.length; i++) {
  2884. var arr = viewconfig[i].plot;
  2885. for (var j = 0; j < arr.length; j++) {
  2886. plot.push(arr[j]);
  2887. }
  2888. }
  2889. //初始化参数
  2890. for (var i = 0; i < plot.length; i++) {
  2891. var name = plot[i];
  2892. //if (name == this.config.mainName) continue;
  2893. var param = this.controller.getIndParam(name);
  2894. if (param) {
  2895. this.dataObj[name].reader.setParam(param);
  2896. }
  2897. }
  2898. var shift = this.getShift(plot);
  2899. //先计算普通的:
  2900. for (var i = 0; i < viewconfig.length; i++) {
  2901. this._getData(viewconfig[i].plot, viewconfig[i].plotnum + shift);
  2902. }
  2903. //再计算关联,但是不会在前台显示的数据
  2904. var nodatalist = [];
  2905. for (var i = 0; i < plot.length; i++) {
  2906. var param = this.controller.getIndParam(plot[i]);
  2907. if (param && param[0] != "none") {
  2908. for (var k = 0; k < param[0].length; k++) {
  2909. if (this.data[param[0][k]]) {
  2910. continue;
  2911. } else {
  2912. nodatalist.push(param[0][k]);
  2913. }
  2914. }
  2915. }
  2916. }
  2917. this._getData(nodatalist, viewconfig[0].plotnum + shift);
  2918. //再计算通过这些数据得到“计算的数据”
  2919. for (var j = 0; j < viewconfig.length; j++) {
  2920. for (var i = 0; i < viewconfig[j].plot.length; i++) {
  2921. var name = viewconfig[j].plot[i];
  2922. var param = this.controller.getIndParam(name);
  2923. if (param && param[2] != "__ignore__") {
  2924. if (name == this.config.mainName) {
  2925. continue;
  2926. }
  2927. if (param[0] != "none") {
  2928. for (var k = 0; k < param[0].length; k++) {
  2929. this.dataObj[name].reader.setDependData(param[0][k], this.data[param[0][k]]);
  2930. }
  2931. }
  2932. this.data[name] = this.dataObj[name].reader.getData(this.config[name].data);
  2933. }
  2934. }
  2935. }
  2936. //计算完成了,这些数据就没有用了,释放掉内存
  2937. for (var i = 0; i < nodatalist.length; i++) {
  2938. this.data[nodatalist[i]] = null;
  2939. }
  2940. return this.formatData(viewconfig, shift);
  2941. }
  2942. Model.prototype._getData = function(plotlist, num) {
  2943. if (!this.data[this.config.mainName]) {
  2944. this.data[this.config.mainName] = this.dataObj[this.config.mainName].reader.getData(this.plotnum, this.config[this.config.mainName].data, true);
  2945. this.maindata = this.dataObj[this.config.mainName].reader.getData(this.num, this.config[this.config.mainName].data, true);
  2946. }
  2947. //计算所有没有参数的情况
  2948. for (var i = 0; i < plotlist.length; i++) {
  2949. var name = plotlist[i];
  2950. if (name == this.config.mainName) continue;
  2951. var param = this.controller.getIndParam(name);
  2952. if (!param || param[2] === "__ignore__") {
  2953. this.data[name] = this.dataObj[name].reader.getDataByMain(this.config[name].data);
  2954. }
  2955. }
  2956. }
  2957. Model.prototype.shiftData = function(shift) {
  2958. //先shift main,main直接按照数字shift
  2959. //其他相关的shift按照时间进行shift。因为,不一定是对齐的。
  2960. var main = this.config.mainName;
  2961. if (shift > 0 && shift < this.data[main].x.length) {
  2962. //this.data[main].x = this.data[main].x.slice(0, -shift);
  2963. //this.data[main].y = this.data[main].y.slice(0, -shift);
  2964. //var minx = this.data[main].x[this.data[main].x.length -1];
  2965. /*for (var key in this.data)
  2966. {
  2967. if (key == main) continue;
  2968. if (this.data[key] && is_object(this.data[key]))
  2969. {
  2970. var shift = this.getShiftNumber(this.data[key].x, minx);
  2971. this.data[key].x = this.data[key].x.slice(0, -shift);
  2972. this.data[key].y = this.data[key].y.slice(0, -shift);
  2973. }
  2974. }*/
  2975. }
  2976. for (var key in this.data) {
  2977. if (this.data[key] && is_object(this.data[key])) {
  2978. this.data[key] = this.dataObj[key].reader.formatData(this.data[key].x, this.data[key].y);
  2979. }
  2980. }
  2981. }
  2982. Model.prototype.getShiftNumber = function(x, minx) {
  2983. var count = 0;
  2984. for (var i = x.length - 1; i >= 0; i--) {
  2985. if (x[i] >= minx) {
  2986. break;
  2987. } else {
  2988. count++;
  2989. }
  2990. }
  2991. return count;
  2992. }
  2993. //如果是主图的数据,因为要用于对齐,所以,复制一份
  2994. //防止外界对其进行修改操作。
  2995. Model.prototype.formatData = function(viewconfig, shift) {
  2996. this.shiftData(shift);
  2997. //再计算通过这些数据得到“计算的数据”
  2998. var data = [];
  2999. //var text;
  3000. for (var j = 0; j < viewconfig.length; j++) {
  3001. data[j] = {};
  3002. //text = "";
  3003. for (var i = 0; i < viewconfig[j].plot.length; i++) {
  3004. var name = viewconfig[j].plot[i];
  3005. if (name == this.config.mainName) {
  3006. data[j][name] = object_copy(this.data[this.config.mainName]);
  3007. data[j][name].x = array_copy1d(this.data[this.config.mainName].x);
  3008. } else {
  3009. data[j][name] = this.data[name];
  3010. }
  3011. //text += "[" + this.getShowName(name) + " " + this.lastData(this.data[name].y[0]) + "] ";
  3012. }
  3013. data[j].c = this.c;
  3014. data[j].p = this.p;
  3015. //data[j].text = text;
  3016. }
  3017. return data;
  3018. }
  3019. Model.prototype.update = function(data, type) {
  3020. if (!data) {
  3021. if (type == Model.DOWN) {
  3022. this.ready = true;
  3023. this.controller.flag("down");
  3024. this.flag(Model.DOWN_END, 1);
  3025. }
  3026. return;
  3027. }
  3028. if (data.code) {
  3029. if (data.code == "goto" && data.msg) {
  3030. window.location.href = data.msg;
  3031. }
  3032. return;
  3033. }
  3034. var is_new = false;
  3035. var is_down = false;
  3036. var is_update = false;
  3037. if (!data.c || !data.p) {
  3038. return;
  3039. }
  3040. var c = data.c.toUpperCase();
  3041. var p = data.p.toUpperCase();
  3042. //数据已经下载到末尾了
  3043. var end = data.end;
  3044. this.flag(Model.DOWN_END, end);
  3045. if (data.code) {
  3046. debug(data.code);
  3047. //发生了错误
  3048. return;
  3049. }
  3050. this.downOptions = data.options || {};
  3051. for (var key in data) {
  3052. //下载的数据
  3053. if (!is_object(data[key])) continue;
  3054. //这三个是保留的
  3055. if (key == "c" || key == "p" || key == "code" || key == "end") {
  3056. continue;
  3057. }
  3058. var keyreal = key;
  3059. if (typeof this.dataObj[key] === "undefined") {
  3060. key = this.realname[key];
  3061. }
  3062. if (typeof key === "undefined") {
  3063. continue;
  3064. }
  3065. if (this.dataObj[key]) {
  3066. if (type == Model.NEW) {
  3067. is_new = true;
  3068. if (this.dataObj[key].writer) this.dataObj[key].writer.setNewData(c, p, data[keyreal]);
  3069. } else if (type == Model.UPDATE) {
  3070. is_update = true;
  3071. if (this.dataObj[key].writer) this.dataObj[key].writer.setUpdateData(c, p, data[keyreal]);
  3072. } else if (this.downOptions.total_size) {
  3073. is_down = true;
  3074. if (this.dataObj[key].writer && this.dataObj[key].writer.setDownloadDataByOffset) {
  3075. this.dataObj[key].writer.setDownloadDataByOffset(c, p, data[keyreal], this.downOptions);
  3076. } else {
  3077. if (this.dataObj[key].writer) this.dataObj[key].writer.setDownloadData(c, p, data[keyreal]);
  3078. }
  3079. } else {
  3080. //判断是否存在数据对象,那么更新图形的数据。
  3081. is_down = true;
  3082. if (this.dataObj[key].writer) this.dataObj[key].writer.setDownloadData(c, p, data[keyreal]);
  3083. }
  3084. }
  3085. }
  3086. if (is_new) {
  3087. this.ready = true;
  3088. this.controller.flag("new");
  3089. }
  3090. if (is_down) {
  3091. this.ready = true;
  3092. this.controller.flag("down");
  3093. }
  3094. if (is_update) {
  3095. this.ready = true;
  3096. this.controller.flag("new");
  3097. }
  3098. }
  3099. Model.prototype.getIndicatorList = function() {
  3100. var list = [];
  3101. for (var key in this.dataObj) {
  3102. if (key == this.config.mainName) continue; //主图的数据,数据接口会默认更新
  3103. if (is_object(this.dataObj[key])) {
  3104. list.push(key);
  3105. }
  3106. }
  3107. return list;
  3108. }
  3109. //数据集合中,按照时间,或者某个x轴一路更新
  3110. //肯定会有一个边界。这个数据边界就从这里取。
  3111. Model.prototype.startXValue = function() {
  3112. var start = this.main.reader.startXValue();
  3113. if (start <= 0 && this.controller.startTime) {
  3114. return this.controller.startTime;
  3115. }
  3116. return start;
  3117. }
  3118. Model.prototype.endXValue = function() {
  3119. return this.main.reader.endXValue();
  3120. }
  3121. Model.prototype.leftDataCount = function() {
  3122. return this.endPos() - this.point() - this.plotnum;
  3123. }
  3124. Model.prototype.rightDataCount = function() {
  3125. return this.point();
  3126. }
  3127. Model.prototype.endPos = function() {
  3128. return this.main.reader.getEndPos();
  3129. }
  3130. Model.prototype.flag = function(key, value, c, p) {
  3131. if (!c) {
  3132. c = this.c;
  3133. }
  3134. if (!p) {
  3135. p = this.p;
  3136. }
  3137. if (!c || !p) {
  3138. return;
  3139. }
  3140. c = c.toUpperCase();
  3141. p = p.toUpperCase();
  3142. if (typeof value === "undefined") {
  3143. return (this.flagset[c][p] & key) == key; //判断标志位是否已经被设置了
  3144. } else if (value == 0) {
  3145. this.flagset[c][p] = this.flagset[c][p] & (~key); //清除标志位
  3146. } else {
  3147. this.flagset[c][p] = this.flagset[c][p] | key; //设置标志位
  3148. }
  3149. }
  3150. Model.prototype.point = function(value) {
  3151. if (typeof value === "undefined") {
  3152. return this.datapoint[this.c][this.p];
  3153. } else {
  3154. this.datapoint[this.c][this.p] = value;
  3155. }
  3156. }
  3157. Model.prototype.getLeftOffset = function() {
  3158. return this.leftoffset;
  3159. }
  3160. Model.prototype.getRightOffset = function() {
  3161. return this.rightoffset;
  3162. }
  3163. Model.prototype.getDownOffset = function(down_flag) {
  3164. this.count = this.config.Global.downloadCount;
  3165. if (down_flag == -1 && this.getRightOffset() == 0) {
  3166. return -1;
  3167. }
  3168. if (down_flag == 1 && this.getLeftOffset() >= this.downOptions.total_size) {
  3169. return -1;
  3170. }
  3171. if (down_flag == 1) {
  3172. var offset = this.getLeftOffset() + 1; //读取下一个数据
  3173. //超出范围
  3174. if (offset >= this.downOptions.total_size) offset = -1;
  3175. }
  3176. if (down_flag == -1) {
  3177. var offset = this.getRightOffset() - this.config.Global.downloadCount;
  3178. if (offset < 0) {
  3179. offset = 0;
  3180. this.count = this.getRightOffset() - offset;
  3181. }
  3182. }
  3183. return offset;
  3184. }
  3185. Model.prototype.getDataByTime = function(name, time, near) {
  3186. var x = this.dataObj[name].writer.getX(this.c, this.p);
  3187. var y = this.dataObj[name].writer.getY(this.c, this.p);
  3188. var index = binsearch_r(x, time);
  3189. var obj = {};
  3190. obj.time = timeToDate(time, this.config.Global.timeformat[this.p], this.config.Global.timezone);
  3191. if (index == -1 && near == "candle") {
  3192. index = find_last_little_r(x, time);
  3193. if (index == -1) return false;
  3194. var close = y[index][Data.CLOSE];
  3195. obj.data = [close, close, close, close, y[index][Data.VOLUMES]];
  3196. } else {
  3197. if (index == -1) return false;
  3198. obj.data = y[index];
  3199. }
  3200. return obj;
  3201. }
  3202. __javascript_debug__ = false;
  3203. __datasource__ = "db";
  3204. __datafile__ = "db";
  3205. __debug__ = false;
  3206. __static__ = false;
  3207. __runtime_load__ = false;
  3208. __start_time__ = false;
  3209. __baseurl__ = "http:\/\/locaohost:9001\/";
  3210. __broadcast_server_active__ = "115.236.165.18";
  3211. __loadhost__ = "localhost:9001";
  3212. __refererhost__ = "localhost:9001";
  3213. __orderhost__ = "localhost:9001";
  3214. __apihost__ = "rsi.33.cn";
  3215. __dbreset__ = ""
  3216. __musicselect__ = { "alert.wav": "alert", "alert2.wav": "alert2", "connect.wav": "connect", "disconnect.wav": "disconnect", "email.wav": "email", "expert.wav": "expert", "ok.wav": "ok", "request.wav": "request", "stops.wav": "stops", "tick.wav": "tick", "timeout.wav": "timeout", "wait.wav": "wait", "": "", "\u05a3\u0534 - ": "\u05a3\u0534 - " };
  3217. //plot base function. process base plot function.
  3218. function Key() {
  3219. }
  3220. Key.KEY_PREV = 37;
  3221. Key.KEY_UP = 38;
  3222. Key.KEY_NEXT = 39;
  3223. Key.KEY_DOWN = 40;
  3224. Key.KEY_HOME = 36;
  3225. Key.KEY_END = 35;
  3226. Key.KEY_PAGE_DOWN = 34;
  3227. Key.KEY_PAGE_UP = 33;
  3228. function Plot(view, grid, name) {
  3229. this.view = view;
  3230. this.name = name;
  3231. this.controller = this.view.controller;
  3232. this.grid = grid;
  3233. this.getPlotArea();
  3234. this.ctx = this.grid.ctx;
  3235. this.ctxBG = this.grid.ctxBG;
  3236. this.ctxFront = this.grid.ctxFront;
  3237. this.axis = this.grid.axis;
  3238. this.canvas = this.grid.canvas;
  3239. this.config = Config.getInstance();
  3240. this.param = {};
  3241. classname = getClassName(this);
  3242. classname = classname.substr(4);
  3243. if (this.config.Global[classname]) {
  3244. this.conf = this.config.Global[classname].public;
  3245. } else {
  3246. this.conf = {};
  3247. }
  3248. //对K线图的操作是全局性的。也就是说,这里的不会像grid里面一样复制一份全局配置。
  3249. //而是直接操作全局配置
  3250. }
  3251. //默认一个时间占据一个像素,这个是线条默认的占用值。
  3252. Plot.prototype.getOneSize = function() {
  3253. return 1;
  3254. }
  3255. //默认一个时间占据一个像素,这个是线条默认的占用值。
  3256. Plot.prototype.getPlotArea = function() {
  3257. var area = this.grid.getPlotArea();
  3258. this.top = area.y.end;
  3259. this.left = area.x.end;
  3260. this.bottom = area.y.beg;
  3261. this.right = area.x.beg + this.grid.conf.paddingX;
  3262. }
  3263. Plot.prototype.getShowName = function() {
  3264. var name = this.name.toUpperCase();
  3265. name = name.replace("MAIN", "OHLC").replace("FXTRADE", "OANDA").replace("||", " ");
  3266. if (name.indexOf("PROFIT_LINE") != -1) {
  3267. name = "PROFIT";
  3268. }
  3269. name = name.split("|");
  3270. if (name.length == 1) {
  3271. return name[0];
  3272. }
  3273. var pre = name.shift();
  3274. return pre + " (" + name.join(" , ") + ")";
  3275. }
  3276. Plot.prototype.lastData = function() {
  3277. var data = this.view.model.getDataReader(this.name).last();
  3278. if (typeof data === "undefined") {
  3279. return "";
  3280. }
  3281. try {
  3282. var yunit = this.axis.viewconfig.y.axis_option.unit;
  3283. } catch (e) {
  3284. return "";
  3285. }
  3286. var ret = [];
  3287. if (is_array(data)) {
  3288. for (var i = 0; i < data.length; i++) {
  3289. ret[i] = this.grid.getText(0, data[i], yunit);
  3290. }
  3291. return ret;
  3292. } else if (!isNaN(Number(data))) {
  3293. return this.grid.getText(0, data, yunit);
  3294. } else {
  3295. return data;
  3296. }
  3297. }
  3298. Plot.prototype.setParam = function(param) {
  3299. if (param.length >= 3) {
  3300. this.param = this.parseParam(param[2]);
  3301. }
  3302. }
  3303. Plot.prototype.parseParam = function(pstr) {
  3304. pstr = pstr.split(",");
  3305. var ret = {};
  3306. for (var i = 0; i < pstr.length; i++) {
  3307. var tmp = pstr[i].split("=", 2);
  3308. ret[tmp[0]] = tmp[1];
  3309. }
  3310. return ret;
  3311. }
  3312. Plot.prototype.lastDataShow = function() {
  3313. var data = this.lastData();
  3314. if (is_array(data)) {
  3315. return data.join(", ");
  3316. }
  3317. return data;
  3318. }
  3319. //价格标线
  3320. Plot.prototype.priceFlag = function(close_price, conf) {
  3321. var close_y = this.axis.getY(close_price);
  3322. drawWithArrowheads(this.grid.xEnd.x-14,close_y,this.grid.xEnd.x+30,close_y,this.ctx);
  3323. // drawRow(this.ctx, new Point(this.grid.xEnd.x , close_y), 10, conf.lineColor, 1);
  3324. //能直接访问grid的内容
  3325. var height = conf.bg.height / 2;
  3326. if (close_y >= 0 && close_y - this.grid.O.y < height) {
  3327. close_y = this.grid.O.y + height;
  3328. }
  3329. if (close_y <= this.grid.xyEnd.y && this.grid.xyEnd.y - close_y < height) {
  3330. close_y = this.grid.xyEnd.y - height;
  3331. }
  3332. conf.unit = this.yunit;
  3333. writeTextOption(this.ctx, new Point(this.grid.xEnd.x-6, close_y), close_price, conf);
  3334. }
  3335. function Shape(ctx, width, height, opt) {
  3336. this.ctx = ctx;
  3337. this.width = width ? width : 0;
  3338. this.height = height ? height : 70;
  3339. if (!opt) {
  3340. opt = {};
  3341. }
  3342. this.boder = opt.boder ? opt.boder : "black";
  3343. this.fill = opt.fill ? opt.fill : "black";
  3344. this.cta = opt.cta ? opt.cta : 0;
  3345. }
  3346. __symbol__list__ = {
  3347. // "BTYBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.001 },
  3348. // "BTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 },
  3349. "BCCBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 },
  3350. "ETHBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 },
  3351. "ETCBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 },
  3352. // "SC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.0001 },
  3353. // "WTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.0001 },
  3354. // "NYCC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.001 },
  3355. // "BTS": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.001 },
  3356. "LTCBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 },
  3357. "ZECBTC": { "time": ["M1", "M2", "M3", "M4", "M5", "M15", "M30", "H1", "H2", "H4", "D1", "W1", "MN1"], "yunit": 0.01 }
  3358. }
  3359. function ToolBar(controller) {
  3360. this.controller = controller;
  3361. this.pair = this.controller.pair;
  3362. // this.initPair();
  3363. // this.hideSymbol(); //隐藏没有数据的货币对
  3364. this.config = Config.getInstance();
  3365. this.api=this.controller.api;
  3366. this.isenable = true;
  3367. }
  3368. ToolBar.prototype.deinit = function() {
  3369. }
  3370. //显示出BTY 和ETH标签
  3371. ToolBar.prototype.initPair = function() {
  3372. // $("#symbol").html('');
  3373. for (var c in this.pair) {
  3374. if (!is_object(this.pair[c])) {
  3375. continue;
  3376. }
  3377. }
  3378. }
  3379. ToolBar.prototype.enable = function() {
  3380. $("#toolbar").show();
  3381. this.isenable = true;
  3382. }
  3383. ToolBar.prototype.disable = function() {
  3384. $("#toolbar").hide();
  3385. this.isenable = false;
  3386. }
  3387. ToolBar.prototype.hideSymbol = function() {
  3388. var _this = this;
  3389. $("#symbol2").find("li").each(
  3390. function() {
  3391. var text = $(this).text();
  3392. text = $.trim(text);
  3393. $(this).show();
  3394. if (typeof _this.pair[text] !== "object") {
  3395. $(this).hide();
  3396. }
  3397. }
  3398. );
  3399. }
  3400. ToolBar.prototype.hidePeriod = function(c) {
  3401. var _this = this;
  3402. if (!c) return;
  3403. var _timeList = _this.pair[c];
  3404. if (!_timeList) return;
  3405. _timeList = _timeList.time;
  3406. _timeMap = {};
  3407. for (var i = 0; i < _timeList.length; i++) {
  3408. _timeMap[_timeList[i]] = 1;
  3409. }
  3410. $("#period").find("li").each(
  3411. function() {
  3412. var text = $(this).text();
  3413. text = $.trim(text);
  3414. $(this).show();
  3415. if (_timeMap[text] !== 1) {
  3416. $(this).hide();
  3417. }
  3418. }
  3419. );
  3420. }
  3421. ToolBar.prototype.init = function() {
  3422. this.InitIndicatorstatus();
  3423. //添加事件
  3424. var _this=this;
  3425. $("#Indicator_list label").click(function () {
  3426. var name=$(this).text();
  3427. _this.IndicatorStatusChange(this);
  3428. })
  3429. // $("#Indicator_list li").click(function () {
  3430. // var name=$(this).attr('name');
  3431. // if($(this).find('a').attr('class')=='active'){
  3432. // $(this).find('a').removeClass('active');
  3433. // }
  3434. // else{
  3435. // $(this).find('a').addClass('active');
  3436. // }
  3437. // _this.IndicatorStatusChange(name);
  3438. // })
  3439. //bty,eth选择切换
  3440. $("#symbol2 a").click(function(){
  3441. $("#symbol2 a").removeClass("active");
  3442. var uid=$.cookie().id;
  3443. $(this).addClass("active");
  3444. _this.newsymbol(this);
  3445. });
  3446. $("#getsymbol").click(function(){
  3447. console.log($.cookie('symbol'));
  3448. if(sessionStorage.getItem('symbol')=='YCC'){
  3449. HTML5StockChartAPI.API.setPair('NYCC', sessionStorage.getItem('period'));
  3450. }else{
  3451. HTML5StockChartAPI.API.setPair($.cookie('symbol'), sessionStorage.getItem('period'));
  3452. }
  3453. })
  3454. $("#ethsymbol").click(function(){
  3455. HTML5StockChartAPI.API.setPair("ETHBTC", $.cookie('period'));
  3456. })
  3457. $("#etcsymbol").click(function(){
  3458. HTML5StockChartAPI.API.setPair("ETCBTC", $.cookie('period'));
  3459. })
  3460. $("#bccsymbol").click(function(){
  3461. HTML5StockChartAPI.API.setPair("BCCBTC", $.cookie('period'));
  3462. })
  3463. /* $("#Indicator_list a").click(function(){
  3464. var name=$(this).text();
  3465. _this.IndicatorStatusChange(name);
  3466. });*/
  3467. $("#period li").click(function() {
  3468. $("#period a").removeClass("active");
  3469. _this.period(this);
  3470. });
  3471. $("#plot_area").bind('click', function() {
  3472. _this.toolList();
  3473. });
  3474. $('body').not($("#plot_area")).unbind('mouseover', function() {
  3475. // console.log($(this));
  3476. $('body').css("cursor", "hand");
  3477. _this.toolList();
  3478. //$("#dropzone").slideUp("normal");
  3479. });
  3480. // this.addSelectEvent($("#symbol2"), this.symbol);
  3481. this.addSelectEvent($("#period"), this.period);
  3482. //this.addSelectEvent($("#tool_list"), this.toolList);//加号功能,指标
  3483. this.addClickEvent($("#zoom"), this.zoom);
  3484. //选择:
  3485. ToolBar.selectItem($("#period"), $.cookie('period'));
  3486. }
  3487. ToolBar.prototype.InitIndicatorstatus = function() {
  3488. // console.log("this.api:"+this.api);
  3489. var inds = $.cookie('ind');
  3490. if (this.config.Global.TPL[inds]) {
  3491. inds = this.config.Global.TPL[inds];
  3492. }
  3493. if (inds.indexOf("ma|main|") != -1) {
  3494. this.SetIndicatorStatus("MA");
  3495. }
  3496. if (inds.indexOf("macd|main|") != -1) {
  3497. this.SetIndicatorStatus("MACD");
  3498. }
  3499. if (inds.indexOf("volumes") != -1) {
  3500. this.SetIndicatorStatus("VOLUMES");
  3501. }
  3502. if (inds.indexOf("bolling") != -1) {
  3503. this.SetIndicatorStatus("BOLLING");
  3504. }
  3505. if (inds.indexOf("kdj") != -1) {
  3506. this.SetIndicatorStatus("KDJ");
  3507. }
  3508. }
  3509. ToolBar.prototype.SetIndicatorStatus = function(indname) {
  3510. $("#Indicator_list label").each(function() {
  3511. if ($(this).text() == indname) {
  3512. $(this).addClass("active");
  3513. }
  3514. });
  3515. }
  3516. ToolBar.prototype.IndicatorStatusChange = function(obj) {
  3517. var name=$(obj).text();
  3518. if($(obj).attr("class")=='active'){
  3519. $(obj).removeClass('active');
  3520. }
  3521. else{
  3522. $(obj).addClass('active')
  3523. }
  3524. var indstr = "main:";
  3525. $("#Indicator_list label").each(function(){
  3526. if ($(this).attr("class")=='active') {
  3527. switch ($(this).text()) {
  3528. case "MA":
  3529. indstr += Config.getInstance().Global.TPL["ma"];
  3530. break;
  3531. case "VOLUMES":
  3532. indstr += Config.getInstance().Global.TPL["volumes"];
  3533. break;
  3534. case "MACD":
  3535. indstr += Config.getInstance().Global.TPL["macd"];
  3536. break;
  3537. case "BOLLING":
  3538. indstr += Config.getInstance().Global.TPL["bolling"];
  3539. break;
  3540. case "KDJ":
  3541. indstr += Config.getInstance().Global.TPL["kdj"];
  3542. break;
  3543. }
  3544. }
  3545. })
  3546. // var indstr = "main:";
  3547. // var indstr = this.api.read('ind');
  3548. // if(this.config.Global.TPL[indstr]) {
  3549. // indstr = this.config.Global.TPL[indstr];
  3550. // }
  3551. // switch (obj) {
  3552. // case "MA":
  3553. // indstr += Config.getInstance().Global.TPL["ma"];
  3554. // break;
  3555. // case "VOLUMES":
  3556. // indstr += Config.getInstance().Global.TPL["volumes"];
  3557. // break;
  3558. // case "MACD":
  3559. // indstr += Config.getInstance().Global.TPL["macd"];
  3560. // break;
  3561. // case "BOLLING":
  3562. // indstr += Config.getInstance().Global.TPL["bolling"];
  3563. // break;
  3564. // case "KDJ":
  3565. // indstr += Config.getInstance().Global.TPL["kdj"];
  3566. // break;
  3567. // }
  3568. // console.log("IndicatorStatusChange:"+name);
  3569. // var indstr = "main:";
  3570. // // 选中那个a 标签就执行什么
  3571. // $("input[name = Indicator]:checkbox").each(function() {
  3572. // if ($(this).is(":checked")) {
  3573. // switch ($(this).val()) {
  3574. // case "MA":
  3575. // indstr += Config.getInstance().Global.TPL["ma"];
  3576. // break;
  3577. // case "VOLUMES":
  3578. // indstr += Config.getInstance().Global.TPL["volumes"];
  3579. // break;
  3580. // case "MACD":
  3581. // indstr += Config.getInstance().Global.TPL["macd"];
  3582. // break;
  3583. // case "BOLLING":
  3584. // indstr += Config.getInstance().Global.TPL["bolling"];
  3585. // break;
  3586. // case "KDJ":
  3587. // indstr += Config.getInstance().Global.TPL["kdj"];
  3588. // break;
  3589. // }
  3590. // }
  3591. // });
  3592. this.api.setInd(indstr);
  3593. }
  3594. ToolBar.prototype.signal = function(obj) {
  3595. var signal_id = $.trim(obj.attr('name'));
  3596. //write cookie of signal
  3597. api.setSignal(signal_id);
  3598. }
  3599. ToolBar.prototype.model = function(obj) {
  3600. var model_id = $.trim(obj.attr('name'));
  3601. //write cookie of model
  3602. api.setModel(model_id);
  3603. }
  3604. ToolBar.prototype.tplswitch = function(obj) {
  3605. var tpl = $.trim(obj.attr('name'));
  3606. if (tpl == "none") return;
  3607. var api = HTML5StockChartAPI.API;
  3608. api.setIndicatorConf(tpl);
  3609. }
  3610. ToolBar.tplselect = function(name) {
  3611. ToolBar.selectItem($("#tpl_list"), name);
  3612. //alert(name);
  3613. }
  3614. ToolBar.prototype.clickFirst = function(obj) {
  3615. var obj = obj.find("li");
  3616. for (var i = 0; i < obj.length; i++) {
  3617. var item = $(obj.get(i));
  3618. if (item.css("display") == "none") {
  3619. continue;
  3620. }
  3621. item.click();
  3622. break;
  3623. }
  3624. }
  3625. ToolBar.prototype.clickByName = function(obj, name) {
  3626. var obj = obj.find("li");
  3627. for (var i = 0; i < obj.length; i++) {
  3628. var item = $(obj.get(i));
  3629. if ($.trim(item.text()) == name) {
  3630. item.click();
  3631. break;
  3632. }
  3633. }
  3634. }
  3635. ToolBar.prototype.clickByLiName = function(obj, name) {
  3636. var obj = obj.find("li");
  3637. for (var i = 0; i < obj.length; i++) {
  3638. var item = $(obj.get(i));
  3639. if (item.attr("name") == name) {
  3640. item.click();
  3641. break;
  3642. }
  3643. }
  3644. }
  3645. ToolBar.prototype.symbol = function(obj) {
  3646. var c = $.trim(obj.text());
  3647. //c="MAC";
  3648. var c = this.findSelected($("#symbol2"));
  3649. //if(c = "ETH") window.location.href="http://33.cn/ethcny";
  3650. //if(c = "BTY") window.location.href="http://33.cn/";
  3651. this.hidePeriod(c); //隐藏没有数据的时间周期
  3652. var p = this.findSelected($("#period"));
  3653. $.cookie('period',p);
  3654. // console.log("p=", p);
  3655. if (!p) {
  3656. //this.clickFirst($("#period"));
  3657. HTML5StockChartAPI.API.setPair(c, this.controller.p);
  3658. } else {
  3659. HTML5StockChartAPI.API.setPair(c, p);
  3660. }
  3661. }
  3662. ToolBar.prototype.newsymbol = function(obj) {
  3663. var c = $(obj).attr("name");
  3664. if ($.cookie('symbol') != c) {
  3665. $.cookie("symbol", null);
  3666. $.cookie("symbol", c);
  3667. }
  3668. //$("#period").children().first();
  3669. // $("#period").children().first().text(c);
  3670. //c="MAC";
  3671. //var c = this.findSelected($("#symbol"));
  3672. //if(c = "ETH") window.location.href="http://33.cn/ethcny";
  3673. //if(c = "BTY") window.location.href="http://33.cn/";
  3674. // this.hidePeriod(c); //隐藏没有数据的时间周期
  3675. var p = this.findSelected($("#period"));
  3676. $.cookie('period',p);
  3677. // console.log("p=", p);
  3678. if (!p) {
  3679. //this.clickFirst($("#period"));
  3680. HTML5StockChartAPI.API.setPair(c, this.controller.p);
  3681. } else {
  3682. HTML5StockChartAPI.API.setPair(c, p);
  3683. }
  3684. }
  3685. ToolBar.prototype.toolList = function(obj) {
  3686. var name = obj.attr("name");
  3687. var _this = this;
  3688. if (name == "cross") //cross情况
  3689. {
  3690. $("#plot_area").css("cursor", "crosshair");
  3691. var view = this.controller.view;
  3692. if (window["FlashCanvas"]) {
  3693. var count = 5;
  3694. } else {
  3695. var count = 2;
  3696. }
  3697. var crossMoveInterval = new IntervalEvent(
  3698. count,
  3699. function(controller, recall) //可以重新被call
  3700. {
  3701. var _this = controller.view;
  3702. if (typeof recall == "undefined") {
  3703. _this.draw();
  3704. }
  3705. if (!this.value || this.value.length != 3) {
  3706. return;
  3707. }
  3708. var x = this.value[0];
  3709. var y = this.value[1];
  3710. var index = this.value[2];
  3711. for (var i = 0; i < _this.canvasActiveCount; i++) {
  3712. _this.grid[i].drawCrossX(x, _this.axis[0]);
  3713. }
  3714. _this.grid[index].drawCrossY(y);
  3715. }
  3716. );
  3717. for (var i = 0; i < view.canvasActiveCount; i++) {
  3718. view.canvas[i].bind("mousemove", crossMoveInterval, this.crossMove);
  3719. }
  3720. //if the page is redraw, call it by controller.recall(). now, only new tick
  3721. //redraw need to recall.
  3722. this.controller.addIntervalEvent("crossMove", crossMoveInterval, true);
  3723. $(document).bind("mouseover", function(e) {
  3724. // console.log(e.target);
  3725. $("body").css("cursor", "default");
  3726. for (var i = 0; i < view.canvasActiveCount; i++) {
  3727. view.canvas[i].unbind("mousemove", _this.crossMove);
  3728. }
  3729. view.draw();
  3730. _this.controller.removeIntervalEvent("crossMove");
  3731. _this.clickByLiName($("#tool_list"), "none");
  3732. $(document).unbind("mouseover");
  3733. });
  3734. } else if (name == "kline_first") { //
  3735. var view = this.config.Global.View;
  3736. for (var key in view) {
  3737. if (is_object(view[key]) && typeof view[key].disable_axis_area !== "undefined") {
  3738. view[key].disable_axis_area = 1;
  3739. }
  3740. }
  3741. this.controller.draw();
  3742. } else if (name == "ind_first") {
  3743. var view = this.config.Global.View;
  3744. for (var key in view) {
  3745. if (is_object(view[key]) && typeof view[key].disable_axis_area !== "undefined") {
  3746. view[key].disable_axis_area = 0;
  3747. }
  3748. }
  3749. this.controller.draw();
  3750. } else if (name == "indicator") {
  3751. $("#tool_list").find("li[name='indicator']").css('cursor', 'pointer');
  3752. indicator.show();
  3753. } else if (name == "tick_price") {
  3754. }
  3755. }
  3756. ToolBar.prototype.toolList = function() {
  3757. var _this = this;
  3758. $("#plot_area").css("cursor", "crosshair");
  3759. this.controller=this.api.controller;
  3760. var view = this.controller.view;
  3761. if (window["FlashCanvas"]) {
  3762. var count = 5;
  3763. } else {
  3764. var count = 2;
  3765. }
  3766. var crossMoveInterval = new IntervalEvent(
  3767. count,
  3768. function(controller, recall) //可以重新被call
  3769. {
  3770. var _this = controller.view;
  3771. if (typeof recall == "undefined") {
  3772. _this.draw();
  3773. }
  3774. if (!this.value || this.value.length != 3) {
  3775. return;
  3776. }
  3777. var x = this.value[0];
  3778. var y = this.value[1];
  3779. var index = this.value[2];
  3780. for (var i = 0; i < _this.canvasActiveCount; i++) {
  3781. _this.grid[i].drawCrossX(x, _this.axis[0]);
  3782. }
  3783. _this.grid[index].drawCrossY(y);
  3784. }
  3785. );
  3786. for (var i = 0; i < view.canvasActiveCount; i++) {
  3787. view.canvas[i].bind("mousemove", crossMoveInterval, this.crossMove);
  3788. }
  3789. //if the page is redraw, call it by controller.recall(). now, only new tick
  3790. //redraw need to recall.
  3791. this.controller.addIntervalEvent("crossMove", crossMoveInterval, true);
  3792. $(document).bind("mouseover", function(e) {
  3793. $("#plot_area").css("cursor", "default");
  3794. if(e.target.id.indexOf("plot")==-1){
  3795. for (var i = 0; i < view.canvasActiveCount; i++) {
  3796. view.canvas[i].unbind("mousemove", _this.crossMove);
  3797. }
  3798. view.draw();
  3799. _this.controller.removeIntervalEvent("crossMove");
  3800. _this.clickByLiName($("#tool_list"), "none");
  3801. $(document).unbind("mouseover");
  3802. }
  3803. });
  3804. }
  3805. ToolBar.prototype.crossMove = function(event) {
  3806. var crossMoveInterval = event.data;
  3807. var id = $(this).attr("id");
  3808. var index = id.split("_").pop();
  3809. index = index.substr(0, index.length - 1);
  3810. index = parseInt(index);
  3811. var x = event.pageX - $(this).offset().left;
  3812. var y = event.pageY - $(this).offset().top;
  3813. crossMoveInterval.setVal([x, y, index]);
  3814. }
  3815. ToolBar.prototype.period = function(obj) {
  3816. var c =$.cookie('symbol');
  3817. if ($(obj).find("a").length ==1) {
  3818. var p = $.trim($(obj).text());
  3819. $.cookie('period',p);
  3820. } else {
  3821. // $(obj).find("a").setAttribute('class','active');
  3822. var elemt = obj.firstChild;
  3823. elemt.setAttribute('class', 'active');// obj拿到的是类似<li name="M1" class="period"><a href="#">M1</a></li>,所以需要拿到M1也就是a标签下的text
  3824. var p = $.trim($(elemt).text());
  3825. $.cookie('period',p);
  3826. $.cookie('period',p);
  3827. }
  3828. // console.log("period:"+p)
  3829. HTML5StockChartAPI.API.setPair(c, p);
  3830. /* if (!c) {
  3831. return; //没有意义,直接忽略
  3832. } else {
  3833. HTML5StockChartAPI.API.setPair("MAC", p);
  3834. }*/
  3835. }
  3836. ToolBar.prototype.zoom = function(obj) {
  3837. var name = obj.attr("name");
  3838. if (name == "in") {
  3839. this.controller.zoomIn();
  3840. } else if (name == "out") {
  3841. this.controller.zoomOut();
  3842. }
  3843. }
  3844. ToolBar.prototype.style = function(obj) {
  3845. var name = obj.attr("name");
  3846. set_style(name);
  3847. this.controller.draw();
  3848. }
  3849. ToolBar.prototype.findSymbolSelected = function(obj) {
  3850. var text = "";
  3851. $(obj).find("a").each(function() {
  3852. if ($(this).attr("class") == "active") {
  3853. text = $(this).attr("name");
  3854. }
  3855. })
  3856. // console.log("findSymbolSelected:"+$.trim(text));
  3857. return $.trim(text);
  3858. }
  3859. ToolBar.prototype.findSelected = function(obj) {
  3860. var text = obj.find("li > strong").text();
  3861. return $.trim(text);
  3862. }
  3863. ToolBar.prototype.addSelectEvent = function(obj, callback) {
  3864. //获取li
  3865. var _this = this;
  3866. var _obj = obj.find("li");
  3867. _obj.each(
  3868. function() {
  3869. var __callback = callback;
  3870. var __obj = _obj;
  3871. $(this).bind("click", _this,
  3872. function(event) {
  3873. var _this = event.data;
  3874. __obj.each(
  3875. function() {
  3876. var text = $(this).text();
  3877. text = $.trim(text);
  3878. // $(this).html("<a href=\"javascript:void(0)\">" + text + "</a>");
  3879. }
  3880. );
  3881. $(this).html('<a class="active" >' + $.trim($(this).text()) + '</a>');
  3882. if (__callback) __callback.call(_this, $(this));
  3883. }
  3884. );
  3885. }
  3886. );
  3887. }
  3888. ToolBar.prototype.addClickEvent = function(obj, callback) {
  3889. var _this = this;
  3890. var _obj = obj.find("li");
  3891. _obj.each(
  3892. function() {
  3893. var __callback = callback;
  3894. $(this).bind("click", _this,
  3895. function(event) {
  3896. var _this = event.data;
  3897. if (__callback) __callback.call(_this, $(this))
  3898. }
  3899. );
  3900. }
  3901. );
  3902. }
  3903. //select item , not trigger event.
  3904. ToolBar.selectItem = function(obj, name) {
  3905. var __obj = obj.find("li");
  3906. var _this = obj.find("li[name='" + name + "']");
  3907. __obj.each(
  3908. function() {
  3909. var text = $(this).text();
  3910. text = $.trim(text);
  3911. $(this).html("<a href=\"javascript:void(0)\">" + text + "</a>");
  3912. }
  3913. );
  3914. //alert(_this.length);
  3915. $(_this).html('<a class="active">' + $.trim($(_this).text()) + '</a>');
  3916. }
  3917. //view 视图,负责绘制图形。
  3918. //控制器把从model 读取数据后,做处理完成。然后更新到view里面。
  3919. //view 再利用这些数据,绘制出图形,view 不能直接读取model 的数据。
  3920. //而是读取control 的数据,这样有一个中间的层次,便于扩展。
  3921. //view 没有c . p 的概念。每个图形的model都会有一个getData接口。
  3922. //每个图形的 view 都有一个setData 的接口。
  3923. //关于图形的显示格式。我想任何选项,包括view 包括 model的都通过
  3924. //更改config的形式来实现。对象本身只是读取配置,不提供更改接口。
  3925. //比如:view 的样式的修改。每次在之前会读取配置。
  3926. //比如:model改成静态图形了,也是类似的修改配置,就可以自动完成。
  3927. //在不同对象之间传递配置信息过于繁琐。我想直接读取配置是最好的方式。
  3928. //
  3929. function View(controller) {
  3930. //当前的图像
  3931. this.controller = controller;
  3932. this.model = this.controller.model;
  3933. this.config = Config.getInstance();
  3934. this.plot_area = this.controller.plot_area;
  3935. this.setPlotArea();
  3936. this.canvas = [];
  3937. this.canvasBG = [];
  3938. this.canvasFront = [];
  3939. this.canvasContainer = [];
  3940. this.resize = [];
  3941. this.grid = [];
  3942. this.axis = [];
  3943. //给每个canvas分配一个grid对象
  3944. var main_axis = new Axis(null);
  3945. for (var i = 0; i < this.config.Global.maxCanvasCount; i++) {
  3946. var prefix = "#" + this.config.Global.canvasIDPerfix + i;
  3947. var id = prefix + "2";
  3948. var bg = prefix + "1";
  3949. var front = prefix + "0";
  3950. var id_div = "#" + this.config.Global.canvasIDPerfix + "div" + "_" + i;
  3951. //canvas
  3952. var tmp = $(id);
  3953. if (!tmp) {
  3954. continue;
  3955. }
  3956. if (!this.config.isIE6) {
  3957. tmp.hide();
  3958. }
  3959. this.canvas.push(tmp);
  3960. this.canvasBG.push($(bg).hide());
  3961. this.canvasFront.push($(front).hide());
  3962. this.canvasContainer.push($(prefix).hide());
  3963. //resize
  3964. var resize = $(id_div);
  3965. resize.hide();
  3966. this.resize.push(resize);
  3967. if (i == 0) { //主图
  3968. var axis_obj = main_axis;
  3969. } else {
  3970. var axis_obj = new Axis(main_axis);
  3971. }
  3972. this.axis.push(axis_obj);
  3973. this.grid.push(new PlotGrid(this, i));
  3974. }
  3975. //设置宽度
  3976. this.setWidth();
  3977. this.setHeight();
  3978. set_style();
  3979. //主图被注册了
  3980. this.canvasActiveCount = 1;
  3981. //判断兼容性
  3982. if (!check_textRender(this.canvas[0])) {
  3983. //console.log('loading stroke text' + __baseurl__ + "js/strokeText.js");
  3984. //include(__baseurl__ + "js/strokeText.js");
  3985. }
  3986. this.plot = {};
  3987. this.plotindex = {};
  3988. this.plotArea = {};
  3989. this.plotArea[this.config.mainName] = true;
  3990. this.viewconfig = [];
  3991. //注册主图
  3992. this.registerPlot(this.config.mainName, null, true, this.controller.ind[this.config.mainName].param);
  3993. }
  3994. View.prototype.deinit = function() {
  3995. }
  3996. View.prototype.setPlotArea = function(fixd) {
  3997. if (this.plot_area != window) {
  3998. var pa = $(this.plot_area);
  3999. this.plotWidth = pa.attr("fw") ? pa.attr("fw") : pa.width();
  4000. this.plotHeight = pa.attr("fh") ? pa.attr("fh") : pa.height();
  4001. $("#plot_area").height(this.plotHeight);
  4002. $("#plot_area").width(this.plotWidth);
  4003. $("#plot_content").show();
  4004. return;
  4005. }
  4006. if (!fixd) {
  4007. fixd = {};
  4008. fixd.x = 10;
  4009. fixd.y = 3;
  4010. if (this.config.browser == "ie" && this.config.bversion[0] >= 8) {
  4011. fixd.y = 8;
  4012. }
  4013. }
  4014. $("#plot_content").hide();
  4015. this.plotWidth = $(this.plot_area).width() - fixd.x;
  4016. this.offsetHeight = $("#plot_area").offset().top;
  4017. this.plotHeight = $(this.plot_area).height() - this.offsetHeight - fixd.y;
  4018. $("#plot_area").height(this.plotHeight + 1);
  4019. $("#plot_area").width($(this.plot_area).width());
  4020. if (this.plotWidth < 200) this.plotWidth = 200;
  4021. if (this.plotHeight < 100) this.plotHeight = 100;
  4022. $("#plot_content").show();
  4023. }
  4024. View.prototype.setWidth = function(w) {
  4025. if (!w) {
  4026. w = this.plotWidth;
  4027. }
  4028. for (var i = 0; i < this.config.Global.maxCanvasCount; i++) {
  4029. set_width(this.canvas[i], w);
  4030. set_width(this.canvasBG[i], w);
  4031. set_width(this.canvasFront[i], w);
  4032. set_width(this.resize[i], w);
  4033. this.grid[i].setWidth(w);
  4034. }
  4035. }
  4036. View.prototype.setHeight = function() {
  4037. // console.log()
  4038. for (var i = 0; i < this.config.Global.maxCanvasCount; i++) {
  4039. set_height(this.canvas[i], 1);
  4040. }
  4041. }
  4042. View.prototype.init = function() {
  4043. //注册全局事件
  4044. //resize 和 canvas 的事件放在grid中
  4045. this.lastW = $(this.plot_area).width();
  4046. this.lastH = $(this.plot_area).height();
  4047. $(document).bind("keydown", this, this.keydown);
  4048. $(document).bind("keyup", this, this.keyup);
  4049. $(this.plot_area).bind("resize", this, this.resizeWindow);
  4050. var _this = this;
  4051. _this.wheelEvent = new IntervalEvent(3,
  4052. function(controller) {
  4053. var mainName = controller.config.mainName;
  4054. var one = controller.view.plot[mainName].getOneSize();
  4055. var offset = Math.round(-this.value * 40 / one);
  4056. controller.startOffset(offset);
  4057. controller.draw();
  4058. }
  4059. );
  4060. this.controller.addIntervalEvent("wheelEvent", _this.wheelEvent);
  4061. var wheelobj;
  4062. if (this.plot_area == window) {
  4063. wheelobj = document;
  4064. } else {
  4065. wheelobj = this.plot_area;
  4066. }
  4067. $(wheelobj).mousewheel(
  4068. function(event, delta)
  4069. {
  4070. var e = window.event||event;
  4071. console.log("滚轮事件:"+e)
  4072. if (e.wheelDelta == 120) {
  4073. _this.controller.zoomIn();
  4074. return true;
  4075. } else if (e.wheelDelta == -120) {
  4076. _this.controller.zoomOut();
  4077. return true;
  4078. }
  4079. if (e.detail == -3) {
  4080. _this.controller.zoomIn();
  4081. return true;
  4082. } else if (e.detail == 3) {
  4083. _this.controller.zoomOut();
  4084. return true;
  4085. }
  4086. if (e.originalEvent.deltaY == -3) {
  4087. _this.controller.zoomIn();
  4088. return true;
  4089. } else if (e.originalEvent.deltaY == 3) {
  4090. _this.controller.zoomOut();
  4091. return true;
  4092. }
  4093. //return false;
  4094. }
  4095. );
  4096. //注册十字光标事件
  4097. }
  4098. View.prototype.registerPlot = function(name, index, has_plot_area, param) {
  4099. if (this.config[name] && !this.plot[name]) {
  4100. var Plot = this.config[name].plot;
  4101. var index = this.getCanvas(name, index);
  4102. this.plot[name] = new Plot(this, this.grid[index], name);
  4103. if (param) this.plot[name].setParam(param);
  4104. if(index==0){
  4105. this.canvas[index].css('display', 'block');
  4106. this.canvasBG[index].css('display', 'block');
  4107. this.canvasFront[index].css('display', 'block');
  4108. // this.canvas[index].css('padding-top', '60px');
  4109. // this.canvasBG[index].css('padding-top', '60px');
  4110. // this.canvasFront[index].css('padding-top', '60px');
  4111. }
  4112. else{
  4113. this.canvas[index].css('display', 'block');
  4114. this.canvasBG[index].css('display', 'block');
  4115. this.canvasFront[index].css('display', 'block');
  4116. // this.canvas[index].css('padding-top', '10px');
  4117. // this.canvasBG[index].css('padding-top', '10px');
  4118. // this.canvasFront[index].css('padding-top', '10px');
  4119. }
  4120. this.canvasContainer[index].css('display', 'block');
  4121. this.resize[index].show();
  4122. this.plotindex[name] = index;
  4123. if (has_plot_area) {
  4124. this.plotArea[name] = has_plot_area;
  4125. }
  4126. this.grid[index].addPlot(name, this.plot[name]);
  4127. this.setLast();
  4128. }
  4129. }
  4130. View.prototype.isSeperatePlot = function(name) {
  4131. if (!this.config.Global.View[name]) {
  4132. return null;
  4133. }
  4134. return this.config.Global.View[name].sep;
  4135. }
  4136. View.prototype.setLast = function() {
  4137. for (var i = 0; i < this.canvasActiveCount; i++) {
  4138. this.grid[i].clearLast();
  4139. }
  4140. this.grid[this.canvasActiveCount - 1].setLast();
  4141. }
  4142. View.prototype.unregisetPlot = function(name) {
  4143. this.plot[name] = null;
  4144. this.plotindex[name] = null;
  4145. this.setLast();
  4146. var index = this.plotindex[name];
  4147. this.grid[index].removePlot(name);
  4148. }
  4149. View.prototype.draw = function() {
  4150. //draw grid
  4151. //绘制Y轴
  4152. for (var i = 0; i < this.canvasActiveCount; i++) {
  4153. if (is_object(this.grid[i])) {
  4154. if (this.data[i].axis.y.axis) {
  4155. this.grid[i].drawBg();
  4156. this.grid[i].drawY();
  4157. this.grid[i].drawX(this.axis[0]);
  4158. //画canvas分割折线
  4159. var ctx = this.grid[i].ctx;
  4160. if(i != this.canvasActiveCount - 1){
  4161. drawLever(ctx,this.grid[i].xEnd.x-20,this.grid[i].yEnd.y-2,'#999',10,10);
  4162. drawLever(ctx,this.grid[i].xEnd.x-20,this.grid[i].yEnd.y+2,'#999',10,-10);
  4163. }
  4164. //绘制底部线条
  4165. // this.grid[i].drawLine(this.ctx, data.x, data.y, color);
  4166. //this.grid[i].drawBoder(this.axis[0]);
  4167. } else {
  4168. this.grid[i].drawBg();
  4169. this.grid[i].drawX(this.axis[0]);
  4170. // drawLever(ctx,this.grid[i].xEnd.x,this.grid[i].yEnd.y,'#999',10,10);
  4171. //绘制底部线条
  4172. //this.grid[i].drawBoder(this.axis[0]);
  4173. }
  4174. }
  4175. if (i == this.canvasActiveCount - 1) {
  4176. //画线
  4177. //绘制底线没有其他图层了画线
  4178. var ctx = this.grid[i].ctx;
  4179. ctx.beginPath();
  4180. ctx.moveTo(this.grid[i].O.x, this.grid[i].yEnd.y+20 - this.grid[i].O.y);
  4181. ctx.lineTo(this.grid[i].xEnd.x, this.grid[i].yEnd.y+20 - this.grid[i].O.y);
  4182. ctx.closePath();
  4183. ctx.lineWidth = 0.3;
  4184. ctx.strokeStyle = "#fff";
  4185. ctx.stroke();
  4186. }
  4187. }
  4188. //绘制x。目前,x只需要绘制最后一个图形x轴部分
  4189. //开始绘制每个图形
  4190. for (i = 0; i < this.data.length; i++) {
  4191. var plot = this.data[i].data;
  4192. var text = "";
  4193. for (var key in plot) {
  4194. if (is_object(plot[key])) {
  4195. //坐标轴的选项对绘图中的 转换是有用的。在通过数字 转换
  4196. //成固定格式的数据的时候非常有用。比如时间转换,4舍五入等。
  4197. if (plot[key].x && plot[key].x.length > 0) {
  4198. this.plot[key].draw(plot[key]);
  4199. //顶部内容 update by fangxiao from 2016/6/29/17:47
  4200. // text += "[" + this.plot[key].getShowName() + " " + this.plot[key].lastDataShow() + "] ";
  4201. }
  4202. }
  4203. }
  4204. if (text.length > 0) {
  4205. // console.log(text);
  4206. this.grid[i].writeHeadText(text);
  4207. }
  4208. }
  4209. }
  4210. //获取坐标轴的配置:
  4211. //
  4212. //1.附图,那么要和主图对应,这样时间应该是通过查询产生的。所以,不需要提供配置。
  4213. //2.计算x轴,完全是利用主图的配置,这样计算主图的配置就可以了。
  4214. //
  4215. View.prototype.getAxisConfig = function() {
  4216. var one = this.plot[this.config.mainName].getOneSize(); //获取一个点占用的点数
  4217. var nx = this.config.Global.View[this.config.mainName].NXPixel; //x轴的数目推荐坐标的数目
  4218. var ny = this.config.Global.View[this.config.mainName].NYPixel; //x轴的数目推荐坐标的数目
  4219. var viewconfig = [];
  4220. for (var i = 0; i < this.canvasActiveCount; i++) {
  4221. if (is_object(this.grid[i])) {
  4222. viewconfig[i] = {};
  4223. var area = this.grid[i].getPlotArea();
  4224. var plotnum = Math.ceil((area.x.beg - area.x.end) / one);
  4225. viewconfig[i].plotnum = plotnum;
  4226. viewconfig[i].one = one;
  4227. viewconfig[i].x = {};
  4228. viewconfig[i].x.n = Math.round((area.x.beg - area.x.end) / nx);
  4229. viewconfig[i].x.beg = area.x.beg;
  4230. viewconfig[i].x.end = area.x.end;
  4231. viewconfig[i].y = {};
  4232. viewconfig[i].y.n = Math.round((area.y.beg - area.y.end) / ny);
  4233. viewconfig[i].y.beg = area.y.beg;
  4234. viewconfig[i].y.end = area.y.end;
  4235. }
  4236. }
  4237. for (var key in this.plotindex) {
  4238. var index = this.plotindex[key];
  4239. if (index === null) continue;
  4240. if (!viewconfig[index]) continue;
  4241. if (typeof viewconfig[index].plot === "undefined") viewconfig[index].plot = [];
  4242. viewconfig[index].plot.push(key);
  4243. }
  4244. this.viewconfig = viewconfig;
  4245. return viewconfig;
  4246. }
  4247. View.prototype.getAxis = function(name) {
  4248. var index = this.plotindex[name];
  4249. return this.axis[index];
  4250. }
  4251. View.prototype.getCanvas = function(name, index) {
  4252. //为指标和主函数分配canvas.
  4253. var plotconfig = this.config.Global.View;
  4254. //判断是否要增加canvas
  4255. if (name == this.config.mainName) {
  4256. this.grid[0].setHeight(this.plotHeight);
  4257. }
  4258. if ((typeof index !== "undefined") && index !== null && index < this.canvasActiveCount) {
  4259. return index;
  4260. }
  4261. if (!plotconfig[name] || !plotconfig[name].sep) {
  4262. return 0;
  4263. }
  4264. var h = this.getUnitHeight(name);
  4265. // console.log("getUnitHeight:"+h);
  4266. var index = this.setExistPlotHeight(h);
  4267. // console.log("getUnitHeight:"+h * plotconfig[name].height);
  4268. this.grid[index++].setHeight(h * plotconfig[name].height);
  4269. this.canvasActiveCount = index;
  4270. return index - 1;
  4271. }
  4272. //设置已经存在的图像的高度
  4273. View.prototype.setExistPlotHeight = function(unit_h) {
  4274. //设置所有的canvas 的高度为0
  4275. var plotconfig = this.config.Global.View;
  4276. for (i = 0; i < this.grid.length; i++) {
  4277. this.grid[i].setHeight(1);
  4278. }
  4279. this.grid[0].setHeight(unit_h);
  4280. var index = 1;
  4281. //返回新加入名称的canvas
  4282. for (var key in this.plot) {
  4283. if (is_object(this.plot[key])) {
  4284. if (key == this.config.mainName) continue; //主图, 直接pass
  4285. if (!plotconfig[key]) continue; //没有配置,直接pass
  4286. if (plotconfig[key].sep) { //分离
  4287. // console.log("unit_h * plotconfig[key].height:"+unit_h * plotconfig[key].height)
  4288. this.grid[index++].setHeight(unit_h * plotconfig[key].height);
  4289. }
  4290. }
  4291. }
  4292. return index;
  4293. //新图加在末尾
  4294. }
  4295. //新家图像
  4296. View.prototype.getUnitHeight = function(newname) {
  4297. var x = 1;
  4298. var plotconfig = this.config.Global.View;
  4299. for (var key in this.plot) {
  4300. if (is_object(this.plot[key])) {
  4301. if (key == this.config.mainName) continue; //主图, 直接pass
  4302. if (!plotconfig[key]) continue; //没有配置,直接pass
  4303. if (!this.plotArea[key]) {
  4304. continue;
  4305. }
  4306. if (plotconfig[key].sep) { //分离
  4307. x += plotconfig[key].height;
  4308. }
  4309. }
  4310. }
  4311. if (newname) {
  4312. x += plotconfig[newname].height;
  4313. }
  4314. var h = this.plotHeight * (1 / x);
  4315. return h;
  4316. }
  4317. View.prototype.clearData = function() {
  4318. this.data = [];
  4319. //清除原来的main值
  4320. this.axis[0].main = null;
  4321. for (var i = 0; i < this.canvasActiveCount; i++) {
  4322. this.axis[i].clearData();
  4323. }
  4324. }
  4325. View.prototype.updateData = function(data, index) {
  4326. var axis = this.axis[index];
  4327. axis.setViewConfig(this.viewconfig[index]);
  4328. axis.setData(data);
  4329. this.data[index] = axis.getData();
  4330. }
  4331. //这里的PlotGrid 的名字是暂时使用的,具体什么名字还没有取好
  4332. //因为事件主要是在plotgrid中处理,所以,我用了这个名字
  4333. View.prototype.keydown = function(event) {
  4334. var _this = event.data;
  4335. PlotGrid.setMoveInterval("key", _this.grid[0]);
  4336. debug("keydown");
  4337. if (event.keyCode == Key.KEY_NEXT) {
  4338. var offset = _this.controller.startSet("Next");
  4339. PlotGrid.moveQueue.push(offset);
  4340. return false;
  4341. } else if (event.keyCode == Key.KEY_PREV) {
  4342. var offset = _this.controller.startSet("Prev");
  4343. PlotGrid.moveQueue.push(offset);
  4344. return false;
  4345. } else if (event.keyCode == Key.KEY_PAGE_DOWN) {
  4346. var offset = _this.controller.startSet("PageDown");
  4347. PlotGrid.moveQueue.push(offset);
  4348. return false;
  4349. } else if (event.keyCode == Key.KEY_PAGE_UP) {
  4350. var offset = _this.controller.startSet("PageUp");
  4351. PlotGrid.moveQueue.push(offset);
  4352. return false;
  4353. } else if (event.keyCode == Key.KEY_HOME) {
  4354. var offset = _this.controller.startSet("Home");
  4355. PlotGrid.moveQueue.push(offset);
  4356. return false;
  4357. } else if (event.keyCode == Key.KEY_END) {
  4358. var offset = _this.controller.startSet("End");
  4359. PlotGrid.moveQueue.push(offset);
  4360. return false;
  4361. } else if (event.keyCode == Key.KEY_UP) {
  4362. _this.controller.zoomIn();
  4363. return false;
  4364. } else if (event.keyCode == Key.KEY_DOWN) {
  4365. _this.controller.zoomOut();
  4366. return false;
  4367. }
  4368. }
  4369. View.prototype.keyup = function(event) {
  4370. debug("keyup");
  4371. var _this = event.data;
  4372. PlotGrid.clearMoveInterval(_this.grid[0]);
  4373. }
  4374. View.prototype.resizeGrid = function(offset, index) {
  4375. debug("set resize offset " + offset);
  4376. if (offset == 0) return;
  4377. var grid1 = this.grid[index];
  4378. var grid2 = this.grid[index + 1];
  4379. // if(index==0){
  4380. // var margin1 = grid1.marginTop[grid1.TOP] + grid1.marginTop[grid1.BOTTOM];
  4381. // var margin2 = grid2.marginTop[grid2.TOP] + grid2.marginTop[grid2.BOTTOM];
  4382. // }else{
  4383. // var margin1 = grid1.margin[grid1.TOP] + grid1.margin[grid1.BOTTOM];
  4384. // var margin2 = grid2.margin[grid2.TOP] + grid2.margin[grid2.BOTTOM];
  4385. // }
  4386. var margin1 = grid1.margin[grid1.TOP] + grid1.margin[grid1.BOTTOM];
  4387. var margin2 = grid2.margin[grid2.TOP] + grid2.margin[grid2.BOTTOM];
  4388. if (!grid1 || !grid2) return;
  4389. if (offset > 0 && grid2.height - margin2 - offset <= 5) {
  4390. offset = grid2.height - 5 - margin2;
  4391. }
  4392. if (offset < 0 && grid1.height - margin1 + offset <= 5) {
  4393. offset = -(grid1.height - 5 - margin1);
  4394. }
  4395. grid1.setHeight(grid1.height + offset);
  4396. grid2.setHeight(grid2.height - offset);
  4397. }
  4398. View.prototype.resizeWindow = function(e) {
  4399. var _this = e.data;
  4400. if (!_this.lastW) {
  4401. return;
  4402. }
  4403. if (_this.lastW == $(window).width() && _this.lastH == $(window).height()) {
  4404. return;
  4405. }
  4406. //debugx("resize0: " + _this.lastW + "," + _this.lastH);
  4407. //debugx("resize1: " + $(window).width() + "," + $(window).height());
  4408. _this.setPlotArea();
  4409. _this.setWidth();
  4410. //_this.setExistPlotHeight(_this.getUnitHeight());
  4411. //debugx("resize2: " + $(window).width() + "," + $(window).height());
  4412. //保存最新的window值
  4413. _this.lastW = $(window).width();
  4414. _this.lastH = $(window).height();
  4415. _this.controller.draw();
  4416. }
  4417. function Win(title, width, height, opt) {
  4418. this.title = title;
  4419. this.width = width ? width : 400;
  4420. this.height = height ? height : 300;
  4421. if (!opt) opt = {};
  4422. this.autoclose = opt.autoclose ? opt.autoclose : 0;
  4423. this.left = opt.left ? opt.left : -1; //-1表示默认向左,其实就是窗口居中
  4424. this.top = opt.top ? opt.top : -1; //top 的意义和 left相同
  4425. this.config = Config.getInstance();
  4426. this.tpl = $(this.config.Global.WinTplID);
  4427. this.cache = {};
  4428. }
  4429. Win.zindex = 1000;
  4430. Win.prototype.getHtml = function() {
  4431. var html = this.tpl.html();
  4432. html = html.replace("{|$title|}", this.title);
  4433. html = html.replace("{|$autoclose|}", this.autoclose);
  4434. return html;
  4435. }
  4436. Win.prototype.createWindow = function(targetID) {
  4437. if ($("#" + targetID).length) {
  4438. return;
  4439. }
  4440. this.conf = this.config.Global.Win[targetID];
  4441. var html
  4442. var newhtml
  4443. if (targetID == "__order__") {
  4444. this.win = $("<div id='" + targetID + "'> </div><input type=\"hidden\" id=\"ordershow\" value=\"0\" />");
  4445. html = this.getHtml();
  4446. newhtml = html.replace("class=\"content\">", "id='popwin' class=\"content\">");
  4447. } else {
  4448. this.win = $("<div id='" + targetID + "'> </div>");
  4449. newhtml = this.getHtml();
  4450. }
  4451. this.targetID = targetID;
  4452. $("body").append(this.win);
  4453. this.win.html(newhtml);
  4454. this.dragArea = this.getClassQuery("popTop");
  4455. this.win.dragdrop(this.dragArea);
  4456. this.setWidth(this.width).setHeight(this.height);
  4457. this.win.css("position", "absolute");
  4458. this.win.css("z-index", Win.zindex);
  4459. this.setPotion();
  4460. Win.zindex++;
  4461. this.addTab();
  4462. this.addEvent();
  4463. this.clickFirst(this.getClassQuery("cc"));
  4464. this.win.hide();
  4465. }
  4466. Win.prototype.addTab = function() {
  4467. var query = this.getClassQuery("cc");
  4468. query = $(query);
  4469. for (var key in this.conf.tab) {
  4470. if (typeof this.conf.tab[key] == "string") {
  4471. query.append('<li name="' + key + '"><a href="javascript:;">' + this.conf.tab[key] + '</a></li>');
  4472. }
  4473. }
  4474. }
  4475. Win.prototype.clickFirst = function(query) {
  4476. query = $(query);
  4477. query.children().first().click();
  4478. }
  4479. Win.prototype.setPotion = function() {
  4480. if (this.top == -1) {
  4481. var top = Math.max(0, ($(window).height() - this.height) / 2);
  4482. }
  4483. if (this.left == -1) {
  4484. var left = Math.max(0, ($(window).width() - this.width) / 2);
  4485. }
  4486. this.win.css("top", top + "px");
  4487. this.win.css("left", left + "px");
  4488. }
  4489. Win.prototype.setWidth = function(w) {
  4490. var mainContainer = this.getClassQuery("windowBody");
  4491. $(mainContainer).width(w);
  4492. return this;
  4493. }
  4494. Win.prototype.setHeight = function(h) {
  4495. var mainContainer = this.getClassQuery("windowBody");
  4496. $(mainContainer).height(h);
  4497. return this;
  4498. }
  4499. Win.prototype.getClassQuery = function(classname) {
  4500. var targetID = this.targetID;
  4501. if (targetID.charAt(0) != "#") {
  4502. targetID = "#" + this.targetID
  4503. }
  4504. if (classname.charAt(0) != ".") {
  4505. classname = " ." + classname;
  4506. }
  4507. var query = targetID + classname;
  4508. return query
  4509. }
  4510. Win.prototype.show = function() {
  4511. this.win.show();
  4512. this.win.css("z-index", Win.zindex++);
  4513. }
  4514. Win.prototype.addEvent = function() {
  4515. //close
  4516. var query = this.getClassQuery("adel");
  4517. var _this = this;
  4518. $(query).click(
  4519. function() {
  4520. $("#tool_dl").find("li[name=none]").click();
  4521. _this.win.hide();
  4522. }
  4523. );
  4524. //tab
  4525. var query = this.getClassQuery("cc");
  4526. var _this = this;
  4527. $(query).children().click(function(e) {
  4528. $(query).children().removeClass("current");
  4529. $(this).addClass("current");
  4530. if (_this.load) {
  4531. _this.load($(this).attr("name"));
  4532. }
  4533. });
  4534. }
  4535. function WinAjax(name, title, width, height, opt) {
  4536. sup(this, title, width, height, opt);
  4537. }
  4538. ClassExtend(WinAjax, Win);
  4539. WinAjax.prototype.load = function(name, flag) {
  4540. //这里可以根据name 做一些特殊的处理。
  4541. //但是,目前,我们采用的是 ajax 从服务器下载相关的配置
  4542. this.tab = name;
  4543. this.flag = flag;
  4544. var query = this.getClassQuery("content");
  4545. if (this.cache[name + flag]) {
  4546. $(query).html(this.cache[name + flag]);
  4547. return;
  4548. }
  4549. var api
  4550. if (name == "order") {
  4551. api = this.config.Global.WinOrder;
  4552. } else {
  4553. api = this.config.Global.WinAPI;
  4554. }
  4555. var _this = this;
  4556. if (this.ajax) {
  4557. this.ajax.abort();
  4558. }
  4559. var param = { win: this.targetID, tab: name, __tmp: Math.random() };
  4560. if (this.flag) {
  4561. param.flag = this.flag;
  4562. }
  4563. if (name == "order") {
  4564. this.ajax = $.get(api, function(data) {
  4565. //_this.cache[data.tab + data.flag] = data.data;
  4566. $(query).html(data);
  4567. }, "html");
  4568. } else {
  4569. this.ajax = $.get(api, param, function(data) {
  4570. _this.cache[data.tab + data.flag] = data.data;
  4571. $(query).html(data.data);
  4572. }, "jsonp");
  4573. }
  4574. }
  4575. function ShapeArrow(ctx, width, height, opt) {
  4576. sup(this, ctx, width, height, opt);
  4577. }
  4578. ClassExtend(ShapeArrow, Shape);
  4579. ShapeArrow.prototype.arrowhalf = function(ctx, width, height) {
  4580. var pi = Math.PI;
  4581. ctx.save();
  4582. ctx.translate(0, -height);
  4583. ctx.beginPath();
  4584. ctx.moveTo(0, 0);
  4585. ctx.lineTo(width, 0);
  4586. var head = (0.618) * height;
  4587. ctx.lineTo(width, head);
  4588. if (width <= 3) {
  4589. var add = 3;
  4590. } else {
  4591. var add = width / 0.618;
  4592. }
  4593. ctx.lineTo(width + add, head - width * Math.tan(pi / 3));
  4594. ctx.lineTo(0, height);
  4595. ctx.closePath();
  4596. ctx.stroke();
  4597. ctx.fill();
  4598. ctx.restore();
  4599. }
  4600. ShapeArrow.prototype.basic_arrow = function(ctx, width, height) {
  4601. ctx.save();
  4602. this.arrowhalf(ctx, width, height);
  4603. ctx.transform(-1, 0, 0, 1, 0, 0);
  4604. this.arrowhalf(ctx, width, height);
  4605. ctx.restore();
  4606. }
  4607. //箭头的定位在于两个方面。一个方面是旋转的角度,一个是箭头指向的位置
  4608. ShapeArrow.prototype.draw = function(point) {
  4609. var ctx = this.ctx;
  4610. var cta = this.cta;
  4611. ctx.save();
  4612. ctx.translate(point.x, point.y);
  4613. ctx.rotate(cta);
  4614. ctx.strokeStyle = this.boder;
  4615. ctx.fillStyle = this.fill;
  4616. this.basic_arrow(ctx, this.width, this.height);
  4617. ctx.restore();
  4618. }
  4619. function PlotAdvFractals(view, grid, name) {
  4620. sup(this, view, grid, name);
  4621. }
  4622. ClassExtend(PlotAdvFractals, Plot);
  4623. PlotAdvFractals.prototype.draw = function(data) {
  4624. var color;
  4625. if (this.param.lineColor) {
  4626. color = this.param.lineColor;
  4627. } else {
  4628. color = this.conf.lineColor;
  4629. }
  4630. /* for(var i = 0 ;i<data.x.length ;i++){
  4631. if(data.y[i][0] ==-1){
  4632. writeText(this.ctx, new Point(data.x[i] , data.y[i][1]+12), "d", color[0], this.param.font);
  4633. }else if(data.y[i][0] == 1){
  4634. writeText(this.ctx, new Point(data.x[i] , data.y[i][1]-12), "u", color[1], this.param.font);
  4635. }
  4636. }*/
  4637. var y1 = []
  4638. for (var i = 0; i < data.y.length; i++) {
  4639. y1[i] = data.y[i][1];
  4640. }
  4641. drawLine(this.ctx, data.x, y1, color[0]);
  4642. }
  4643. function Plotadx(view, grid, name) {
  4644. sup(this, view, grid, name);
  4645. }
  4646. ClassExtend(Plotadx, Plot);
  4647. Plotadx.prototype.draw = function(data) {
  4648. var color;
  4649. if (this.param.lineColor) {
  4650. color = this.param.lineColor;
  4651. } else {
  4652. color = this.conf.lineColor;
  4653. }
  4654. var y1 = []
  4655. var y2 = []
  4656. var y3 = []
  4657. for (var i = 0; i < data.y.length; i++) {
  4658. y1[i] = data.y[i][0];
  4659. y2[i] = data.y[i][1];
  4660. y3[i] = data.y[i][2];
  4661. }
  4662. drawLine(this.ctx, data.x, y1, color[0]);
  4663. drawLine(this.ctx, data.x, y2, color[1]);
  4664. drawLine(this.ctx, data.x, y3, color[2]);
  4665. }
  4666. function Plotatr(view, grid, name) {
  4667. sup(this, view, grid, name);
  4668. }
  4669. ClassExtend(Plotatr, Plot);
  4670. Plotatr.prototype.draw = function(data) {
  4671. //建立点
  4672. var color;
  4673. if (this.param.color) {
  4674. color = this.param.color;
  4675. } else {
  4676. color = this.conf.lineColor;
  4677. }
  4678. var y1 = []
  4679. var y2 = []
  4680. for (var i = 0; i < data.y.length; i++) {
  4681. y1[i] = data.y[i][0];
  4682. y2[i] = data.y[i][1];
  4683. }
  4684. drawLine(this.ctx, data.x, y1, color[0]);
  4685. drawLine(this.ctx, data.x, y2, color[1]);
  4686. }
  4687. function Plotbdensity(view, grid, name) {
  4688. sup(this, view, grid, name);
  4689. }
  4690. ClassExtend(Plotbdensity, Plot);
  4691. Plotbdensity.prototype.draw = function(data) {
  4692. //建立点
  4693. var color;
  4694. if (this.param.lineColor) {
  4695. color = this.param.lineColor;
  4696. } else {
  4697. color = this.conf.lineColor;
  4698. }
  4699. for (var i = 0; i < data.y.length; i++) {
  4700. if (data.y[i][2] != 0) {
  4701. writeText(this.ctx, new Point(data.x[i], data.y[i][0]), "~", color[0], this.param.font)
  4702. writeText(this.ctx, new Point(data.x[i], data.y[i][1]), "*", color[0], this.param.font)
  4703. }
  4704. if (data.y[i][6] != 0) {
  4705. writeText(this.ctx, new Point(data.x[i], data.y[i][4]), "~", color[1], this.param.font)
  4706. writeText(this.ctx, new Point(data.x[i], data.y[i][5]), "*", color[1], this.param.font)
  4707. }
  4708. if (data.y[i][10] != 0) {
  4709. writeText(this.ctx, new Point(data.x[i], data.y[i][8]), "~", color[2], this.param.font)
  4710. writeText(this.ctx, new Point(data.x[i], data.y[i][9]), "*", color[2], this.param.font)
  4711. }
  4712. }
  4713. }
  4714. function PlotBolling(view, grid, name) {
  4715. sup(this, view, grid, name);
  4716. }
  4717. ClassExtend(PlotBolling, Plot);
  4718. PlotBolling.prototype.draw = function(data) {
  4719. //建立点
  4720. var color;
  4721. if (this.param.color) {
  4722. color = this.param.color.split("-");
  4723. } else {
  4724. color = this.conf.lineColor;
  4725. }
  4726. var y1 = []
  4727. var y2 = []
  4728. var y3 = []
  4729. for (var i = 0; i < data.y.length; i++) {
  4730. y1[i] = data.y[i][0];
  4731. y2[i] = data.y[i][1];
  4732. y3[i] = data.y[i][2];
  4733. }
  4734. drawLine(this.ctx, data.x, y1, color[0]);
  4735. drawLine(this.ctx, data.x, y2, color[1]);
  4736. drawLine(this.ctx, data.x, y3, color[2]);
  4737. }
  4738. function PlotBollingDesity(view, grid, name) {
  4739. sup(this, view, grid, name);
  4740. this.color = ["red", "rgb(255, 128, 128)", "red", "rgb(255, 128, 128)",
  4741. "green", "rgb(128, 255, 128)", "green", "rgb(128, 255, 128)",
  4742. "yellow", "rgb(128, 255, 128)", "yellow", "rgb(128, 255, 128)",
  4743. "Cyan", "Cyan",
  4744. "Blue", "Blue",
  4745. "Fuchsia", "Fuchsia",
  4746. ];
  4747. }
  4748. ClassExtend(PlotBollingDesity, Plot);
  4749. PlotBollingDesity.prototype.draw = function(data) {
  4750. this.X = data.x;
  4751. this.Y = data.y;
  4752. this.setMaxMinDesity();
  4753. this.getPlotArea();
  4754. this.box = this.view.plot[this.config.mainName].getBoxSize();
  4755. this.left = this.view.plot[this.config.mainName].getBoxLeft();
  4756. for (var i = 0; i < this.X.length; i++) {
  4757. this.drawOne(this.X[i], this.Y[i]);
  4758. }
  4759. }
  4760. PlotBollingDesity.prototype.setMaxMinDesity = function() {
  4761. var min = Infinity
  4762. var max = -Infinity;
  4763. var y = this.Y;
  4764. for (var i = 0; i < y.length; i++) {
  4765. for (var j = 1; j < y.length; j += 2) {
  4766. if (y[i][j] == -1) {
  4767. continue;
  4768. }
  4769. if (max < y[i][j]) {
  4770. max = y[i][j];
  4771. }
  4772. if (min > y[i][j]) {
  4773. min = y[i][j]
  4774. }
  4775. }
  4776. }
  4777. this.maxD = max;
  4778. this.minD = min;
  4779. }
  4780. PlotBollingDesity.prototype.drawOne = function(time, data) {
  4781. var price, desity, color, left, top;
  4782. try {
  4783. for (var i = 0; i < 16; i += 2) {
  4784. price = data[i];
  4785. if (price == -1 || data[i + 1] == -1) {
  4786. continue;
  4787. }
  4788. desity = this.getDesity(data[i + 1]);
  4789. color = this.color[i / 2];
  4790. this.ctx.fillStyle = color;
  4791. left = time - this.left;
  4792. top = price - desity;
  4793. if (top < this.top || top > this.bottom) {
  4794. continue;
  4795. }
  4796. this.ctx.fillRect(left, top, this.box, desity);
  4797. }
  4798. } catch (e) {}
  4799. }
  4800. PlotBollingDesity.prototype.getDesity = function(d) {
  4801. return (Math.floor(((d - this.minD) / (this.maxD - this.minD)) * 6) + 1);
  4802. }
  4803. PlotBollingDesity.prototype.lastDataShow = function() {
  4804. var data = this.lastData();
  4805. var newdata = [];
  4806. for (var i = 0; i < data.length; i += 2) {
  4807. newdata[i / 2] = data[i];
  4808. }
  4809. return newdata;
  4810. }
  4811. function PlotCandle(view, grid, name) {
  4812. sup(this, view, grid, name);
  4813. //放大缩小尺寸控制更加灵活。采用配置数组的形式
  4814. this.box = [1, 2, 3, 5, 7, 9, 11, 13];
  4815. this.space = [0, 1, 1, 2, 2, 3, 4, 5];
  4816. this.left = [0, 1, 1, 2, 3, 4, 5, 6]
  4817. // this.box = [ 7, 9, 11, 13,15,18,21,23];
  4818. // this.space = [ 2, 3, 4, 5,6,8,9,10];
  4819. // this.left = [ 3, 4, 5, 6,7,9,10,11]
  4820. // this.box = [3, 5, 9, 13, 17, 19, 23, 25];
  4821. // this.space = [1, 2, 3, 5, 7, 8, 10, 11];
  4822. // this.left = [1, 2, 4, 6, 8, 9, 11, 12]
  4823. }
  4824. ClassExtend(PlotCandle, Plot);
  4825. PlotCandle.prototype.zoomIn = function() {
  4826. if (this.conf.box_pixel >= 7 && this.conf.space_pixel >= 7) {
  4827. return;
  4828. }
  4829. if (this.conf.box_pixel < this.conf.space_pixel) {
  4830. this.conf.box_pixel++;
  4831. } else if (this.conf.box_pixel > this.conf.space_pixel) {
  4832. this.spaceOffset(1);
  4833. } else {
  4834. this.conf.box_pixel++;
  4835. }
  4836. }
  4837. PlotCandle.prototype.spaceOffset = function(offset) {
  4838. var prev = this.space[this.conf.space_pixel];
  4839. this.conf.space_pixel = this.conf.space_pixel + offset;
  4840. var current = this.space[this.conf.space_pixel];
  4841. if (prev == current) {
  4842. this.conf.box_pixel = this.conf.box_pixel + offset;
  4843. }
  4844. }
  4845. PlotCandle.prototype.zoomOut = function() {
  4846. if (this.conf.box_pixel <= 0 && this.conf.space_pixel <= 0) {
  4847. return;
  4848. }
  4849. if (this.conf.box_pixel < this.conf.space_pixel) {
  4850. this.spaceOffset(-1);
  4851. } else if (this.conf.box_pixel > this.conf.space_pixel) {
  4852. this.conf.box_pixel--;
  4853. } else {
  4854. this.spaceOffset(-1);
  4855. }
  4856. this.conf.box_pixel = this.conf.box_pixel < 0 ? 0 : this.conf.box_pixel;
  4857. }
  4858. PlotCandle.prototype.getOneSize = function() {
  4859. return this.box[this.conf.box_pixel] + 2*this.space[this.conf.space_pixel];
  4860. }
  4861. PlotCandle.prototype.getBoxLeft = function() {
  4862. return this.left[this.conf.box_pixel];
  4863. }
  4864. PlotCandle.prototype.getBoxSize = function() {
  4865. return this.box[this.conf.box_pixel];
  4866. }
  4867. PlotCandle.prototype.draw = function(data) {
  4868. this.data = data;
  4869. this.X = data.x;
  4870. this.Y = data.y;
  4871. this.xunit = this.data.xunit;
  4872. this.yunit = this.data.yunit;
  4873. this.closePriceFlag();
  4874. var width = this.box[this.conf.box_pixel];
  4875. var left = this.left[this.conf.box_pixel];
  4876. if (width > 2) {
  4877. width--;
  4878. }
  4879. this.config.Global.boxwidth = width;
  4880. //最高最低点标签
  4881. var maxy=this.Y[this.data.maxIndex][1]-5;
  4882. var miny=this.Y[this.data.minIndex][2]+15;
  4883. writeText(this.ctx,new Point(this.X[this.data.maxIndex],maxy),parseFloat(this.data.maxY).toFixed(3), "#ff6600", "#fff");
  4884. writeText(this.ctx,new Point(this.X[this.data.minIndex],miny),parseFloat(this.data.minY).toFixed(3), "#ff6600", "#fff");
  4885. //画个分界线
  4886. for (var i = 0; i < this.X.length; i++) {
  4887. this.drawOne(this.X[i], this.Y[i], width, left);
  4888. // var ohlc=this.Y[i];
  4889. // var maxy=parseFloat(GetText(ohlc[1],this.yunit)).toFixed(3);
  4890. // var miny=parseFloat(GetText(ohlc[2],this.yunit)).toFixed(3);
  4891. // if(maxy==this.data.maxY){
  4892. // writeText(this.ctx, new Point(this.X[i] + this.conf.ledgeLen + 2, this.Y[i]), this.data.maxY, this.conf.fontColor, this.conf.font);
  4893. // }
  4894. // if(miny==this.data.minY){
  4895. // writeText(this.ctx, new Point(this.X[i] + this.conf.ledgeLen + 2, this.Y[i]), this.data.maxY, this.conf.fontColor, this.conf.font);
  4896. // }
  4897. }
  4898. //console.log(data.text);
  4899. }
  4900. //按照道理,这些数据都应该是计算好了之后,
  4901. //会送给客户端的。这个部分,还是要对数据层进行改进
  4902. //才能比较好的封装。现在暂时这样处理。
  4903. PlotCandle.prototype.closePriceFlag = function() {
  4904. //view 一般不调用model的数据。因为,这样使得view 和 model层直接联系起来。
  4905. //但是,我们知道,我们的Controller 是一般性的分发。
  4906. //而且这样的一般性的分发在大多数情况下面是够用的。
  4907. //出于这样的考虑,我们允许在view里面调用model,因为,的确很多时候需要这样的调用。
  4908. //每个图都有对应的 model plot
  4909. var close_price = this.view.model.getDataReader(this.name).close(0);
  4910. this.priceFlag(close_price, this.conf.close);
  4911. }
  4912. PlotCandle.prototype.over = function(x, y) {
  4913. //查找最接近的
  4914. // console.log("1");
  4915. if (!this.X || !this.Y) return;
  4916. var index = find_near(this.X, x);
  4917. if (index == -1) return false;
  4918. if (Math.abs(this.X[index] - x) > this.getOneSize()) {
  4919. return false;
  4920. }
  4921. var ohlc = this.Y[index];
  4922. // console.log("text PlotCandle");
  4923. //找到此金额的y轴坐标
  4924. //if (ohlc[Data.HIGH] - this.config.Global.overPadding <= y && ohlc[Data.LOW] + this.config.Global.overPadding >= y) {
  4925. var findTime = this.axis.getXValue(x, PlotGrid.NEAR);
  4926. if (findTime === false) return;
  4927. var cdata = this.view.model.getDataByTime(this.name, findTime, "candle");
  4928. if (!cdata) return false;
  4929. var time = cdata.time;
  4930. var ohlc = cdata.data;
  4931. var yunit = this.axis.viewconfig.y.axis_option.unit;
  4932. var fallOrDegrees = parseFloat(GetText(ohlc[Data.CLOSE], yunit) - GetText(ohlc[Data.OPEN], yunit)) / parseFloat(GetText(ohlc[Data.OPEN], yunit));
  4933. var fallOrDegrees = fallOrDegrees.toFixed(3);
  4934. $(".freetimebox li:first-child").text("时间:"+time);
  4935. $(".freetimebox li:nth(1)").text("开:"+GetText(ohlc[Data.OPEN], yunit));
  4936. $(".freetimebox li:nth(2)").text("高:"+GetText(ohlc[Data.HIGH], yunit));
  4937. $(".freetimebox li:nth(3)").text("低:"+GetText(ohlc[Data.LOW], yunit));
  4938. $(".freetimebox li:nth(4)").text("收:"+GetText(ohlc[Data.LOW], yunit));
  4939. $(".freetimebox li:nth(4)").text("收:"+GetText(ohlc[Data.CLOSE], yunit));
  4940. $(".freetimebox li:nth(5)").text("涨幅:"+fallOrDegrees);
  4941. $(".freetimebox li:nth(6)").text("振幅:"+fallOrDegrees);
  4942. $(".freetimebox li:nth(7)").text("量:"+GetText(ohlc[Data.VOLUMES], yunit));
  4943. $('.freetimebox').show();
  4944. //timeLine Data
  4945. // timelineData(time, GetText(ohlc[Data.OPEN], yunit), GetText(ohlc[Data.HIGH], yunit), GetText(ohlc[Data.LOW], yunit), GetText(ohlc[Data.CLOSE], yunit), GetText(ohlc[Data.VOLUMES], yunit));
  4946. // console.log("text PlotCandle");
  4947. // return time + "<br/>" + "O: " + GetText(ohlc[Data.OPEN], yunit) + "<br />" + "H: " + GetText(ohlc[Data.HIGH], yunit) + "<br />" + "L : " + GetText(ohlc[Data.LOW], yunit) + "<br />" + "C: " + GetText(ohlc[Data.CLOSE], yunit) + "<br />" + "V: " + GetText(ohlc[Data.VOLUMES], yunit) + "<br />";
  4948. // } else {
  4949. // return false;
  4950. // }
  4951. }
  4952. PlotCandle.prototype.drawOne = function(time, ohlc, width, left) {
  4953. var ctx = this.ctx;
  4954. var open = ohlc[Data.OPEN];
  4955. var high = ohlc[Data.HIGH];
  4956. var low = ohlc[Data.LOW];
  4957. var close = ohlc[Data.CLOSE];
  4958. time += 0.5;
  4959. open += 0.5;
  4960. high += 0.5;
  4961. low += 0.5;
  4962. close += 0.5;
  4963. if (high == low) {
  4964. //画个横线就可以了
  4965. ctx.strokeStyle = this.conf.os_border_color;
  4966. ctx.beginPath();
  4967. ctx.moveTo(time - left, open);
  4968. ctx.lineTo(time + width, open);
  4969. ctx.stroke();
  4970. return;
  4971. }
  4972. if (open < close) {
  4973. var up = open;
  4974. var down = close;
  4975. var fill = this.conf.open_big_color;
  4976. var border = this.conf.ob_border_color;
  4977. } else {
  4978. var up = close;
  4979. var down = open;
  4980. var fill = this.conf.open_small_color;
  4981. var border = this.conf.os_border_color;
  4982. }
  4983. ctx.strokeStyle = border;
  4984. ctx.beginPath();
  4985. ctx.moveTo(time, high);
  4986. ctx.lineTo(time, low);
  4987. ctx.stroke();
  4988. if (this.conf.space_pixel > 0) {
  4989. ctx.fillStyle = fill;
  4990. ctx.fillRect(time - left, up, width, down - up);
  4991. ctx.strokeRect(time - left, up, width, down - up);
  4992. }
  4993. }
  4994. function PlotFractals(view, grid, name) {
  4995. sup(this, view, grid, name);
  4996. }
  4997. ClassExtend(PlotFractals, Plot);
  4998. PlotFractals.prototype.draw = function(data) {
  4999. var color;
  5000. if (this.param.lineColor) {
  5001. color = this.param.lineColor;
  5002. } else {
  5003. color = this.conf.lineColor;
  5004. }
  5005. /* for(var i = 0 ;i<data.x.length ;i++){
  5006. if(data.y[i][0] ==-1){
  5007. writeText(this.ctx, new Point(data.x[i] , data.y[i][1]+12), "d", color[0], this.param.font);
  5008. }else if(data.y[i][0] == 1){
  5009. writeText(this.ctx, new Point(data.x[i] , data.y[i][1]-12), "u", color[1], this.param.font);
  5010. }
  5011. }*/
  5012. var y1 = []
  5013. for (var i = 0; i < data.y.length; i++) {
  5014. y1[i] = data.y[i][1];
  5015. }
  5016. drawLine(this.ctx, data.x, y1, color[0]);
  5017. }
  5018. //grid 是一个令人纠结的类,他是图形的一部分,各种图形都在grid上进行绘制
  5019. function PlotGrid(view, index) {
  5020. this.TOP = 0;
  5021. this.RIGHT = 1;
  5022. this.BOTTOM = 2;
  5023. this.LEFT = 3;
  5024. this.index = index;
  5025. this.view = view;
  5026. this.axis = this.view.axis[index];
  5027. this.canvas = $(this.view.canvas[index]);
  5028. this.canvasBG = $(this.view.canvasBG[index]);
  5029. this.canvasFront = $(this.view.canvasFront[index]);
  5030. this.canvasContainer = $(this.view.canvasContainer[index]);
  5031. this.resize = this.view.resize[index];
  5032. this.controller = this.view.controller;
  5033. this.plot = [];
  5034. if (!this.canvas.get(0).getContext) {
  5035. //debug(Alert(this.canvas.get(0)));
  5036. $("#flash_notify").show();
  5037. alert("not support flash or html5");
  5038. }
  5039. this.ctx = this.canvas.get(0).getContext('2d');
  5040. this.ctxBG = this.canvasBG.get(0).getContext('2d');
  5041. this.ctxFront = this.canvasFront.get(0).getContext('2d');
  5042. // if(index==0){
  5043. // this.height = this.canvas.get(0).height-60;
  5044. // }
  5045. // else{
  5046. // this.height = this.canvas.get(0).height-10;
  5047. // }
  5048. this.width = this.canvas.get(0).width;
  5049. this.height = this.canvas.get(0).height;
  5050. // var img=document.getElementById("myCanvas");
  5051. // this.ctx.drawImage(pic,0,0,this.width, this.height);
  5052. this.config = Config.getInstance();
  5053. this.conf = this.config.Global.Grid.public; //这个是全局公共配置,更改会引起全局对象的改变。
  5054. //私有变量导出
  5055. this.margin = array_copy(this.conf.margin);
  5056. this.xstyle_axis = this.conf.xstyle_axis;
  5057. this.ystyle_axis = this.conf.ystyle_axis;
  5058. this.setConfig();
  5059. this.addEvent();
  5060. PlotGrid._this = this;
  5061. }
  5062. PlotGrid.FIX_BEG = 1; //开始值固定 (小值)
  5063. PlotGrid.FIX_END = 1 << 1; //结束值固定 (大值)
  5064. PlotGrid.FLOAT = 1 << 2; //浮动计算,可以得到更好的坐标值(浮动20%,得到一些更好的值)
  5065. PlotGrid.GT_ZERO = 1 << 3;
  5066. PlotGrid.TIME = 1 << 4;
  5067. PlotGrid.FIX_PIXEL = 1 << 5;
  5068. PlotGrid.NO_GRID = 1 << 6;
  5069. PlotGrid.NO_AXIS = 1 << 7;
  5070. PlotGrid.NEAR = 1 << 8; //采用寻找最近的点的模式
  5071. PlotGrid.INTERPOLATION = 1 << 9; //采用差值法
  5072. PlotGrid.ADD_YEAR = 1 << 10; //采用差值法
  5073. PlotGrid.prototype.setConfig = function() {
  5074. this.O = new Point(this.margin[this.LEFT], this.margin[this.TOP]);
  5075. this.xEnd = new Point(this.width - this.margin[this.RIGHT], this.margin[this.TOP]);
  5076. this.yEnd = new Point(this.margin[this.LEFT], this.height - this.margin[this.BOTTOM]);
  5077. this.xyEnd = new Point(this.width - this.margin[this.RIGHT], this.height - this.margin[this.BOTTOM]);
  5078. }
  5079. PlotGrid.prototype.setLast = function() {
  5080. this.clearLast();
  5081. if (this.margin[this.BOTTOM] < 20) {
  5082. this.margin[this.BOTTOM] = 20; //又足够的地方写字
  5083. }
  5084. this.resize.hide();
  5085. this.xstyle_axis = this.xstyle_axis & ~PlotGrid.NO_AXIS;
  5086. this.setConfig();
  5087. }
  5088. PlotGrid.prototype.clearLast = function() {
  5089. this.margin = array_copy(this.conf.margin);
  5090. if (!this.xstyle_axis) {
  5091. this.xstyle_axis = 0;
  5092. }
  5093. this.resize.show();
  5094. this.xstyle_axis |= PlotGrid.NO_AXIS;
  5095. this.setConfig();
  5096. }
  5097. PlotGrid.prototype.setHeight = function(h) {
  5098. h = Math.round(h);
  5099. // console.log(h);
  5100. this.height = h;
  5101. // if(this.canvasContainer.attr('id')=="plot_canvas_0"){
  5102. // h=h-60;
  5103. // }
  5104. // else{
  5105. // h=h;
  5106. // }
  5107. // console.log("PlotGrid.prototype.setHeight:"+this.height)
  5108. set_height(this.canvas, h);
  5109. set_height(this.canvasBG, h);
  5110. set_height(this.canvasFront, h);
  5111. set_height(this.canvasContainer, h);
  5112. this.resize.css("top", $(this.canvas).offset().top + h - 4);
  5113. this.setConfig();
  5114. }
  5115. PlotGrid.prototype.setWidth = function(w) {
  5116. this.width = w;
  5117. this.setConfig();
  5118. }
  5119. PlotGrid.prototype.getPlotArea = function() {
  5120. //获取绘图的区域
  5121. var area = { x: {}, y: {} };
  5122. area.y.beg = Math.round(this.xyEnd.y - this.conf.paddingY);
  5123. area.y.end = Math.round(this.xEnd.y);
  5124. area.x.beg = Math.round(this.xyEnd.x - this.conf.paddingX);
  5125. area.x.end = Math.round(this.yEnd.x);
  5126. return area;
  5127. }
  5128. //绘制行,要考虑padding的值 update by fangxiao from 2016/6/29 17:16
  5129. PlotGrid.prototype.drawY = function(axis) {
  5130. if (!axis) axis = this.axis;
  5131. axis_option = axis.viewconfig.y.axis_option;
  5132. var points = axis.viewconfig.y.axis;
  5133. for (var i = 0; i < points.length; i++) {
  5134. var point = new Point(this.O.x, points[i].key);
  5135. var len = this.xEnd.x - this.O.x;
  5136. if (this.conf.ystyle_grid & PlotGrid.NO_GRID) {
  5137. //do noting
  5138. } else {
  5139. drawRow(this.ctx, point, len, this.conf.gridColor, 1);
  5140. }
  5141. if (this.ystyle_axis & PlotGrid.NO_AXIS) {
  5142. //do nothing
  5143. } else {
  5144. var point = new Point(this.xEnd.x, points[i].key);
  5145. //drawRow(this.ctx, point, this.conf.ledgeLen, this.conf.axisColor, 1); 去除y轴右侧字旁边的横杆
  5146. var text = this.getText(axis_option.style, points[i].value, axis_option.unit);
  5147. if (i == points.length - 1) //最后一个点,往内缩
  5148. {
  5149. // var ypoint = points[i].key + 12;
  5150. var ypoint = points[i].key;
  5151. } else {
  5152. var ypoint = points[i].key;
  5153. }
  5154. if(i!=0){
  5155. drawDashLine(this.ctx,this.O.x,ypoint,this.xEnd.x,ypoint,2);
  5156. }
  5157. writeText(this.ctx, new Point(this.xEnd.x + this.conf.ledgeLen + 2, ypoint), text, this.conf.fontColor, this.conf.font);
  5158. }
  5159. }
  5160. }
  5161. PlotGrid.prototype.drawCrossX = function(x, axis) {
  5162. var len = this.yEnd.y - this.O.y;
  5163. drawCol(this.ctx, new Point(x, this.O.y-15), len+20, this.conf.crossX.lineColor, 0.6);
  5164. if (this.xstyle_axis & PlotGrid.NO_AXIS) {
  5165. //do nothing;
  5166. } else {
  5167. this.writeXLable(x, axis);
  5168. }
  5169. }
  5170. //开始绘制
  5171. PlotGrid.prototype.writeXLable = function(x, axis) {
  5172. if (typeof axis === "undefined") {
  5173. axis = this.axis;
  5174. }
  5175. var value = this.axis.getXValue(x, this.conf.crossXMode, axis);
  5176. if (value === false) return;
  5177. var opt = axis.viewconfig.x.axis_option;
  5178. value = this.getText(opt.style, value, opt.unit);
  5179. writeTextOption(this.ctx, new Point(x - this.conf.crossX.bg.width / 2, this.yEnd.y + this.conf.crossX.bg.height / 2), value, this.conf.crossX);
  5180. }
  5181. //开始绘制
  5182. PlotGrid.prototype.writeYLable = function(y, axis) {
  5183. if (typeof axis === "undefined") {
  5184. axis = this.axis;
  5185. }
  5186. var value = this.axis.getYValue(y, this.conf.crossYMode, axis);
  5187. if (value === false) return;
  5188. var opt = axis.viewconfig.y.axis_option;
  5189. value = this.getText(opt.style, value, opt.unit);
  5190. writeTextOption(this.ctx, new Point(this.xEnd.x, y), value, this.conf.crossY);
  5191. }
  5192. PlotGrid.prototype.writeHeadText = function(text) {
  5193. writeText(this.ctx, new Point(this.O.x + 10, this.O.y + 20), text, this.conf.headText.color, this.conf.headText.font);
  5194. }
  5195. PlotGrid.prototype.drawCrossY = function(y) {
  5196. var len = this.xEnd.x - this.O.x;
  5197. drawRow(this.ctx, new Point(this.O.x, y), len, this.conf.crossY.lineColor, 0.3);
  5198. if (this.ystyle_axis & PlotGrid.NO_AXIS) {
  5199. //do nothing
  5200. } else {
  5201. this.writeYLable(y);
  5202. }
  5203. }
  5204. PlotGrid.prototype.drawX = function(axis) {
  5205. if (!axis) axis = this.axis;
  5206. axis_option = axis.viewconfig.x.axis_option;
  5207. var points = axis.viewconfig.x.axis;
  5208. if (typeof points === "undefined") {
  5209. return;
  5210. }
  5211. for (var i = 0; i < points.length; i++) {
  5212. var point = new Point(points[i].key, this.O.y);
  5213. var len = this.yEnd.y - this.O.y;
  5214. if (this.conf.xstyle_grid & PlotGrid.NO_GRID) {
  5215. //do noting
  5216. } else {
  5217. drawCol(this.ctx, point, len, this.conf.gridColor, 1);
  5218. }
  5219. if (this.xstyle_axis & PlotGrid.NO_AXIS) {
  5220. //do nothing
  5221. } else {
  5222. var point = new Point(points[i].key, this.yEnd.y);
  5223. //画线
  5224. drawCol(this.ctx, point, this.conf.ledgeLen, this.conf.axisColor, 1);
  5225. var offset = 0;
  5226. if (i == points.length - 1) {
  5227. var text = this.getText(axis_option.style | PlotGrid.ADD_YEAR, points[i].value, axis_option.unit);
  5228. offset = -20;
  5229. } else {
  5230. var text = this.getText(axis_option.style, points[i].value, axis_option.unit);
  5231. }
  5232. writeText(this.ctx, new Point(points[i].key + offset,
  5233. this.yEnd.y + this.conf.ledgeLen + 12), text, this.conf.fontColor, this.conf.font);
  5234. }
  5235. }
  5236. }
  5237. //如果是固定像素的形式的,xstart 是开始index xend 是结束的 index xunit 是数据
  5238. //设计默认是xend 是画在最右边,如果屏幕像素不够,自动会舍弃xstart 这边的。
  5239. PlotGrid.prototype.drawBg = function() {
  5240. this.ctx.fillStyle = this.conf.bgColor;
  5241. this.ctx.fillRect(0, 0, this.width, this.height);
  5242. }
  5243. //update by fangxiao from 2016、6/29 17:24
  5244. PlotGrid.prototype.drawBoder = function(axis) {
  5245. /*
  5246. if (!axis) axis = this.axis;
  5247. axis_option = axis.viewconfig.x.axis_option;
  5248. var points = axis.viewconfig.x.axis;
  5249. if (typeof points === "undefined")
  5250. {
  5251. return;
  5252. }*/
  5253. //绘制底部线条
  5254. this.ctx.lineWidth = 0.85;
  5255. this.ctx.strokeStyle = this.conf.axisColor;
  5256. //this.ctx.moveTo(this.O.x + 0.5,this.0.y+this.O.y-this.yend.y+0.5);
  5257. //this.ctx.lineTo(this.xEnd.x+0.5,this.0.y+this.O.y-this.yend.y+0.5);
  5258. //this.ctx.stroke();
  5259. //this.ctx.moveTo(this.O.x + 0.5,this.yEnd.y - this.O.y);
  5260. //this.ctx.lineTo(this.xEnd.x - this.O.x, this.yEnd.y - this.O.y);
  5261. //this.ctx.fill();
  5262. // this.ctx.stroke();
  5263. this.ctx.strokeRect(this.O.x + 0.5, this.O.y + 0.5, this.xEnd.x - this.O.x, this.yEnd.y - this.O.y);
  5264. }
  5265. PlotGrid.prototype.getText = function(style, value, unit) {
  5266. if (style & Axis.TIME) {
  5267. var format = this.config.Global.timeformat[this.axis.p];
  5268. if (style & PlotGrid.ADD_YEAR) {
  5269. format = "Y-" + format;
  5270. }
  5271. var text = timeToDate(value, format, this.config.Global.timezone);
  5272. } else {
  5273. var text = GetText(value, unit);
  5274. }
  5275. return text;
  5276. }
  5277. PlotGrid.minwidth = 1; //每个图形点的最小值,至少是一个像素
  5278. PlotGrid.moveQueue = [];
  5279. PlotGrid.moveTimeid = null;
  5280. PlotGrid.xleft = 0;
  5281. PlotGrid.ytop = 0;
  5282. //1. 情况1: 指标 和
  5283. //加载第一次数据被绑定
  5284. //2. 情况2:在加载数据的时候,这在初始化。【这个时候,加一个任务,初始化未初始化的指标】
  5285. //3. 情况3:数据已经初始化完成了,指标被加入。这个时候,马上初始化指标。然后,新下载的数据,先让指标自己缓存起来。
  5286. //4. 暂时只考虑被绑定的情况
  5287. PlotGrid.setMoveInterval = function(mode, _this) {
  5288. if (PlotGrid.moveTimeid !== null) return;
  5289. debug(mode);
  5290. if (typeof mode === "undefined") {
  5291. mode = "mouse";
  5292. }
  5293. if (mode == "mouse") {
  5294. PlotGrid.mode = mode;
  5295. //var _time = 30;
  5296. var _time = 10;
  5297. PlotGrid.minwidth = _this.view.plot[_this.view.config.mainName].getOneSize();
  5298. } else if (mode == "key") {
  5299. PlotGrid.mode = mode;
  5300. //var _time = 100;
  5301. var _time = 100;
  5302. } else {
  5303. //do nothing
  5304. PlotGrid.mode = mode;
  5305. }
  5306. if (window["FlashCanvas"]) {
  5307. //_time = 60;
  5308. _time = 60;
  5309. }
  5310. this.moveTimeid = window.setInterval(function() {
  5311. if (PlotGrid.moveQueue.length > 0) {
  5312. debug("setInterval draw beg");
  5313. PlotGrid.moveTo(PlotGrid.moveQueue.pop(), _this);
  5314. debug("setInterval draw end");
  5315. PlotGrid.moveQueue = [];
  5316. }
  5317. }, _time);
  5318. debug(this.moveTimeid);
  5319. }
  5320. PlotGrid.clearMoveInterval = function(_this) {
  5321. if (PlotGrid.moveQueue.length > 0) {
  5322. PlotGrid.moveTo(PlotGrid.moveQueue.pop(), _this);
  5323. PlotGrid.moveQueue = [];
  5324. }
  5325. if (PlotGrid.moveTimeid !== null) window.clearInterval(PlotGrid.moveTimeid);
  5326. debug("clearMoveInterval");
  5327. PlotGrid.moveTimeid = null;
  5328. }
  5329. PlotGrid.prototype.getYValue = function(y, axis) {
  5330. if (typeof axis === "undefined") {
  5331. axis = this.axis;
  5332. }
  5333. var value = this.axis.getYValue(y, this.conf.crossYMode, axis);
  5334. if (value === false) return;
  5335. var opt = axis.viewconfig.y.axis_option;
  5336. value = this.getText(opt.style, value, opt.unit);
  5337. return value;
  5338. }
  5339. PlotGrid.prototype.addEvent = function() {
  5340. this.active = true;
  5341. //这两个事件在主图中注册就可以了
  5342. $(this.canvasContainer).bind('mousedown touchstart', this, function(e) {
  5343. debug('mousedown');
  5344. var _this = e.data;
  5345. //PlotGrid.xleft = e.pageX;
  5346. PlotGrid.xleft = isPC() ? e.pageX - $(this).offset().left : e.originalEvent.targetTouches[0].pageX - $(this).offset().left;
  5347. PlotGrid.setMoveInterval('mouse', _this);
  5348. var canvas_mousemove = function(e) {
  5349. //console.log("move");
  5350. var _this = e.data;
  5351. //var newxleft = e.pageX - $(this).offset().left;
  5352. var newxleft = isPC() ? e.pageX - $(this).offset().left : e.originalEvent.targetTouches[0].pageX - $(this).offset().left;
  5353. PlotGrid.moveQueue.push(newxleft);
  5354. debug("move to " + newxleft);
  5355. return false;
  5356. };
  5357. $(_this.canvasContainer).bind('mousemove touchmove', _this, canvas_mousemove);
  5358. var _canvas = _this.canvas;
  5359. if (_canvas.selector == "#plot_canvas_02") {
  5360. /*var x = e.pageX - $(_canvas).offset().left;*/
  5361. var x = isPC() ? e.pageX - $(_canvas).offset().left : e.originalEvent.targetTouches[0].pageX - $(_canvas).offset().left;
  5362. /*var y = e.pageY - $(_canvas).offset().top;*/
  5363. var y = isPC() ? e.pageY - $(_canvas).offset().top : e.originalEvent.targetTouches[0].pageY - $(_canvas).offset().top;
  5364. /*
  5365. if(_this.xEnd.x >x && (_this.xEnd.x-x)<40){
  5366. $("#tool_list").find("li[name='order']").css('cursor', 'pointer');
  5367. $("#ordershow").val(_this.getYValue(y));
  5368. $("#orderprice").val( $("#ordershow").val());
  5369. $("#orderdirection").html("买");
  5370. order.show();
  5371. }else if(_this.xEnd.x <x){
  5372. $("#tool_list").find("li[name='order']").css('cursor', 'pointer');
  5373. $("#ordershow").val(_this.getYValue(y));
  5374. $("#orderprice").val( $("#ordershow").val());
  5375. $("#orderdirection").html("卖");
  5376. order.show();
  5377. }*/
  5378. }
  5379. $(document).bind('mouseup touchend', _this, function(e) {
  5380. var _this = e.data;
  5381. $(_this.canvasContainer).unbind('mousemove', canvas_mousemove);
  5382. $(this).unbind('mouseup');
  5383. PlotGrid.clearMoveInterval(_this);
  5384. return false;
  5385. });
  5386. return false;
  5387. });
  5388. $(this.resize).bind("mousedown touchstart", this, function(e) {
  5389. debug("resize mouse down");
  5390. var _this = e.data;
  5391. //PlotGrid.ytop = e.pageY;
  5392. PlotGrid.ytop = isPC() ? e.pageY : e.originalEvent.targetTouches[0].pageY;
  5393. PlotGrid.setMoveInterval('resize', _this);
  5394. $("body").css("cursor", "n-resize");
  5395. var document_mousemove = function(e) {
  5396. var _this = e.data;
  5397. //var newxtop = e.pageY;
  5398. var newxtop = isPC() ? e.pageY : e.originalEvent.targetTouches[0].pageY;
  5399. PlotGrid.moveQueue.push(newxtop);
  5400. debug("move to new top " + newxtop);
  5401. return false;
  5402. };
  5403. $(document).bind('mousemove tonchmove', _this, document_mousemove);
  5404. $(document).bind('mouseup touchend', _this, function(e) {
  5405. $(document).unbind('mousemove tonchmove', document_mousemove);
  5406. $("body").css("cursor", "default");
  5407. $(document).unbind('mouseup');
  5408. PlotGrid.clearMoveInterval(_this);
  5409. return false;
  5410. });
  5411. return false;
  5412. });
  5413. this.bindHover();
  5414. }
  5415. //鼠标经过的位置hover出框框
  5416. PlotGrid.prototype.bindHover = function() {
  5417. var _this = this;
  5418. var mouseMoveInterval = new IntervalEvent(
  5419. 3,
  5420. function(controller) //可以重新被call
  5421. {
  5422. if (!this.value || this.value.length != 4) {
  5423. return;
  5424. }
  5425. var x = this.value[0];
  5426. var y = this.value[1];
  5427. var time = this.value[2];
  5428. if (time < 0) //已经显示过了,不用再显示了。
  5429. {
  5430. return;
  5431. }
  5432. var newtime = (new Date()).getTime();
  5433. if (newtime - time >= PlotGrid._this.config.Global.hoverTime) {
  5434. var show = 1;
  5435. this.value[2] = -1;
  5436. } else {
  5437. var show = 0;
  5438. }
  5439. // console.log("time:"+time+",newtime:"+newtime+",show:"+show+",x:"+x+",y:"+y);//头部标题内容
  5440. if (this.X && this.Y) {
  5441. var index = find_near(this.X, x);
  5442. if ((index != -1) && (Math.abs(this.X[index] - x) <= this.getOneSize())) {
  5443. var ohlc = this.Y[index];
  5444. if (ohlc[Data.HIGH] - this.config.Global.overPadding <= y && ohlc[Data.LOW] + this.config.Global.overPadding >= y) {
  5445. var findTime = this.axis.getXValue(x, PlotGrid.NEAR);
  5446. if (findTime === false) return;
  5447. var cdata = this.view.model.getDataByTime(this.name, findTime, "candle");
  5448. if (!cdata) return false;
  5449. var time = cdata.time;
  5450. var ohlc = cdata.data;
  5451. var yunit = this.axis.viewconfig.y.axis_option.unit;
  5452. var fallOrDegrees = parseFloat(GetText(ohlc[Data.CLOSE], yunit) - GetText(ohlc[Data.OPEN], yunit)) / parseFloat(GetText(ohlc[Data.OPEN], yunit));
  5453. var fallOrDegrees = fallOrDegrees.toFixed(3);
  5454. //timeLine Data
  5455. // timelineData(time, GetText(ohlc[Data.OPEN], yunit), GetText(ohlc[Data.HIGH], yunit), GetText(ohlc[Data.LOW], yunit), GetText(ohlc[Data.CLOSE], yunit), fallOrDegrees, GetText(ohlc[Data.VOLUMES], yunit));
  5456. // console.log("text PlotCandle");
  5457. }
  5458. }
  5459. }
  5460. PlotGrid.doHover(x, y, this.value[3], show);
  5461. }, true
  5462. );
  5463. $(this.canvas).bind("mousemove touchmove", this, this.mouseMove);
  5464. this.controller.addIntervalEvent("mouseMoveInterval", mouseMoveInterval);
  5465. $(this.canvas).bind("mouseout touchend", this, function(e) {
  5466. $("#msgbox").hide();
  5467. });
  5468. }
  5469. PlotGrid.prototype.mouseMove = function(e) {
  5470. var _this = e.data;
  5471. PlotGrid._this = _this;
  5472. var _canvas = _this.canvas;
  5473. //var x = e.pageX - $(_canvas).offset().left;
  5474. var x = isPC() ? e.pageX - $(_canvas).offset().left : e.originalEvent.targetTouches[0].pageX - $(_canvas).offset().left;
  5475. //var y = e.pageY - $(_canvas).offset().top;
  5476. var y = isPC() ? e.pageY - $(_canvas).offset().top : e.originalEvent.targetTouches[0].pageY - $(_canvas).offset().top;
  5477. var time = (new Date()).getTime();
  5478. var interval = _this.controller.intervalEvent.mouseMoveInterval;
  5479. //位置没有变化,不进行处理
  5480. if (interval.value && interval.value[0] == x && interval.value[1] == y) {
  5481. return;
  5482. }
  5483. interval.setVal([x, y, time, e]);
  5484. }
  5485. //十字光标经过操作
  5486. PlotGrid.doHover = function(x, y, e, showhover) {
  5487. var _this = PlotGrid._this;
  5488. if (!showhover) {
  5489. if ($("#msgbox").css('display') != "none") {
  5490. $("#msgbox").css("top", -1000).css("left", -1000);
  5491. $("#msgbox").hide();
  5492. //debugx("hide1: " + x + "," + y);
  5493. }
  5494. return false;
  5495. }
  5496. //_this.controller.intervalEvent.mouseMoveInterval.setVal(null);
  5497. var overstr = '';
  5498. for (var i = _this.plot.length - 1; i >= 0; i--) {
  5499. if (_this.plot[i].obj.over) { //将内容加入头部
  5500. overstr = _this.plot[i].obj.over(x, y);
  5501. if (overstr) break;
  5502. }
  5503. }
  5504. if (overstr) {
  5505. $("#msgbox").html(overstr);
  5506. //debugx("show: " + x + "," + y);
  5507. var top = e.pageY + 10;
  5508. var left = e.pageX + 10;
  5509. var w = $("#msgbox").width();
  5510. var h = $("#msgbox").height();
  5511. if (top + h + 10 > $(window).height()) {
  5512. top = $(window).height() - h - 12;
  5513. }
  5514. if (left + w + 10 > $(window).width()) {
  5515. left = $(window).width() - w - 12;
  5516. }
  5517. $("#msgbox").css("top", top).css("left", left);
  5518. $("#msgbox").show();
  5519. } else {
  5520. $("#msgbox").css("top", -1000).css("left", -1000);
  5521. $("#msgbox").hide();
  5522. //debugx("hide2: " + x + "," + y);
  5523. }
  5524. }
  5525. PlotGrid.prototype.removeEvent = function() {
  5526. this.active = false;
  5527. $(document).unbind("keydown");
  5528. $(this.canvas).unbind('mousedown uchstartto');
  5529. $(this.canvas).unbind('mousemove touchmove');
  5530. $(document).unbind('mouseup touchend');
  5531. }
  5532. PlotGrid.moveTo = function(newxleft, _this) {
  5533. if (PlotGrid.mode == "mouse") {
  5534. if (newxleft - PlotGrid.xleft > PlotGrid.minwidth) //move to left
  5535. {
  5536. _this.controller.startOffset(Math.round((newxleft - PlotGrid.xleft) / PlotGrid.minwidth));
  5537. _this.controller.draw();
  5538. PlotGrid.xleft = newxleft;
  5539. } else if (PlotGrid.xleft - newxleft > PlotGrid.minwidth) {
  5540. _this.controller.startOffset(-Math.round((PlotGrid.xleft - newxleft) / PlotGrid.minwidth));
  5541. _this.controller.draw();
  5542. PlotGrid.xleft = newxleft;
  5543. }
  5544. } else if (PlotGrid.mode == "key") {
  5545. _this.controller.draw();
  5546. } else if (PlotGrid.mode == "resize") {
  5547. _this.view.resizeGrid(newxleft - PlotGrid.ytop, _this.index);
  5548. _this.controller.draw();
  5549. PlotGrid.ytop = newxleft;
  5550. }
  5551. }
  5552. PlotGrid.prototype.addPlot = function(name, plot) {
  5553. var obj = { name: name, obj: plot };
  5554. this.plot.push(obj);
  5555. }
  5556. PlotGrid.prototype.removePlot = function(name) {
  5557. var plot = [];
  5558. for (var i = 0; i < plot.length; i++) {
  5559. var item = plot[i];
  5560. if (item.name != name) {
  5561. plot.push(item);
  5562. }
  5563. }
  5564. this.plot = plot;
  5565. }
  5566. function isPC() {
  5567. var userAgentInfo = navigator.userAgent;
  5568. //alert(userAgentInfo)
  5569. var Agents = ["Android", "iPhone",
  5570. "SymbianOS", "Windows Phone",
  5571. "iPad", "iPod"
  5572. ];
  5573. var flag = true;
  5574. for (var v = 0; v < Agents.length; v++) {
  5575. if (userAgentInfo.indexOf(Agents[v]) > 0) {
  5576. flag = false;
  5577. break;
  5578. }
  5579. }
  5580. return flag;
  5581. }
  5582. function PlotKshape(view, grid, name) {
  5583. sup(this, view, grid, name);
  5584. }
  5585. ClassExtend(PlotKshape, Plot);
  5586. PlotKshape.tagMap = {
  5587. 1: "A",
  5588. 2: "a",
  5589. 3: "B",
  5590. 4: "b",
  5591. 5: "C",
  5592. 6: "c",
  5593. 7: "D",
  5594. 8: "d",
  5595. 9: "E",
  5596. 10: "e",
  5597. 11: "N",
  5598. 12: "n",
  5599. 13: "W",
  5600. 14: "w",
  5601. 15: "X",
  5602. 16: "x",
  5603. 17: "F",
  5604. 18: "f",
  5605. 19: "L",
  5606. 20: "l",
  5607. 21: "T",
  5608. 22: "t",
  5609. 23: "G",
  5610. 24: "g",
  5611. 25: "Z",
  5612. 26: "z",
  5613. 27: "V",
  5614. 28: "v",
  5615. 29: "J",
  5616. 30: "j",
  5617. 31: "Y",
  5618. 32: "y"
  5619. };
  5620. PlotKshape.prototype.draw = function(data) {
  5621. //建立点
  5622. var color;
  5623. if (this.param.lineColor) {
  5624. color = this.param.lineColor;
  5625. } else {
  5626. color = this.conf.lineColor;
  5627. }
  5628. for (var i = 0; i < data.x.length; i++) {
  5629. if (data.y[i][1] != -1) {
  5630. writeText(this.ctx, new Point(data.x[i], data.y[i][0]), PlotKshape.tagMap[data.y[i][1]], color[0], this.param.font);
  5631. }
  5632. if (data.y[i][2] != -1) {
  5633. writeText(this.ctx, new Point(data.x[i], data.y[i][0] + 12), PlotKshape.tagMap[data.y[i][2]], color[1], this.param.font);
  5634. }
  5635. }
  5636. }
  5637. function PlotLine(view, grid, name) {
  5638. sup(this, view, grid, name);
  5639. }
  5640. ClassExtend(PlotLine, Plot);
  5641. PlotLine.prototype.draw = function(data) {
  5642. //建立点
  5643. var color;
  5644. if (this.param.color) {
  5645. color = this.param.color;
  5646. } else {
  5647. color = this.conf.lineColor;
  5648. }
  5649. drawLine(this.ctx, data.x, data.y, color);
  5650. }
  5651. function PlotMacd(view, grid, name) {
  5652. sup(this, view, grid, name);
  5653. }
  5654. ClassExtend(PlotMacd, Plot);
  5655. PlotMacd.prototype.draw = function(data) {
  5656. //建立点
  5657. var color;
  5658. if (this.param.color) {
  5659. color = this.param.color.split("-");
  5660. } else {
  5661. color = this.conf.lineColor;
  5662. }
  5663. var y1 = []
  5664. var y2 = []
  5665. for (var i = 0; i < data.y.length; i++) {
  5666. y1[i] = data.y[i][0];
  5667. y2[i] = data.y[i][1];
  5668. }
  5669. //color[1] = "rgb(112,207,88)";
  5670. drawLine(this.ctx, data.x, y2, color[0],1.5);
  5671. this.plotBar(data.x, y1, color[1]);
  5672. }
  5673. PlotMacd.prototype.getShowName = function() {
  5674. var name = this.name.toUpperCase();
  5675. name = name.replace("MAIN", "").replace("||", " ");
  5676. name = name.split("|");
  5677. if (name.length == 1) {
  5678. return name[0];
  5679. }
  5680. var pre = name.shift();
  5681. return pre + " (" + name.join(" , ") + ")";
  5682. }
  5683. PlotMacd.prototype.plotBar = function(x, H, colorbar) {
  5684. var zero_y = this.axis.getY(0);
  5685. drawRow(this.ctx, { x: this.left, y: zero_y }, this.right - this.left, this.conf.lineColorZero);
  5686. this.ctx.beginPath();
  5687. this.ctx.strokeStyle = colorbar;
  5688. for (var i = 0; i < x.length; i++) {
  5689. try {
  5690. if (isNaN(H[i])) continue;
  5691. this.ctx.moveTo(x[i] + 0.5, zero_y);
  5692. this.ctx.lineTo(x[i] + 0.5, H[i]);
  5693. } catch (e) {
  5694. // console.log(e);
  5695. // console.log(x[i]);
  5696. // console.log(H[i]);
  5697. }
  5698. }
  5699. this.ctx.stroke();
  5700. }
  5701. function Plotmatrend(view, grid, name) {
  5702. sup(this, view, grid, name);
  5703. }
  5704. ClassExtend(Plotmatrend, Plot);
  5705. Plotmatrend.prototype.draw = function(data) {
  5706. //建立点
  5707. var color;
  5708. if (this.param.color) {
  5709. color = this.param.color;
  5710. } else {
  5711. color = this.conf.lineColor;
  5712. }
  5713. var y1 = []
  5714. var y2 = []
  5715. var y3 = []
  5716. var y4 = []
  5717. var y5 = []
  5718. var y6 = []
  5719. for (var i = 0; i < data.y.length; i++) {
  5720. y1[i] = data.y[i][0];
  5721. y2[i] = data.y[i][1];
  5722. y3[i] = data.y[i][2];
  5723. y4[i] = data.y[i][3];
  5724. y5[i] = data.y[i][4];
  5725. y6[i] = data.y[i][5]
  5726. }
  5727. drawLine(this.ctx, data.x, y1, color[0]);
  5728. drawLine(this.ctx, data.x, y2, color[1]);
  5729. drawLine(this.ctx, data.x, y3, color[2]);
  5730. drawLine(this.ctx, data.x, y4, color[3]);
  5731. drawLine(this.ctx, data.x, y5, color[4]);
  5732. drawLine(this.ctx, data.x, y6, color[5]);
  5733. }
  5734. function PlotMLine(view, grid, name) {
  5735. sup(this, view, grid, name);
  5736. this.laststatus = "";
  5737. this.lastquick = "";
  5738. }
  5739. ClassExtend(PlotMLine, Plot);
  5740. PlotMLine.prototype.draw = function(data) {
  5741. //建立点,mline的格式
  5742. //
  5743. var color, width;
  5744. this.data = data;
  5745. var last = this.lastData();
  5746. for (var key in data.data) {
  5747. if (this.param[key.toLowerCase() + "_color"]) {
  5748. color = this.param[key.toLowerCase() + "_color"];
  5749. } else {
  5750. color = this.conf.lineColor;
  5751. }
  5752. if (data.width && data.width[key]) {
  5753. width = data.width[key];
  5754. //console.log(width);
  5755. }
  5756. if (data.data[key].x.length > 0) {
  5757. drawLine(this.ctx, data.data[key].x, data.data[key].y, color, width);
  5758. }
  5759. if (this.param[key.toLowerCase() + "_flag"]) {
  5760. this.priceFlag(last[key].bidask[0], this.config.Global.Candle["public"].close);
  5761. }
  5762. }
  5763. }
  5764. PlotMLine.prototype.lastDataShow = function() {
  5765. var text = [];
  5766. text.push("Local-QuickT = " + this.data.offset.local);
  5767. text.push("QuickT-SlowT = " + this.data.offset.delt);
  5768. if (1) {
  5769. var last = this.lastData();
  5770. var laststatus = "BID(";
  5771. for (var key in last) {
  5772. laststatus += key + "=" + this.grid.getText(0, last[key].bidask[0], this.data.yunit) + " ";
  5773. }
  5774. this.laststatus = laststatus + ")";
  5775. }
  5776. if (!this.data.quick.inquick) {
  5777. var quick = this.data.quick;
  5778. if (quick.start && quick.end) {
  5779. this.lastquick = " ([" + quick.start + ", " + quick.end + "] Point: " + quick.point / 10 + " Time: " + quick.delt + ") "
  5780. }
  5781. }
  5782. return this.lastquick + this.laststatus + text.join(" , ");
  5783. }
  5784. PlotMLine.prototype.getShowName = function() {
  5785. var text = "";
  5786. var keyarr;
  5787. var name = this.name.split("|", 2)[0];
  5788. for (var key in this.param) {
  5789. if (key.indexOf("_color") !== -1) {
  5790. keyarr = key.split("_");
  5791. text += keyarr[0] + "(" + this.param[key] + ") ";
  5792. }
  5793. }
  5794. var ret = name + " " + text;
  5795. ret = ret.toUpperCase();
  5796. return ret;
  5797. }
  5798. function PlotOrder(view, grid, name) {
  5799. sup(this, view, grid, name);
  5800. this.arrow = {};
  5801. var conf = this.config.Global.arrow[DataWriterProfit.BUY_OPEN];
  5802. this.arrow[DataWriterProfit.BUY_OPEN] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
  5803. var conf = this.config.Global.arrow[DataWriterProfit.BUY_CLOSE];
  5804. this.arrow[DataWriterProfit.BUY_CLOSE] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
  5805. var conf = this.config.Global.arrow[DataWriterProfit.SELL_OPEN];
  5806. this.arrow[DataWriterProfit.SELL_OPEN] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
  5807. var conf = this.config.Global.arrow[DataWriterProfit.SELL_CLOSE];
  5808. this.arrow[DataWriterProfit.SELL_CLOSE] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
  5809. }
  5810. ClassExtend(PlotProfit, Plot);
  5811. PlotProfit.prototype.draw = function(data) {
  5812. var x, y, type;
  5813. this.X = data.x;
  5814. this.Y = data.y;
  5815. for (var i = 0; i < data.x.length; i++) {
  5816. for (var j = 0; j < data.y[i].length; j++) {
  5817. y = data.y[i][j];
  5818. type = y[0];
  5819. y = y[1];
  5820. x = this.fixedX(data.x[i], type);
  5821. this.arrow[type].draw(new Point(x, y));
  5822. }
  5823. }
  5824. }
  5825. PlotProfit.prototype.getShowName = function() {
  5826. return this.controller.c + " " + this.controller.p;
  5827. }
  5828. PlotProfit.prototype.lastDataShow = function() {
  5829. return "";
  5830. }
  5831. PlotProfit.prototype.fixedX = function(x, type) {
  5832. x += 0.5;
  5833. var box = this.view.plot[this.config.mainName].getBoxSize();
  5834. var left = this.view.plot[this.config.mainName].getBoxLeft();
  5835. if (type == DataWriterProfit.BUY_OPEN || type == DataWriterProfit.SELL_OPEN) {
  5836. x -= left;
  5837. } else {
  5838. x += box - left;
  5839. }
  5840. return x;
  5841. }
  5842. PlotProfit.prototype.over = function(x1, y1) {
  5843. if (!this.X) {
  5844. return false;
  5845. }
  5846. var x, y, type, bk = false;
  5847. x1 += 0.5;
  5848. for (var i = 0; i < this.X.length; i++) {
  5849. for (var j = 0; j < this.Y[i].length; j++) {
  5850. y = this.Y[i][j][1];
  5851. type = this.Y[i][j][0];
  5852. x = this.fixedX(this.X[i], type);
  5853. if (this.inarrow(new Point(x, y), type, x1, y1)) {
  5854. bk = true;
  5855. break;
  5856. }
  5857. }
  5858. if (bk) {
  5859. break;
  5860. }
  5861. }
  5862. if (!bk) {
  5863. return false;
  5864. }
  5865. var findTime = this.axis.getXValue(this.X[i], PlotGrid.NEAR);
  5866. if (findTime === false) return;
  5867. var cdata = this.view.model.getDataByTime(this.name, findTime);
  5868. if (!cdata) {
  5869. return false;
  5870. }
  5871. cdata.data = cdata.data[j];
  5872. /*
  5873. var data = cdata.data[2];
  5874. var open_time = timeToDate(data[1], null, this.config.Global.timezone);
  5875. var close_time = timeToDate(data[8], null, this.config.Global.timezone);
  5876. return "Ticket: " + data[0] + "<br />" +
  5877. "Open Time: " + open_time + "<br />" +
  5878. "Close Time: " + close_time + "<br />" +
  5879. "Open Price: " + data[5] + "<br />" +
  5880. "Close Price:" + data[9] + "<br />" +
  5881. "Size: " + data[3] + "<br />" +
  5882. "Profit: " + data[13] + "<br />";
  5883. */
  5884. return "<b>Type</b>: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + (DataWriterProfit.nameMap[cdata.data[0]]) + "<br/>" +
  5885. "<b>Price</b>: &nbsp;&nbsp;&nbsp;&nbsp;" + cdata.data[1] + "<br/>" +
  5886. "<b>OrderID</b>: " + cdata.data[2] + "<br/>";
  5887. }
  5888. //某个坐标是否在某个点内部
  5889. PlotProfit.prototype.inarrow = function(point, type, x, y) {
  5890. var conf = this.config.Global.arrow[type];
  5891. var cta = conf.incta;
  5892. var len = conf.height;
  5893. var width = conf.width + 5;
  5894. point.y = -point.y;
  5895. y = -y;
  5896. var newpoint = axis_translate(new Point(x, y), cta, point);
  5897. if (newpoint.x >= 0 && newpoint.x <= len && Math.abs(newpoint.y) <= width) {
  5898. return true;
  5899. } else {
  5900. return false;
  5901. }
  5902. }
  5903. function Plotcombinparam1001(view, grid, name) {
  5904. sup(this, view, grid, name);
  5905. }
  5906. ClassExtend(Plotcombinparam1001, Plot);
  5907. Plotcombinparam1001.prototype.draw = function(data) {
  5908. //建立点
  5909. var color;
  5910. if (this.param.color) {
  5911. color = this.param.color;
  5912. } else {
  5913. color = this.conf.lineColor;
  5914. }
  5915. var y1 = []
  5916. var y2 = []
  5917. var y3 = []
  5918. var y4 = []
  5919. var y5 = []
  5920. var y6 = []
  5921. for (var i = 0; i < data.y.length; i++) {
  5922. y1[i] = data.y[i][0];
  5923. y2[i] = data.y[i][1];
  5924. y3[i] = data.y[i][2];
  5925. y4[i] = data.y[i][3];
  5926. y5[i] = data.y[i][4];
  5927. y6[i] = data.y[i][5];
  5928. }
  5929. drawLine(this.ctx, data.x, y1, color[0]);
  5930. drawLine(this.ctx, data.x, y2, color[1]);
  5931. drawLine(this.ctx, data.x, y3, color[2]);
  5932. drawLine(this.ctx, data.x, y4, color[3]);
  5933. drawLine(this.ctx, data.x, y5, color[4]);
  5934. drawLine(this.ctx, data.x, y6, color[5]);
  5935. }
  5936. function PlotProfit(view, grid, name) {
  5937. sup(this, view, grid, name);
  5938. this.arrow = {};
  5939. var conf = this.config.Global.arrow[DataWriterProfit.BUY_OPEN];
  5940. this.arrow[DataWriterProfit.BUY_OPEN] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
  5941. var conf = this.config.Global.arrow[DataWriterProfit.BUY_CLOSE];
  5942. this.arrow[DataWriterProfit.BUY_CLOSE] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
  5943. var conf = this.config.Global.arrow[DataWriterProfit.SELL_OPEN];
  5944. this.arrow[DataWriterProfit.SELL_OPEN] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
  5945. var conf = this.config.Global.arrow[DataWriterProfit.SELL_CLOSE];
  5946. this.arrow[DataWriterProfit.SELL_CLOSE] = new ShapeArrow(this.ctx, conf.width, conf.height, conf);
  5947. }
  5948. ClassExtend(PlotProfit, Plot);
  5949. PlotProfit.prototype.draw = function(data) {
  5950. var x, y, type;
  5951. this.X = data.x;
  5952. this.Y = data.y;
  5953. for (var i = 0; i < data.x.length; i++) {
  5954. for (var j = 0; j < data.y[i].length; j++) {
  5955. y = data.y[i][j];
  5956. type = y[0];
  5957. y = y[1];
  5958. x = this.fixedX(data.x[i], type);
  5959. this.arrow[type].draw(new Point(x, y));
  5960. }
  5961. }
  5962. }
  5963. PlotProfit.prototype.getShowName = function() {
  5964. return this.controller.c + " " + this.controller.p;
  5965. }
  5966. PlotProfit.prototype.lastDataShow = function() {
  5967. return "";
  5968. }
  5969. PlotProfit.prototype.fixedX = function(x, type) {
  5970. x += 0.5;
  5971. var box = this.view.plot[this.config.mainName].getBoxSize();
  5972. var left = this.view.plot[this.config.mainName].getBoxLeft();
  5973. if (type == DataWriterProfit.BUY_OPEN || type == DataWriterProfit.SELL_OPEN) {
  5974. x -= left;
  5975. } else {
  5976. x += box - left;
  5977. }
  5978. return x;
  5979. }
  5980. PlotProfit.prototype.over = function(x1, y1) {
  5981. if (!this.X) {
  5982. return false;
  5983. }
  5984. var x, y, type, bk = false;
  5985. x1 += 0.5;
  5986. for (var i = 0; i < this.X.length; i++) {
  5987. for (var j = 0; j < this.Y[i].length; j++) {
  5988. y = this.Y[i][j][1];
  5989. type = this.Y[i][j][0];
  5990. x = this.fixedX(this.X[i], type);
  5991. if (this.inarrow(new Point(x, y), type, x1, y1)) {
  5992. bk = true;
  5993. break;
  5994. }
  5995. }
  5996. if (bk) {
  5997. break;
  5998. }
  5999. }
  6000. if (!bk) {
  6001. return false;
  6002. }
  6003. var findTime = this.axis.getXValue(this.X[i], PlotGrid.NEAR);
  6004. if (findTime === false) return;
  6005. var cdata = this.view.model.getDataByTime(this.name, findTime);
  6006. if (!cdata) {
  6007. return false;
  6008. }
  6009. cdata.data = cdata.data[j];
  6010. /*
  6011. var data = cdata.data[2];
  6012. var open_time = timeToDate(data[1], null, this.config.Global.timezone);
  6013. var close_time = timeToDate(data[8], null, this.config.Global.timezone);
  6014. return "Ticket: " + data[0] + "<br />" +
  6015. "Open Time: " + open_time + "<br />" +
  6016. "Close Time: " + close_time + "<br />" +
  6017. "Open Price: " + data[5] + "<br />" +
  6018. "Close Price:" + data[9] + "<br />" +
  6019. "Size: " + data[3] + "<br />" +
  6020. "Profit: " + data[13] + "<br />";
  6021. */
  6022. return "<b>Type</b>: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + (DataWriterProfit.nameMap[cdata.data[0]]) + "<br/>" +
  6023. "<b>Price</b>: &nbsp;&nbsp;&nbsp;&nbsp;" + cdata.data[1] + "<br/>" +
  6024. "<b>OrderID</b>: " + cdata.data[2] + "<br/>";
  6025. }
  6026. //某个坐标是否在某个点内部
  6027. PlotProfit.prototype.inarrow = function(point, type, x, y) {
  6028. var conf = this.config.Global.arrow[type];
  6029. var cta = conf.incta;
  6030. var len = conf.height;
  6031. var width = conf.width + 5;
  6032. point.y = -point.y;
  6033. y = -y;
  6034. var newpoint = axis_translate(new Point(x, y), cta, point);
  6035. if (newpoint.x >= 0 && newpoint.x <= len && Math.abs(newpoint.y) <= width) {
  6036. return true;
  6037. } else {
  6038. return false;
  6039. }
  6040. }
  6041. function Plotrsi(view, grid, name) {
  6042. sup(this, view, grid, name);
  6043. }
  6044. ClassExtend(Plotrsi, Plot);
  6045. Plotrsi.prototype.draw = function(data) {
  6046. this.plotBar(data.x, data.y);
  6047. }
  6048. Plotrsi.prototype.lastDataShow = function() {
  6049. var data = this.lastData();
  6050. return data;
  6051. }
  6052. Plotrsi.prototype.plotBar = function(x, H) {
  6053. var zero_y = this.axis.getY(50);
  6054. drawRow(this.ctx, { x: this.left, y: zero_y }, this.right - this.left, this.conf.lineColorZero);
  6055. this.ctx.beginPath();
  6056. this.ctx.strokeStyle = this.conf.lineColorH;
  6057. for (var i = 0; i < x.length; i++) {
  6058. try {
  6059. if (isNaN(H[i])) continue;
  6060. this.ctx.moveTo(x[i] + 0.5, zero_y);
  6061. this.ctx.lineTo(x[i] + 0.5, H[i]);
  6062. } catch (e) {
  6063. // console.log(e);
  6064. // console.log(x[i]);
  6065. // console.log(H[i]);
  6066. }
  6067. }
  6068. this.ctx.stroke();
  6069. }
  6070. function Plotrsisma(view, grid, name) {
  6071. sup(this, view, grid, name);
  6072. //放大缩小尺寸控制更加灵活。采用配置数组的形式
  6073. this.box = [1, 2, 3, 5, 7, 9, 11, 13];
  6074. this.space = [0, 1, 1, 2, 2, 3, 4, 5];
  6075. this.left = [0, 1, 1, 2, 3, 4, 5, 6]
  6076. }
  6077. ClassExtend(Plotrsisma, Plot);
  6078. Plotrsisma.prototype.zoomIn = function() {
  6079. if (this.conf.box_pixel >= 7 && this.conf.space_pixel >= 7) {
  6080. return;
  6081. }
  6082. if (this.conf.box_pixel < this.conf.space_pixel) {
  6083. this.conf.box_pixel++;
  6084. } else if (this.conf.box_pixel > this.conf.space_pixel) {
  6085. this.spaceOffset(1);
  6086. } else {
  6087. this.conf.box_pixel++;
  6088. }
  6089. }
  6090. Plotrsisma.prototype.spaceOffset = function(offset) {
  6091. var prev = this.space[this.conf.space_pixel];
  6092. this.conf.space_pixel = this.conf.space_pixel + offset;
  6093. var current = this.space[this.conf.space_pixel];
  6094. if (prev == current) {
  6095. this.conf.box_pixel = this.conf.box_pixel + offset;
  6096. }
  6097. }
  6098. Plotrsisma.prototype.zoomOut = function() {
  6099. if (this.conf.box_pixel <= 0 && this.conf.space_pixel <= 0) {
  6100. return;
  6101. }
  6102. if (this.conf.box_pixel < this.conf.space_pixel) {
  6103. this.spaceOffset(-1);
  6104. } else if (this.conf.box_pixel > this.conf.space_pixel) {
  6105. this.conf.box_pixel--;
  6106. } else {
  6107. this.spaceOffset(-1);
  6108. }
  6109. this.conf.box_pixel = this.conf.box_pixel < 0 ? 0 : this.conf.box_pixel;
  6110. }
  6111. Plotrsisma.prototype.getOneSize = function() {
  6112. return this.box[this.conf.box_pixel] + 2 * this.space[this.conf.space_pixel];
  6113. }
  6114. Plotrsisma.prototype.getBoxLeft = function() {
  6115. return this.left[this.conf.box_pixel];
  6116. }
  6117. Plotrsisma.prototype.getBoxSize = function() {
  6118. return this.box[this.conf.box_pixel];
  6119. }
  6120. Plotrsisma.prototype.draw = function(data) {
  6121. this.data = data;
  6122. this.X = data.x;
  6123. this.Y = data.y;
  6124. this.xunit = this.data.xunit;
  6125. this.yunit = this.data.yunit;
  6126. var width = this.box[this.conf.box_pixel];
  6127. var left = this.left[this.conf.box_pixel];
  6128. if (width > 2) {
  6129. width--;
  6130. }
  6131. for (var i = 0; i < this.X.length; i++) {
  6132. this.drawOne(this.X[i], this.Y[i], width, left);
  6133. }
  6134. var ySma = []
  6135. for (var i = 0; i < data.y.length; i++) {
  6136. ySma[i] = data.y[i][7];
  6137. }
  6138. drawLine(this.ctx, data.x, ySma, this.conf.SmaColor);
  6139. }
  6140. //鼠标经过十字光标显示的内容框
  6141. Plotrsisma.prototype.over = function(x, y) {
  6142. //查找最接近的
  6143. // console.log("1");
  6144. if (!this.X || !this.Y) return;
  6145. var index = find_near(this.X, x);
  6146. if (index == -1) return false;
  6147. if (Math.abs(this.X[index] - x) > this.getOneSize()) {
  6148. return false;
  6149. }
  6150. var ohlc = this.Y[index];
  6151. if (ohlc[Data.HIGH] - this.config.Global.overPadding <= y && ohlc[Data.LOW] + this.config.Global.overPadding >= y) {
  6152. // console.log("Plotrsisma");
  6153. var findTime = this.axis.getXValue(x, PlotGrid.NEAR);
  6154. if (findTime === false) return;
  6155. var cdata = this.view.model.getDataByTime(this.name, findTime, "candle");
  6156. if (!cdata) return false;
  6157. var time = cdata.time;
  6158. var ohlc = cdata.data;
  6159. var yunit = this.axis.viewconfig.y.axis_option.unit;
  6160. var fallOrDegrees=parseFloat(GetText(ohlc[Data.CLOSE], yunit)-GetText(ohlc[Data.OPEN], yunit))/parseFloat(GetText(ohlc[Data.OPEN], yunit)) ;
  6161. var fallOrDegrees=fallOrDegrees.toFixed(3);
  6162. //timeLine Data
  6163. // timelineData(time,GetText(ohlc[Data.OPEN], yunit),GetText(ohlc[Data.HIGH], yunit),GetText(ohlc[Data.LOW], yunit),GetText(ohlc[Data.CLOSE], yunit),fallOrDegrees,GetText(ohlc[Data.VOLUMES], yunit));
  6164. // return time + "<br/>" + "O: " + GetText(ohlc[Data.OPEN], yunit) + "<br />" + "H: " + GetText(ohlc[Data.HIGH], yunit) + "<br />" + "L : " + GetText(ohlc[Data.LOW], yunit) + "<br />" + "C: " + GetText(ohlc[Data.CLOSE], yunit) + "<br />" +
  6165. // +"V: " + GetText(ohlc[Data.VOLUMES], yunit) + "<br />";
  6166. } else {
  6167. return false;
  6168. }
  6169. }
  6170. Plotrsisma.prototype.drawOne = function(time, ohlc, width, left) {
  6171. var ctx = this.ctx;
  6172. var open = ohlc[Data.OPEN];
  6173. var high = ohlc[Data.HIGH];
  6174. var low = ohlc[Data.LOW];
  6175. var close = ohlc[Data.CLOSE];
  6176. time += 0.5;
  6177. open += 0.5;
  6178. high += 0.5;
  6179. low += 0.5;
  6180. close += 0.5;
  6181. if (high == low) {
  6182. //画个横线就可以了
  6183. ctx.strokeStyle = this.conf.hx.os_border_color;
  6184. ctx.beginPath();
  6185. ctx.moveTo(time - left, open);
  6186. ctx.lineTo(time + width, open);
  6187. ctx.stroke();
  6188. return;
  6189. }
  6190. if (open < close) {
  6191. var up = open;
  6192. var down = close;
  6193. var fill = this.conf.hx.open_big_color;
  6194. var border = this.conf.hx.ob_border_color;
  6195. } else {
  6196. var up = close;
  6197. var down = open;
  6198. var fill = this.conf.hx.open_small_color;
  6199. var border = this.conf.hx.os_border_color;
  6200. }
  6201. ctx.strokeStyle = border;
  6202. ctx.beginPath();
  6203. ctx.moveTo(time, high);
  6204. ctx.lineTo(time, low);
  6205. ctx.stroke();
  6206. if (this.conf.space_pixel > 0) {
  6207. ctx.fillStyle = fill;
  6208. ctx.fillRect(time - left, up, width, down - up);
  6209. ctx.strokeRect(time - left, up, width, down - up);
  6210. }
  6211. }
  6212. function PlotTrendLine(view, grid, name) {
  6213. sup(this, view, grid, name);
  6214. }
  6215. ClassExtend(PlotTrendLine, Plot);
  6216. PlotTrendLine.prototype.draw = function(data) {
  6217. this.X = data.x;
  6218. this.Y = data.y;
  6219. var plot_list = this.config.Global.trend_line_selected;
  6220. if (plot_list == null) {
  6221. return;
  6222. }
  6223. for (var i = 0; i < data.x.length; i++) {
  6224. if (plot_list.indexOf("" + data.y[i][2]) == -1) {
  6225. continue;
  6226. }
  6227. this.drawTrendLine(data.x[i], data.y[i][0], data.y[i][1], data.y[i][2], data.y[i]);
  6228. }
  6229. }
  6230. PlotTrendLine.prototype.drawTrendLine = function(x, y, tan, type, data) {
  6231. //曲线方程 y = ax + b
  6232. var a = -tan;
  6233. var b = y + tan * x;
  6234. var p = [];
  6235. p[0] = {};
  6236. p[1] = {};
  6237. var i = 0;
  6238. var o = this.grid.O;
  6239. var xy = this.grid.xyEnd;
  6240. var plot_point = {};
  6241. if (data[5] == 0 && typeof data[6] !== "undefined") {
  6242. plot_point.x = data[6];
  6243. plot_point.y = data[7];
  6244. } else {
  6245. if (tan != 0) {
  6246. //和坐标轴的交点的计算
  6247. //o 点 , 和o点的对角点
  6248. //计算曲线与坐标轴的绘图区域的焦点
  6249. //top
  6250. ytop = o.y;
  6251. xtop = (ytop - b) / a;
  6252. if (i < 2 && xtop >= o.x && xtop <= xy.x) {
  6253. p[i].x = xtop;
  6254. p[i].y = ytop;
  6255. i++;
  6256. }
  6257. //bottom
  6258. ybot = xy.y;
  6259. xbot = (ybot - b) / a;
  6260. if (i < 2 && xbot >= o.x && xbot <= xy.x) {
  6261. p[i].x = xbot;
  6262. p[i].y = ybot;
  6263. i++;
  6264. }
  6265. //left
  6266. xleft = o.x;
  6267. yleft = xleft * a + b;
  6268. if (i < 2 && yleft >= o.y && yleft <= xy.y) {
  6269. p[i].x = xleft;
  6270. p[i].y = yleft;
  6271. i++;
  6272. }
  6273. //right
  6274. xright = xy.x;
  6275. yright = xright * a + b;
  6276. if (i < 2 && yright >= o.y && yright <= xy.y) {
  6277. p[i].x = xright;
  6278. p[i].y = yright;
  6279. i++;
  6280. }
  6281. } else {
  6282. p[0].x = o.x;
  6283. p[0].y = y;
  6284. p[1].x = xy.x;
  6285. p[1].y = y;
  6286. }
  6287. //从 x ,y 开始,然后绘制到边界上。
  6288. if (p[0].x > x) {
  6289. plot_point = p[0];
  6290. } else {
  6291. plot_point = p[1];
  6292. }
  6293. }
  6294. plotLine(this.ctx, { x: x, y: y }, plot_point, this.conf.lineColor[type]);
  6295. }
  6296. PlotTrendLine.prototype.over = function(x1, y1) {
  6297. //console.log(this.X);
  6298. //console.log(this.Y);
  6299. mind = Infinity;
  6300. mini = 0;
  6301. if (typeof this.X === "undefined") {
  6302. return;
  6303. }
  6304. for (var i = 0; i < this.X.length; i++) {
  6305. var d = this.distance(x1, y1, this.X[i], this.Y[i]);
  6306. if (d < mind) {
  6307. mind = d;
  6308. mini = i;
  6309. }
  6310. }
  6311. //i 是最短距离了
  6312. if (mind <= 3) {
  6313. return "<b>index:</b>" + this.Y[mini][3] + "<br/>";
  6314. }
  6315. }
  6316. PlotTrendLine.prototype.distance = function(x1, y1, x, y) {
  6317. //曲线方程
  6318. A = -y[1];
  6319. B = -1;
  6320. C = y[0] + y[1] * x;
  6321. d = Math.abs(A * x1 + B * y1 + C) / Math.sqrt(A * A + B * B);
  6322. return d;
  6323. }
  6324. function Plotvolumes(view, grid, name) {
  6325. sup(this, view, grid, name);
  6326. }
  6327. ClassExtend(Plotvolumes, Plot);
  6328. Plotvolumes.prototype.draw = function(data) {
  6329. //偏移量配置 根据function Plotrsisma(view, grid, name)函数的配置
  6330. var left = [0, 1, 1, 2, 3, 4, 5, 6];
  6331. // var left = [ 3, 4, 5, 6,7,9,10,11]
  6332. //建立点
  6333. var color;
  6334. if (this.param.color) {
  6335. color = this.param.color;
  6336. } else {
  6337. color = this.conf.lineColor;
  6338. }
  6339. var zero_y = this.axis.getY(0);
  6340. for (var i = 0; i < data.y.length - 1; i++) {
  6341. if (isNaN(data.y[i][0])) {
  6342. data.y[i][0] = 1;
  6343. }
  6344. /*if (data.y[i][0]>data.y[i+1][0]){
  6345. this.ctx.strokeStyle = color[1]; //green
  6346. }else if (data.y[i][0]<data.y[i+1][0]){
  6347. this.ctx.strokeStyle = color[0]; //red
  6348. }*/
  6349. if (data.y[i].length == 2) {
  6350. if(zero_y>data.y[i][0]){
  6351. var height=zero_y-data.y[i][0];
  6352. }
  6353. else{
  6354. var height=data.y[i][0]-zero_y;
  6355. }
  6356. this.ctx.strokeStyle = color[1]; //green
  6357. //绘制矩形 参考Plotrsisma.prototype.drawOne函数
  6358. this.ctx.closePath();
  6359. this.ctx.beginPath();
  6360. this.ctx.lineWidth = 1;
  6361. this.ctx.fillStyle = color[1];
  6362. this.ctx.fillRect(data.x[i]+0.5-left[this.config.Global.Candle.public.box_pixel],zero_y-height,this.config.Global.boxwidth,height);
  6363. this.ctx.strokeRect(data.x[i]+0.5-left[this.config.Global.Candle.public.box_pixel],zero_y-height,this.config.Global.boxwidth,height);
  6364. this.ctx.closePath();
  6365. // this.ctx.moveTo(data.x[i] + 0.5, zero_y);
  6366. // this.ctx.lineTo(data.x[i] + 0.5, data.y[i][0]);
  6367. // this.ctx.closePath();
  6368. // this.ctx.lineWidth = this.config.Global.boxwidth;
  6369. // this.ctx.stroke();
  6370. // this.ctx.closePath();
  6371. } else {
  6372. this.ctx.strokeStyle = color[0]; //red
  6373. this.ctx.closePath();
  6374. this.ctx.beginPath();
  6375. if(zero_y>data.y[i][0]){
  6376. var height=zero_y-data.y[i][0];
  6377. }
  6378. else{
  6379. var height=data.y[i][0]-zero_y;
  6380. }
  6381. this.ctx.lineWidth = 1;
  6382. this.ctx.fillStyle = "#0a0a0a";
  6383. this.ctx.fillRect(data.x[i]+0.5-left[this.config.Global.Candle.public.box_pixel],zero_y-height,this.config.Global.boxwidth,height);
  6384. this.ctx.strokeRect(data.x[i]+0.5-left[this.config.Global.Candle.public.box_pixel],zero_y-height,this.config.Global.boxwidth,height);
  6385. this.ctx.closePath();
  6386. // if(zero_y>data.y[i][0])
  6387. // {
  6388. // var height=zero_y-data.y[i][0];
  6389. // this.ctx.strokeRect(data.x[i] + 0.5-this.config.Global.boxwidth,data.y[i][0],this.config.Global.boxwidth,height)
  6390. // this.ctx.closePath();
  6391. // }
  6392. // else{
  6393. // var height=data.y[i][0]-zero_y;
  6394. // this.ctx.lineWidth=5;
  6395. // if(height!=0){
  6396. // this.ctx.strokeRect(data.x[i] + 0.5-this.config.Global.boxwidth,data.y[i][0],this.config.Global.boxwidth,height);
  6397. // this.ctx.closePath();
  6398. // }
  6399. //
  6400. // }
  6401. // this.ctx.closePath();
  6402. }
  6403. // this.ctx.beginPath();
  6404. // this.ctx.moveTo(data.x[i] + 0.5, zero_y);
  6405. // this.ctx.lineTo(data.x[i] + 0.5, data.y[i][0]);
  6406. // this.ctx.closePath();
  6407. // this.ctx.lineWidth = this.config.Global.boxwidth;
  6408. // this.ctx.stroke();
  6409. // this.ctx.closePath();
  6410. }
  6411. this.ctx.beginPath();
  6412. this.ctx.moveTo(data.x[data.y.length - 1] + 0.5, zero_y);
  6413. this.ctx.lineTo(data.x[data.y.length - 1] + 0.5, data.y[data.y.length - 1][0]);
  6414. this.ctx.closePath();
  6415. //this.ctx.lineWidth = this.config.Global.boxwidth;
  6416. this.ctx.stroke();
  6417. }
  6418. function Plotvolumes2(view, grid, name) {
  6419. sup(this, view, grid, name);
  6420. }
  6421. ClassExtend(Plotvolumes2, Plot);
  6422. Plotvolumes2.prototype.draw = function(data) {
  6423. //建立点
  6424. var color;
  6425. if (this.param.color) {
  6426. color = this.param.color;
  6427. } else {
  6428. color = this.conf.lineColor;
  6429. }
  6430. var zero_y = this.axis.getY(0);
  6431. for (var i = 0; i < data.x.length; i++) {
  6432. if (isNaN(data.y[i][0])) continue;
  6433. this.ctx.beginPath();
  6434. this.ctx.moveTo(data.x[i] + 0.5, zero_y);
  6435. if (data.y[i][0] > zero_y) {
  6436. this.ctx.strokeStyle = color[1];
  6437. this.ctx.lineTo(data.x[i] + 0.5, 2 * zero_y - data.y[i][0]);
  6438. } else {
  6439. this.ctx.strokeStyle = color[0];
  6440. this.ctx.lineTo(data.x[i] + 0.5, data.y[i][0]);
  6441. }
  6442. this.ctx.closePath();
  6443. this.ctx.stroke();
  6444. }
  6445. }
  6446. function PlotWave(view, grid, name) {
  6447. sup(this, view, grid, name);
  6448. }
  6449. ClassExtend(PlotWave, Plot);
  6450. PlotWave.prototype.draw = function(data) {
  6451. //建立点
  6452. var color;
  6453. if (this.param.color) {
  6454. color = this.param.color;
  6455. } else {
  6456. color = this.conf.lineColor;
  6457. }
  6458. var y1 = []
  6459. for (var i = 0; i < data.y.length; i++) {
  6460. y1[i] = data.y[i][0];
  6461. }
  6462. drawLine(this.ctx, data.x, y1, color[0]);
  6463. }
  6464. function Plotwdensity(view, grid, name) {
  6465. sup(this, view, grid, name);
  6466. }
  6467. ClassExtend(Plotwdensity, Plot);
  6468. Plotwdensity.prototype.draw = function(data) {
  6469. //建立点
  6470. var color;
  6471. if (this.param.lineColor) {
  6472. color = this.param.lineColor;
  6473. } else {
  6474. color = this.conf.lineColor;
  6475. }
  6476. for (var i = 0; i < data.y.length; i++) {
  6477. for (var j = 0; j < data.y[i].length / 2; j++) {
  6478. if (data.y[i][2 * j] != 0 && data.y[i][j * 2 + 1] != 0) {
  6479. writeText(this.ctx, new Point(data.x[i], data.y[i][2 * j]), "~", color[j], this.param.font)
  6480. }
  6481. }
  6482. }
  6483. }
  6484. //Node 版本的数据接收
  6485. //这里主要针对本地传送数据。[直接一次性加载的策略]
  6486. function ModelNode(controller) {
  6487. sup(this, controller);
  6488. this.host = this.config.Global.NodeHost;
  6489. this.port = this.config.Global.NodePort;
  6490. this.isinit = false;
  6491. }
  6492. ClassExtend(ModelNode, Model);
  6493. ModelNode.prototype.initData = function() {
  6494. if (this.isinit) return;
  6495. this.isinit = true;
  6496. var socket = io.connect('http://' + document.domain);
  6497. this.socket = socket;
  6498. var _this = this;
  6499. socket.on("error", function(data) {
  6500. // console.log("error");
  6501. });
  6502. socket.on("init", function(data) {
  6503. // console.log("init");
  6504. _this.updateData(data, "init");
  6505. });
  6506. socket.on("data", function(data) {
  6507. if (data.main && data.main.options.prev_calculated == 0) console.log("data");
  6508. _this.updateData(data, "new");
  6509. });
  6510. var _this = this;
  6511. _this.isconnect = false;
  6512. socket.on("connect", function() {
  6513. _this.isconnect = true;
  6514. _this.subscribe();
  6515. });
  6516. this.socket = socket;
  6517. }
  6518. ModelNode.prototype.subscribe = function() {
  6519. if (this.isconnect) {
  6520. this.socket.emit("subscribe", { c: this.controller.c, p: this.controller.p });
  6521. }
  6522. }
  6523. ModelNode.prototype.downloadData = function() {
  6524. }
  6525. ModelNode.prototype.newData = function() {
  6526. }
  6527. ModelNode.prototype.updateData = function(data, action_name) {
  6528. // console.log("data.p:"+data.p);
  6529. if (data && data.c && data.p) {
  6530. if (data.c != this.c || data.p != this.p) {
  6531. //$("#symbol li[name="+data.c+"]").click();
  6532. $("#period li[name=" + data.p + "]").click();
  6533. action_name = "init";
  6534. }
  6535. }
  6536. if (action_name == "init") {
  6537. if (data && data.c && data.p) {
  6538. this.flag(Model.INITED, 1, data.c, data.p);
  6539. } else {
  6540. this.flag(Model.INITED, 1);
  6541. }
  6542. hide_loading();
  6543. } else {
  6544. debug("update");
  6545. }
  6546. this.update(data, Model.UPDATE);
  6547. }
  6548. //采用短连接下载数据的接口,有两个子类,一个子类是poll 采用轮询的方式更新数据。
  6549. //还有一个 WS采用websocket 的方式更新数据,
  6550. //如果在配置中,指定采用poll,那么我们就采用poll
  6551. //如果在配置中 指定采用websokect,但是发现,有些浏览器不支持,我们还是要退回轮询的方式。
  6552. //而服务器端 会有两套服务器。
  6553. //为了便于扩展。我们没有直接重写 data.set 类。
  6554. function ModelShort(controller) {
  6555. sup(this, controller);
  6556. this.controller=controller;
  6557. this.api = this.config.Global.DataAPI;
  6558. this.prevPoint = 0;
  6559. }
  6560. ClassExtend(ModelShort, Model);
  6561. ModelShort.prototype.getAPI = function() {
  6562. console.log($.cookie('symbol'));
  6563. if($.cookie('symbol')=="YCC"){
  6564. return "https://kdata.fxee.com/kdata?datafile=db" + "&c=NYCC&p="+ this.p;
  6565. }
  6566. else{
  6567. return "https://kdata.fxee.com/kdata?datafile=db" + "&c=" + $.cookie('symbol') + "&p=" + this.p;
  6568. }
  6569. // if(this.p==null){
  6570. // return "https://tick.33.cn:4062/kdata?datafile=db" + "&c=" + $.cookie('symbol') + "&p=H1" ;
  6571. // }
  6572. // else{
  6573. // return "https://tick.33.cn:4062/kdata?datafile=db" + "&c=" + $.cookie('symbol') + "&p=" + this.p;
  6574. // }
  6575. // if(this.c=="ETC"){
  6576. // return etcUrl + "&c=" + this.c + "&p=" + this.p;
  6577. // }
  6578. // else{
  6579. // if (this.api.indexOf("?") == -1) {
  6580. // return this.api + "?" + "c=" + this.c + "&p=" + this.p;
  6581. // } else {
  6582. // return this.api + "&c=" + this.c + "&p=" + this.p;
  6583. // }
  6584. // }
  6585. }
  6586. ModelShort.prototype.download = function(action_name) {
  6587. this.count = this.config.Global.downloadCount;
  6588. if (action_name == "down") {
  6589. if (this.flag(Model.DOWN_END)) return;
  6590. //判断左边是否需要下载(左边的优先下载)
  6591. var down_flag = 0;
  6592. if (this.leftDataCount() < this.config.Global.lowMark) {
  6593. if (this.downOptions.total_size) {
  6594. if (this.getLeftOffset() < this.downOptions.total_size - 1) down_flag = 1;
  6595. } else {
  6596. down_flag = 1; //left
  6597. }
  6598. }
  6599. //判断右边是否需要下载。对于以时间下载的模式,不会消去数据。所以,右边的永远不需要下载。
  6600. if (down_flag == 0 && this.rightDataCount() < this.config.Global.lowMark) {
  6601. if (this.downOptions.total_size) {
  6602. if (this.getRightOffset() > 0) down_flag = -1;
  6603. }
  6604. }
  6605. if (!down_flag) return;
  6606. }
  6607. if (this.config[this.config.mainName].downdata == 0) return;
  6608. var api = this.getAPI();
  6609. if (!api) return;
  6610. var _this = this;
  6611. var ind = this.getIndicatorList();
  6612. //用一个数字,来标记这些状态. init_beg 和 init_end
  6613. //是一对,设置了一个,就会清除另外的一个
  6614. if (this.flag(Model.DOWN) == 1) return; //如果数据正在下载中,那么忽略新的下载任务
  6615. if (this.downOptions.total_size) {
  6616. //以位置分页
  6617. if (this.state.length == '' && action_name == 'down') {
  6618. var offset = this.getDownOffset(down_flag);
  6619. if (offset < 0) return;
  6620. } else if (this.state == 'home') {
  6621. offset = this.downOptions.total_size - this.count;
  6622. } else if (this.state == "end") {
  6623. offset = 0;
  6624. }
  6625. if (this.getRightOffset() <= offset && offset <= this.getLeftOffset()) {
  6626. this.state = '';
  6627. return;
  6628. }
  6629. var baseparam = { action: action_name, offset: offset, count: this.count, 'ind': ind.join(":") }
  6630. } else {
  6631. //以时间分页
  6632. var baseparam = { action: action_name, ts: this.startXValue(), count: this.count, 'ind': ind.join(":") }
  6633. }
  6634. var pollmode = this.config.Global.PollMode;
  6635. baseparam.out = pollmode;
  6636. this.flag(Model.DOWN, 1);
  6637. $.ajax({
  6638. type: "post",
  6639. url: api,
  6640. data: baseparam,
  6641. success: function(data) {
  6642. // console.log("ajax data:"+data);
  6643. if (data) {
  6644. _this.processDown(data, data.action);
  6645. }
  6646. },
  6647. error : function() {
  6648. // view("异常!");
  6649. alert("异常!");
  6650. //光标移至输入用户名框
  6651. $("#loginusername").focus();
  6652. return -1;
  6653. },
  6654. complete: function(xhr) {
  6655. _this.flag(Model.DOWN, 0);
  6656. _this.state = '';
  6657. },
  6658. dataType: baseparam.out
  6659. });
  6660. }
  6661. ModelShort.prototype.processDown = function(data, action_name) {
  6662. if (action_name == "init") {
  6663. if (data && data.c && data.p) {
  6664. this.flag(Model.INITED, 1, data.c, data.p);
  6665. } else {
  6666. this.flag(Model.INITED, 1);
  6667. }
  6668. hide_loading();
  6669. } else {
  6670. debug("down ok");
  6671. }
  6672. this.update(data, Model.DOWN);
  6673. this.flag(Model.DOWN_DATA, 1); //标记下载的数据可用了
  6674. if (action_name == "init") {
  6675. //this.newData();
  6676. }
  6677. }
  6678. ModelShort.prototype.initData = function() {
  6679. return this.download("init");
  6680. }
  6681. ModelShort.prototype.downloadData = function() {
  6682. this.download("down");
  6683. }
  6684. //通过广播的方式得到tick数据。在本地计算出K线的数据。(方案1)
  6685. //但是本地计算有些麻烦,比较简单的解决方案是:支持一个new 命令
  6686. //把相关的数据下载下来。并注册广播该数据。这个广播服务器需要复杂一点。
  6687. //暂时采用第二种方案,个人认为这个方案在不需要tick报价的情况下,客户端
  6688. //逻辑最少,数据最不容易出错。
  6689. //
  6690. //tick广播服务器,只要缓存24小时内的数据,一般就不会有出现断层。【如果new
  6691. //命令在的时间是在24小时以外的。可以提醒客户端,刷新。但是不考虑这样的异常。】
  6692. //
  6693. //下载数据:会收集所有注册指标的名称,一起下载。下载的数据,按照主K线图对齐。
  6694. //没有对齐的填上NULL,如果某个点为NULL,那么这个点就直接跳过,不会进行绘制
  6695. //function 继承
  6696. function ModelShortPoll(controller) {
  6697. sup(this, controller);
  6698. this.interval = new IntervalEvent(Math.round(this.config.Global.PollInterval / this.config.Global.Interval), function(controller) {
  6699. if(controller.model==undefined)return;
  6700. controller.model.newData();
  6701. }, true);
  6702. controller.addIntervalEvent("poll", this.interval);
  6703. }
  6704. ClassExtend(ModelShortPoll, ModelShort);
  6705. ModelShortPoll.prototype.newData = function() {
  6706. var api = this.getAPI();
  6707. if (!api) return;
  6708. //如果是静态图形
  6709. if (this.controller.staticChat) return true;
  6710. var _this = this;
  6711. if (this.isNewing) {
  6712. if (getTime() - this.lastSend > 1000 * this.config.Global.maxConnectAliveTime) {
  6713. //reconnect. may be the connect is error
  6714. } else {
  6715. return false;
  6716. }
  6717. }
  6718. //如果没有初始化,那么返回
  6719. if (!this.flag(Model.INITED)) {
  6720. return;
  6721. }
  6722. this.isNewing = true;
  6723. this.lastSend = getTime();
  6724. var ind = this.getIndicatorList();
  6725. //更新时间按照主图:的最新数据
  6726. var first = this.flag(Model.FIRST_NEW) ? 1 : 0;
  6727. this.c = this.c;
  6728. console.log(this);
  6729. var baseparam = { action: 'new', "ind": ind.join(":"), te: this.endXValue(), first: first, __tmp: Math.random() };
  6730. var pollmode = this.config.Global.PollMode;
  6731. baseparam.out = pollmode;
  6732. this.newDataXHR = $.ajax({
  6733. type: "post",
  6734. url: api,
  6735. data: baseparam,
  6736. success: function(data) {
  6737. _this.processNew(data);
  6738. _this.isNewing = false;
  6739. },
  6740. complete: function(xhr) {
  6741. _this.isNewing = false;
  6742. },
  6743. dataType: baseparam.out
  6744. });
  6745. return true;
  6746. }
  6747. ModelShortPoll.prototype.processNew = function(data) {
  6748. if (data != null) {
  6749. this.update(data, Model.NEW);
  6750. this.flag(Model.FIRST_NEW, 0, data.c, data.p);
  6751. }
  6752. }
  6753. //通过广播的方式得到tick数据。在本地计算出K线的数据。(方案1)
  6754. //但是本地计算有些麻烦,比较简单的解决方案是:支持一个new 命令
  6755. //把相关的数据下载下来。并注册广播该数据。这个广播服务器需要复杂一点。
  6756. //暂时采用第二种方案,个人认为这个方案在不需要tick报价的情况下,客户端
  6757. //逻辑最少,数据最不容易出错。
  6758. //
  6759. //tick广播服务器,只要缓存24小时内的数据,一般就不会有出现断层。【如果new
  6760. //命令在的时间是在24小时以外的。可以提醒客户端,刷新。但是不考虑这样的异常。】
  6761. //
  6762. //下载数据:会收集所有注册指标的名称,一起下载。下载的数据,按照主K线图对齐。
  6763. //没有对齐的填上NULL,如果某个点为NULL,那么这个点就直接跳过,不会进行绘制
  6764. //function 继承
  6765. //这个是通过 websocket 广播进行数据更新的模式。数据下载部分不变,只是更新了数据更新的部分。
  6766. function ModelShortWS(controller) {
  6767. sup(this, controller);
  6768. this.wsinit = false;
  6769. if (!this.config.Global.WSHost) {
  6770. return;
  6771. }
  6772. this.url = "ws://" + this.config.Global.WSHost + ":" + this.config.Global.WSPort + "/";
  6773. this.interval = new IntervalEvent(Math.round(1000 / this.config.Global.Interval), function(controller) {
  6774. var model = controller.model;
  6775. if (getTime() - model.lastRead > model.config.Global.maxNOData * 1000) {
  6776. model.lastRead = getTime();
  6777. if (model.wsinit) {
  6778. if (model.ws) {
  6779. model.ws.close();
  6780. }
  6781. model.ws = null;
  6782. model.wsinit = false;
  6783. model.newData();
  6784. } else {
  6785. model.ws = null;
  6786. model.wsinit = false;
  6787. model.newData();
  6788. }
  6789. return;
  6790. }
  6791. if (getTime() - model.lastRead > model.config.Global.pingTime * 1000) {
  6792. if (model.ws) {
  6793. try {
  6794. model.ws.send("ping");
  6795. } catch (e) {}
  6796. }
  6797. }
  6798. }, true);
  6799. if (!this.config.Global.newDisable) {
  6800. controller.addIntervalEvent("ws", this.interval);
  6801. }
  6802. this.ws = null;
  6803. }
  6804. ClassExtend(ModelShortWS, ModelShort);
  6805. ModelShortWS.prototype.initWS = function() {
  6806. var _this = this;
  6807. if (this.ws) return;
  6808. if (this.url) {
  6809. this.ws = new WebSocket(this.url);
  6810. this.ws.onopen = function() {
  6811. _this.open();
  6812. };
  6813. this.ws.onmessage = function(e) {
  6814. _this.message(e);
  6815. };
  6816. this.ws.onclose = function(e) {
  6817. _this.message(e);
  6818. };
  6819. }
  6820. }
  6821. ModelShortWS.prototype.newData = function() {
  6822. //如果是静态图形
  6823. if (this.controller.staticChat || this.config.Global.newDisable) return true;
  6824. if (!this.flag(Model.INITED)) {
  6825. return;
  6826. }
  6827. //货币对+指标列表
  6828. var ind = this.getIndicatorList();
  6829. this.cmd = [];
  6830. var hasmain = false;
  6831. var super_ind = [];
  6832. for (var i = 0; i < ind.length; i++) {
  6833. if (ind[i] == this.config.mainName) {
  6834. hasmain = true;
  6835. break;
  6836. }
  6837. }
  6838. if (!hasmain) ind.push(this.config.mainName);
  6839. for (var i = 0; i < ind.length; i++) {
  6840. var mycmd = this.dataObj[ind[i]].reader.getWSCmd();
  6841. if (mycmd) {
  6842. this.cmd.push(mycmd);
  6843. } else {
  6844. super_ind.push(ind[i]);
  6845. }
  6846. }
  6847. if (super_ind.length != 0) {
  6848. super_ind = super_ind.join(',');
  6849. this.cmd.push("super_sub:" + this.c + "_" + this.p + ";" + super_ind + ":" + this.endXValue());
  6850. }
  6851. this.initWS();
  6852. if (this.wsinit) {
  6853. this.sendcmd();
  6854. this.cmd = null;
  6855. }
  6856. }
  6857. ModelShortWS.prototype.sendcmd = function() {
  6858. if (this.cmd) {
  6859. try {
  6860. for (var i = 0; i < this.cmd.length; i++) {
  6861. this.ws.send(this.cmd[i]);
  6862. }
  6863. } catch (e) {}
  6864. }
  6865. }
  6866. ModelShortWS.prototype.open = function() {
  6867. this.wsinit = true;
  6868. this.sendcmd();
  6869. }
  6870. ModelShortWS.prototype.message = function(e) {
  6871. this.lastRead = getTime();
  6872. if (e.data == "here") {
  6873. return;
  6874. }
  6875. var data = eval("(" + e.data + ")");
  6876. this.update(data, Model.NEW);
  6877. }
  6878. ModelShortWS.prototype.close = function(e) {
  6879. this.ws = null;
  6880. this.wsinit = false;
  6881. this.initWS();
  6882. }
  6883. //一般任务reader是一个很简单的东西,但是它实际上也不是非常简单,它涉及预处理。定位等。
  6884. //现在我们考虑一般的情况,那就是main 图 和 这个指标图并不是时间对齐的。
  6885. //我们需要通过time查找。这里,我们采用二分查找。
  6886. //
  6887. //基本的reader会提供两个函数,一个是通过一个start值和number 读取数据
  6888. //一个是通过一个时间范围。读取这个时间范围内的数据。
  6889. //
  6890. //通过精心的组织代码,我们发现这个代码还是可以控制的。虽然,你很难想像用Javascript
  6891. //写这样大型的绘图程序到底能否成功。
  6892. //
  6893. function DataReader(model, writer, name) {
  6894. //每个datreader 对象建立的时候。有一个data write 对象
  6895. this.model = model;
  6896. this.controller = this.model.controller;
  6897. /*if (name!="volumes"){
  6898. this.setParam(this.controller.ind[name].param);
  6899. }*/
  6900. this.writer = writer;
  6901. this.name = name;
  6902. this.config = Config.getInstance();
  6903. this.shift = 0;
  6904. }
  6905. DataReader.EXTEND = 1;
  6906. DataReader.MAIN = 1 << 1;
  6907. DataReader.prototype.setWriter = function(writer) {
  6908. this.writer = writer;
  6909. }
  6910. DataReader.prototype.setParam = function(param) {
  6911. this.param = param;
  6912. }
  6913. DataReader.prototype.getShift = function() {
  6914. //为了计算精确, 从图表中多读取这样多的数据。同时,兼容K线这一端对齐的 和 非对齐的情况,这样,指标的计算只和图表数据相关 和原始数据无关。
  6915. //为了不影响画图,最好不要影响画图
  6916. //时间刻度一般以主图为准。
  6917. return this.shift;
  6918. }
  6919. DataReader.prototype.getStart = function(number) {
  6920. //数据指针
  6921. var start = this.model.point();
  6922. var endpos = this.getEndPos();
  6923. if (endpos < 0) {
  6924. return -1;
  6925. }
  6926. //alert(start);
  6927. if (start < 0) {
  6928. start = 0;
  6929. }
  6930. if (start > endpos) {
  6931. start = endpos;
  6932. }
  6933. if (!number) return start;
  6934. if (endpos - start < number) {
  6935. start = endpos - number + 1;
  6936. }
  6937. if (start < 0) {
  6938. start = 0;
  6939. }
  6940. if (start > endpos) {
  6941. start = endpos - number + 1;
  6942. }
  6943. //修正
  6944. this.model.point(start);
  6945. return start;
  6946. }
  6947. DataReader.prototype.getEndPos = function() {
  6948. var x = this.main.getX(this.c, this.p);
  6949. return x.length - 1;
  6950. }
  6951. DataReader.prototype.startXValue = function() {
  6952. var x = this.main.getX(this.c, this.p);
  6953. return x[x.length - 1];
  6954. }
  6955. DataReader.prototype.endXValue = function() {
  6956. var x = this.main.getX(this.c, this.p);
  6957. return x[0];
  6958. }
  6959. DataReader.prototype.set = function() {
  6960. this.c = this.model.c;
  6961. // console.log("this.model.p:"+this.model.p);
  6962. this.p = this.model.p;
  6963. this.xunit = this.config.Global.xunit[this.p] * 60; //这个是根据时间决定其单位
  6964. if (this.config[this.name] && this.config[this.name].yunit) {
  6965. this.yunit = this.config[this.name].yunit;
  6966. } else {
  6967. this.yunit = this.config.get("Global.yunit." + this.c, this.config.Global.yunit.default_value); //这个是根据货币对决定其单位
  6968. }
  6969. if (this.writer) {
  6970. this.store = this.writer.getStore(this.c, this.p);
  6971. }
  6972. this.config = Config.getInstance();
  6973. // this.config.mainName="main";
  6974. this.main = this.model.dataObj[this.config.mainName].writer; //这个对main是引用关系,所以只要c,p 没有切换
  6975. this.mainData = this.model.data[this.config.mainName]; //main刚刚读取的数据
  6976. this.step = this.xunit;
  6977. this.maxstep = this.config.Global.maxstep; //(5个小时没有数据,那么不进行补充)
  6978. //这个数据,依然是引用了main的最新的数据。
  6979. }
  6980. DataReader.prototype.getMainData = function() {
  6981. this.mainData = this.model.data[this.config.mainName];
  6982. return this.mainData;
  6983. }
  6984. DataReader.prototype.getYminmax = function(y) {
  6985. return minmax(y);
  6986. }
  6987. DataReader.prototype.getWSCmd = function() {
  6988. return false;
  6989. }
  6990. //抽象函数,不提供任何的功能。//主图数据
  6991. DataReader.prototype.getDataByMain = function(readconfig) {
  6992. this.mainData = this.getMainData();
  6993. var nLen = this.mainData.x.length;
  6994. if (nLen > this.model.plotnum) {
  6995. nLen = this.model.plotnum
  6996. }
  6997. var start = this.mainData.x[nLen - 1];
  6998. var end = this.mainData.x[0];
  6999. var x = new Array();
  7000. var y = new Array();
  7001. var xdata = this.writer.getX(this.c, this.p);
  7002. var ydata = this.writer.getY(this.c, this.p);
  7003. //这个部分是数据,首先查找xdata,当然还要判断是否扩展。
  7004. //这里的扩展方式是扩展K线图。其他的扩展,在其他的图里面表示。
  7005. //先获取数据:
  7006. var count = 0;
  7007. var index = find_first_big_r(xdata, end); //查找到第一个点
  7008. if (index == -1) {
  7009. index = 0;
  7010. }
  7011. if (xdata[index] > end) index++; //去掉第一个大于的点
  7012. for (var i = index; i < xdata.length; i++) {
  7013. if (xdata[i] >= start) {
  7014. x[count] = xdata[i];
  7015. y[count] = ydata[i];
  7016. count++;
  7017. } else {
  7018. break;
  7019. }
  7020. }
  7021. if (readconfig & DataReader.EXTEND) {
  7022. //多添加一个最后时间的数据,这个数据如果不存在,那么就复制前一个数据的 open 值,这个时间值肯定小于 start
  7023. if (xdata[i]) {
  7024. x.push(xdata[i]);
  7025. y.push(ydata[i]);
  7026. } else if (x[x.length - 1] > start) {
  7027. x.push(start);
  7028. var ylast = y[y.length - 1][Data.OPEN];
  7029. y.push([ylast, ylast, ylast, ylast, y[y.length - 1][Data.VOLUMES]]);
  7030. }
  7031. return this.extendByMain(x, y);
  7032. }
  7033. //深度拷贝
  7034. y = array_copy(y);
  7035. // }
  7036. return { x: x, y: y };
  7037. }
  7038. DataReader.prototype._formatData = function(x, y) {
  7039. var data = {};
  7040. data.x = x;
  7041. data.y = y;
  7042. data.xunit = this.xunit;
  7043. data.yunit = this.yunit;
  7044. data.maxX = x[0];
  7045. data.minX = x[x.length - 1];
  7046. data.maxIndex=0;
  7047. data.minIndex=0;
  7048. var _minmax = this.getYminmax(y);
  7049. data.maxY = _minmax[1];
  7050. data.minY = _minmax[0];
  7051. data.maxIndex=_minmax[3];
  7052. data.minIndex=_minmax[2];
  7053. return data;
  7054. }
  7055. DataReader.prototype.formatData = function(x, y) {
  7056. return this._formatData(x, y);
  7057. }
  7058. DataReader.prototype.last = function(index) {
  7059. if (!index || index < 0) index = 0;
  7060. var y = this.writer.getY(this.c, this.p);
  7061. return y[index];
  7062. }
  7063. function DataWriter(model, name) {
  7064. this.model = model;
  7065. this.name = name;
  7066. this.config = this.model.config;
  7067. this.storeSet = {};
  7068. }
  7069. DataWriter.prototype.getStore = function(c, p) {
  7070. this.storeSet = init_obj(this.storeSet, c, p, { x: [], y: [] });
  7071. return this.storeSet[c][p];
  7072. }
  7073. DataWriter.prototype.clear = function() {
  7074. this.storeSet = {};
  7075. }
  7076. DataWriter.prototype.setNewData = function(c, p, data) {
  7077. //do nothing.
  7078. }
  7079. DataWriter.prototype.setDownloadData = function(c, p, data) {
  7080. //do nothing.
  7081. }
  7082. DataWriter.prototype.getX = function(c, p) {
  7083. var store = this.getStore(c, p);
  7084. return store.x;
  7085. }
  7086. DataWriter.prototype.getY = function(c, p) {
  7087. var store = this.getStore(c, p);
  7088. return store.y;
  7089. }
  7090. function DataWriterbdensity(model, name) {
  7091. sup(this, model, name);
  7092. }
  7093. ClassExtend(DataWriterbdensity, DataWriter);
  7094. DataWriterbdensity.prototype.setNewData = function(c, p, data) {
  7095. if (!is_array(data) || data.length == 0) {
  7096. return;
  7097. }
  7098. var store = this.getStore(c, p);
  7099. }
  7100. DataWriterbdensity.prototype.notify = function(items) {
  7101. if (items && items.length) {
  7102. /*var typename = DataWriterProfit.nameMap[items[items.length - 1][0]];
  7103. typename = typename.replace("/", "_").toLowerCase();
  7104. var url = $("#music_list select[name="+typename+"]").val();
  7105. playmusic(url);
  7106. */
  7107. }
  7108. }
  7109. DataWriterbdensity.prototype.parseItem = function(items) {
  7110. var newarr = [];
  7111. var type = null;
  7112. for (var i = 0; i < items.length; i++) {
  7113. var item = items[i];
  7114. if (item[0] == "buy" && item[1] == "open") {
  7115. type = DataWriterProfit.BUY_OPEN;
  7116. } else if (item[0] == "buy" && item[1] == "close") {
  7117. type = DataWriterProfit.BUY_CLOSE;
  7118. } else if (item[0] == "sell" && item[1] == "open") {
  7119. type = DataWriterProfit.SELL_OPEN;
  7120. } else if (item[0] == "sell" && item[1] == "close") {
  7121. type = DataWriterProfit.SELL_CLOSE;
  7122. }
  7123. if (type) {
  7124. newarr[i] = [type, parseFloat(item[2]), item[3]];
  7125. }
  7126. }
  7127. if (newarr.length == 0) {
  7128. return false;
  7129. }
  7130. newarr = this.formatItem(newarr);
  7131. return newarr;
  7132. }
  7133. DataWriterbdensity.prototype.formatItem = function(arr) {
  7134. for (var i = 0; i < arr.length; i++) {}
  7135. return arr;
  7136. }
  7137. DataWriterbdensity.prototype.setDownloadData = function(c, p, data) {
  7138. //数据按照时间倒序序进行排列
  7139. var beg, end;
  7140. //处理指标
  7141. if (!is_array(data.x)) {
  7142. return;
  7143. }
  7144. var store = this.getStore(c, p);
  7145. var item;
  7146. for (var i = 0; i < data.x.length; i++) {
  7147. //format time
  7148. var time = formatTime(data.x[i], p);
  7149. store.x.push(time);
  7150. item = data.y[i]; //this.parseItem(data[i][1]);
  7151. if (item) store.y.push(item);
  7152. }
  7153. }
  7154. function DataWriterCandle(model, name) {
  7155. sup(this, model, name);
  7156. this.chunks = []; //数据在服务器端的[开始,结束,total,在本地数组中的,开始位置,长度,方便删除]
  7157. }
  7158. ClassExtend(DataWriterCandle, DataWriter);
  7159. //重写父类.
  7160. //写类不能像读类一样,直接读取model.c 个 model.p
  7161. //因为,数据属于什么类,由服务器端返回的值决定
  7162. //
  7163. DataWriterCandle.prototype.getStore = function(c, p) {
  7164. this.storeSet = init_obj(this.storeSet, c, p, { time: [], ohlc: [], v: [] });
  7165. return this.storeSet[c][p];
  7166. }
  7167. DataWriterCandle.prototype.setDownloadDataByOffset = function(c, p, data, options) {
  7168. //数据按照时间倒序序进行排列
  7169. var beg, end;
  7170. //处理指标
  7171. if (!is_array(data.x)) {
  7172. return;
  7173. }
  7174. this.c = c;
  7175. this.p = p;
  7176. var store = this.getStore(c, p);
  7177. data.x = data.x.reverse();
  7178. data.y = data.y.reverse();
  7179. //判断offset 是否衔接,如果不衔接,那么重置所有的数据。
  7180. //如果衔接。要判断一下左衔接 还是 右衔接。
  7181. //如果是左衔接,并且缓存数目超过一个配置的值,那么删除一部分数据
  7182. //每个数据用一个chunks来表示
  7183. options.astart = 0;
  7184. options.alen = data.x.length;
  7185. if (this.chunks.length && options.end + 1 == this.chunks[0].start) { //右衔接[在头部加入数据]
  7186. var len = data.x.length;
  7187. store.time = data.x.concat(store.time);
  7188. store.ohlc = data.y.concat(store.ohlc);
  7189. this.shiftLeftChunk(store, options); //把chunk往左移
  7190. } else if (this.chunks.length && this.chunks[this.chunks.length - 1].end + 1 == options.start) { //左衔接
  7191. var len = data.x.length;
  7192. store.time = store.time.concat(data.x);
  7193. store.ohlc = store.ohlc.concat(data.y);
  7194. this.shiftRightChunk(store, options);
  7195. } else { //不衔接
  7196. store.time = data.x;
  7197. store.ohlc = data.y;
  7198. this.chunks = [];
  7199. this.chunks[0] = options;
  7200. }
  7201. //更新数据offset 的范围
  7202. this.model.leftoffset = this.chunks[this.chunks.length - 1].end;
  7203. this.model.rightoffset = this.chunks[0].start;
  7204. }
  7205. DataWriterCandle.prototype.shiftLeftChunk = function(store, options) {
  7206. //update chunk data
  7207. for (var i = 0; i < this.chunks.length; i++) {
  7208. this.chunks[i].astart += options.alen;
  7209. }
  7210. this.chunks.unshift(options);
  7211. //更新数据指针,头部数据被加入
  7212. this.model.point(this.model.point() + options.alen);
  7213. if (store.time.length > this.config.Global.maxStoreChunk * this.config.Global.downloadCount) {
  7214. var chunk = this.chunks.pop();
  7215. store.time.splice(chunk.astart);
  7216. store.ohlc.splice(chunk.astart);
  7217. }
  7218. }
  7219. DataWriterCandle.prototype.shiftRightChunk = function(store, options) {
  7220. //处理chunk
  7221. var lastchunk = this.chunks[this.chunks.length - 1];
  7222. options.astart += lastchunk.astart + lastchunk.alen;
  7223. this.chunks.push(options);
  7224. if (store.time.length > this.config.Global.maxStoreChunk * this.config.Global.downloadCount) {
  7225. var chunk = this.chunks.shift();
  7226. for (var i = 0; i < this.chunks.length; i++) {
  7227. this.chunks[i].astart -= chunk.alen;
  7228. }
  7229. //头部数据被删除
  7230. store.time.splice(0, chunk.alen);
  7231. store.ohlc.splice(0, chunk.alen);
  7232. //更新数据指针
  7233. var point = this.model.point();
  7234. point -= chunk.alen;
  7235. this.model.point(point);
  7236. }
  7237. }
  7238. DataWriterCandle.prototype.setUpdateData = function(c, p, data) {
  7239. //更新第一个数据
  7240. if (!is_array(data.x) || data.x.length == 0) {
  7241. return;
  7242. }
  7243. var store = this.getStore(c, p);
  7244. var mintime = data.x[0];
  7245. data.x = data.x.reverse();
  7246. data.y = data.y.reverse();
  7247. if (store.time.length == 0 || parseInt(data.options.prev_calculated) == 0) {
  7248. store.time = data.x;
  7249. store.ohlc = data.y;
  7250. //console.log(store.time);
  7251. return;
  7252. }
  7253. var i = 0;
  7254. while (i < store.time.length && store.time[i] >= mintime) {
  7255. i++;
  7256. }
  7257. if (i == store.time.length) {
  7258. store.time = data.x;
  7259. store.ohlc = data.y;
  7260. } else {
  7261. store.time.splice(0, i);
  7262. store.ohlc.splice(0, i);
  7263. store.time = data.x.concat(store.time);
  7264. store.ohlc = data.y.concat(store.ohlc);
  7265. }
  7266. }
  7267. /*
  7268. DataWriterCandle.prototype.setNewData = function(c, p, data)
  7269. {
  7270. console.log("newdata=",data,is_array(data),data.length);
  7271. //更新第一个数据
  7272. if (!is_array(data) || data.length == 0)
  7273. {
  7274. return;
  7275. }
  7276. data = data.reverse();
  7277. var store = this.getStore(c, p);
  7278. var time = parseInt(data[0][0]);
  7279. while (data.length && time < store.time[0])
  7280. {
  7281. data.shift();
  7282. time = parseInt(data[0][0]);
  7283. }
  7284. if (data.length == 0)
  7285. {
  7286. return;
  7287. }
  7288. //
  7289. for (var i = 1; i < data[0].length; i++)
  7290. {
  7291. data[0][i] = parseFloat(data[0][i]);
  7292. }
  7293. var first = data[0].slice(1);
  7294. if (time == store.time[0])
  7295. {
  7296. store.time[0] = time;
  7297. store.ohlc[0] = first;
  7298. } else {
  7299. store.time.unshift(time);
  7300. store.ohlc.unshift(first);
  7301. }
  7302. if (isNaN(store.ohlc[0][0]))
  7303. {
  7304. alert("update new NaN");
  7305. }
  7306. //store.v[0] = parseFloat(data[0][5]);
  7307. for (var i = 1; i < data.length; i++)
  7308. {
  7309. if (!is_array(data[i]))
  7310. {
  7311. continue;
  7312. }
  7313. for (var j = 1; j < data[i].length; j++)
  7314. {
  7315. data[i][j] = parseFloat(data[i][j]);
  7316. }
  7317. store.time.unshift(parseInt(data[i][0]));
  7318. var newdata = data[i].slice(1);
  7319. store.ohlc.unshift(newdata);
  7320. }
  7321. }*/
  7322. DataWriterCandle.prototype.setNewData = function(c, p, data) {
  7323. //更新第一个数据
  7324. if (!is_array(data.x) || data.x.length == 0) {
  7325. return;
  7326. }
  7327. var store = this.getStore(c, p);
  7328. var time = parseInt(data.x[0]);
  7329. while (data.x.length && time < store.time[0]) {
  7330. data.x.shift();
  7331. data.y.shift();
  7332. time = parseInt(data.x[0]);
  7333. }
  7334. if (data.x.length == 0) {
  7335. return;
  7336. }
  7337. var first = data.y[0];
  7338. if (time == store.time[0]) {
  7339. store.time[0] = time;
  7340. store.ohlc[0] = data.y[0]
  7341. } else {
  7342. store.time.unshift(time);
  7343. store.ohlc.unshift(data.y[0]);
  7344. }
  7345. if (isNaN(store.ohlc[0][0])) {
  7346. alert("update new NaN");
  7347. }
  7348. for (var i = 1; i < data.x.length; i++) {
  7349. store.time.unshift(data.x[i]);
  7350. store.ohlc.unshift(data.y[i]);
  7351. }
  7352. }
  7353. DataWriterCandle.prototype.getX = function(c, p) {
  7354. var store = this.getStore(c, p);
  7355. return store.time;
  7356. }
  7357. DataWriterCandle.prototype.getY = function(c, p) {
  7358. var store = this.getStore(c, p);
  7359. return store.ohlc;
  7360. }
  7361. DataWriterCandle.prototype.setDownloadData = function(c, p, data) {
  7362. //数据按照时间倒序序进行排列
  7363. var beg, end;
  7364. //处理指标
  7365. if (!is_array(data)) {
  7366. if (is_array(data.x) && is_array(data.y)) {
  7367. var newdata = [];
  7368. for (var i = data.x.length -1; i >= 0; i--) {
  7369. var item = [];
  7370. item.push(data.x[i]);
  7371. item = item.concat(data.y[i]);
  7372. newdata.push(item);
  7373. }
  7374. data = newdata;
  7375. } else {
  7376. return;
  7377. }
  7378. }
  7379. var store = this.getStore(c, p);
  7380. for (var i = 0; i < data.length; i++) {
  7381. if (!is_array(data[i])) {
  7382. continue;
  7383. }
  7384. for (var j = 1; j < data[i].length; j++) {
  7385. data[i][j] = parseFloat(data[i][j]);
  7386. }
  7387. store.time.push(parseInt(data[i][0]));
  7388. store.ohlc.push(data[i].slice(1));
  7389. }
  7390. }
  7391. function DataWriterFractals(model, name) {
  7392. sup(this, model, name);
  7393. }
  7394. ClassExtend(DataWriterFractals, DataWriter);
  7395. DataWriterFractals.prototype.setNewData = function(c, p, data) {
  7396. if (!is_array(data) || data.length == 0) {
  7397. return;
  7398. }
  7399. //data = data.reverse();
  7400. var store = this.getStore(c, p);
  7401. /*
  7402. for (var i = 0; i < data.length; i++)
  7403. {
  7404. if (!is_array(data[i]))
  7405. {
  7406. continue;
  7407. }
  7408. var item = this.parseItem(data[i][1]);
  7409. var newitem;
  7410. if (item) {} else {continue;}
  7411. var time = formatTime(data[i][0], p);
  7412. if (store.x[0] == time) {
  7413. //可能会有新的买卖点
  7414. newitem = array_diff(item, store.y[0]);
  7415. store.y[0] = item;
  7416. } else {
  7417. store.x.unshift(time);
  7418. store.y.unshift(item);
  7419. newitem = item;
  7420. }
  7421. this.notify(newitem);
  7422. }
  7423. */
  7424. }
  7425. DataWriterFractals.prototype.notify = function(items) {
  7426. if (items && items.length) {
  7427. /*var typename = DataWriterProfit.nameMap[items[items.length - 1][0]];
  7428. typename = typename.replace("/", "_").toLowerCase();
  7429. var url = $("#music_list select[name="+typename+"]").val();
  7430. playmusic(url);
  7431. */
  7432. }
  7433. }
  7434. DataWriterFractals.prototype.parseItem = function(items) {
  7435. var newarr = [];
  7436. var type = null;
  7437. for (var i = 0; i < items.length; i++) {
  7438. var item = items[i];
  7439. if (item[0] == "buy" && item[1] == "open") {
  7440. type = DataWriterProfit.BUY_OPEN;
  7441. } else if (item[0] == "buy" && item[1] == "close") {
  7442. type = DataWriterProfit.BUY_CLOSE;
  7443. } else if (item[0] == "sell" && item[1] == "open") {
  7444. type = DataWriterProfit.SELL_OPEN;
  7445. } else if (item[0] == "sell" && item[1] == "close") {
  7446. type = DataWriterProfit.SELL_CLOSE;
  7447. }
  7448. if (type) {
  7449. newarr[i] = [type, parseFloat(item[2]), item[3]];
  7450. }
  7451. }
  7452. if (newarr.length == 0) {
  7453. return false;
  7454. }
  7455. newarr = this.formatItem(newarr);
  7456. return newarr;
  7457. }
  7458. DataWriterFractals.prototype.formatItem = function(arr) {
  7459. for (var i = 0; i < arr.length; i++) {}
  7460. return arr;
  7461. }
  7462. DataWriterFractals.prototype.setDownloadData = function(c, p, data) {
  7463. //数据按照时间倒序序进行排列
  7464. var beg, end;
  7465. //处理指标
  7466. if (!is_array(data.x)) {
  7467. return;
  7468. }
  7469. var store = this.getStore(c, p);
  7470. var item;
  7471. for (var i = 0; i < data.x.length; i++) {
  7472. //format time
  7473. var time = formatTime(data.x[i], p);
  7474. store.x.push(time);
  7475. item = data.y[i]; //this.parseItem(data[i][1]);
  7476. if (item) store.y.push(item);
  7477. }
  7478. }
  7479. function DataWriterKshape(model, name) {
  7480. sup(this, model, name);
  7481. }
  7482. ClassExtend(DataWriterKshape, DataWriter);
  7483. DataWriterKshape.prototype.setNewData = function(c, p, data) {
  7484. if (!is_array(data) || data.length == 0) {
  7485. return;
  7486. }
  7487. //data = data.reverse();
  7488. var store = this.getStore(c, p);
  7489. /*
  7490. for (var i = 0; i < data.length; i++)
  7491. {
  7492. if (!is_array(data[i]))
  7493. {
  7494. continue;
  7495. }
  7496. var item = this.parseItem(data[i][1]);
  7497. var newitem;
  7498. if (item) {} else {continue;}
  7499. var time = formatTime(data[i][0], p);
  7500. if (store.x[0] == time) {
  7501. //可能会有新的买卖点
  7502. newitem = array_diff(item, store.y[0]);
  7503. store.y[0] = item;
  7504. } else {
  7505. store.x.unshift(time);
  7506. store.y.unshift(item);
  7507. newitem = item;
  7508. }
  7509. this.notify(newitem);
  7510. }
  7511. */
  7512. }
  7513. DataWriterKshape.prototype.notify = function(items) {
  7514. if (items && items.length) {
  7515. /*var typename = DataWriterProfit.nameMap[items[items.length - 1][0]];
  7516. typename = typename.replace("/", "_").toLowerCase();
  7517. var url = $("#music_list select[name="+typename+"]").val();
  7518. playmusic(url);
  7519. */
  7520. }
  7521. }
  7522. DataWriterKshape.prototype.parseItem = function(items) {
  7523. var newarr = [];
  7524. var type = null;
  7525. for (var i = 0; i < items.length; i++) {
  7526. var item = items[i];
  7527. if (item[0] == "buy" && item[1] == "open") {
  7528. type = DataWriterProfit.BUY_OPEN;
  7529. } else if (item[0] == "buy" && item[1] == "close") {
  7530. type = DataWriterProfit.BUY_CLOSE;
  7531. } else if (item[0] == "sell" && item[1] == "open") {
  7532. type = DataWriterProfit.SELL_OPEN;
  7533. } else if (item[0] == "sell" && item[1] == "close") {
  7534. type = DataWriterProfit.SELL_CLOSE;
  7535. }
  7536. if (type) {
  7537. newarr[i] = [type, parseFloat(item[2]), item[3]];
  7538. }
  7539. }
  7540. if (newarr.length == 0) {
  7541. return false;
  7542. }
  7543. newarr = this.formatItem(newarr);
  7544. return newarr;
  7545. }
  7546. DataWriterKshape.prototype.formatItem = function(arr) {
  7547. for (var i = 0; i < arr.length; i++) {}
  7548. return arr;
  7549. }
  7550. DataWriterKshape.prototype.setDownloadData = function(c, p, data) {
  7551. //数据按照时间倒序序进行排列
  7552. var beg, end;
  7553. //处理指标
  7554. if (!is_array(data.x)) {
  7555. return;
  7556. }
  7557. var store = this.getStore(c, p);
  7558. var item;
  7559. for (var i = 0; i < data.x.length; i++) {
  7560. //format time
  7561. var time = formatTime(data.x[i], p);
  7562. store.x.push(time);
  7563. item = data.y[i]; //this.parseItem(data[i][1]);
  7564. if (item) store.y.push(item);
  7565. }
  7566. }
  7567. function DataWriterMath(model, name) {
  7568. sup(this, model, name);
  7569. }
  7570. ClassExtend(DataWriterMath, DataWriter);
  7571. function DataWriterProfit(model, name) {
  7572. sup(this, model, name);
  7573. }
  7574. ClassExtend(DataWriterProfit, DataWriter);
  7575. DataWriterProfit.BUY_OPEN = 1;
  7576. DataWriterProfit.BUY_CLOSE = 2;
  7577. DataWriterProfit.SELL_OPEN = 3;
  7578. DataWriterProfit.SELL_CLOSE = 4;
  7579. DataWriterProfit.nameMap = {
  7580. 1: "Open/Buy",
  7581. 2: "Close/Buy",
  7582. 3: "Open/Sell",
  7583. 4: "Close/Sell"
  7584. };
  7585. DataWriterProfit.prototype.setNewData = function(c, p, data) {
  7586. if (!is_array(data) || data.length == 0) {
  7587. return;
  7588. }
  7589. data = data.reverse();
  7590. var store = this.getStore(c, p);
  7591. for (var i = 0; i < data.length; i++) {
  7592. if (!is_array(data[i])) {
  7593. continue;
  7594. }
  7595. var item = this.parseItem(data[i][1]);
  7596. var newitem;
  7597. if (item) {} else {
  7598. continue;
  7599. }
  7600. var time = formatTime(data[i][0], p);
  7601. if (store.x[0] == time) {
  7602. //可能会有新的买卖点
  7603. newitem = array_diff(item, store.y[0]);
  7604. store.y[0] = item;
  7605. } else {
  7606. store.x.unshift(time);
  7607. store.y.unshift(item);
  7608. newitem = item;
  7609. }
  7610. this.notify(newitem);
  7611. }
  7612. }
  7613. DataWriterProfit.prototype.notify = function(items) {
  7614. if (items && items.length) {
  7615. var typename = DataWriterProfit.nameMap[items[items.length - 1][0]];
  7616. typename = typename.replace("/", "_").toLowerCase();
  7617. var url = $("#music_list select[name=" + typename + "]").val();
  7618. // playmusic(url);
  7619. }
  7620. }
  7621. DataWriterProfit.prototype.parseItem = function(items) {
  7622. var newarr = [];
  7623. var type = null;
  7624. for (var i = 0; i < items.length; i++) {
  7625. var item = items[i];
  7626. if (item[0] == "buy" && item[1] == "open") {
  7627. type = DataWriterProfit.BUY_OPEN;
  7628. } else if (item[0] == "buy" && item[1] == "close") {
  7629. type = DataWriterProfit.BUY_CLOSE;
  7630. } else if (item[0] == "sell" && item[1] == "open") {
  7631. type = DataWriterProfit.SELL_OPEN;
  7632. } else if (item[0] == "sell" && item[1] == "close") {
  7633. type = DataWriterProfit.SELL_CLOSE;
  7634. }
  7635. if (type) {
  7636. newarr[i] = [type, parseFloat(item[2]), item[3]];
  7637. }
  7638. }
  7639. if (newarr.length == 0) {
  7640. return false;
  7641. }
  7642. newarr = this.formatItem(newarr);
  7643. return newarr;
  7644. }
  7645. DataWriterProfit.prototype.formatItem = function(arr) {
  7646. for (var i = 0; i < arr.length; i++) {}
  7647. return arr;
  7648. }
  7649. DataWriterProfit.prototype.setDownloadData = function(c, p, data) {
  7650. //数据按照时间倒序序进行排列
  7651. var beg, end;
  7652. //处理指标
  7653. if (!is_array(data)) {
  7654. return;
  7655. }
  7656. var store = this.getStore(c, p);
  7657. var item;
  7658. for (var i = 0; i < data.length; i++) {
  7659. if (!is_array(data[i])) {
  7660. continue;
  7661. }
  7662. //format time
  7663. var time = formatTime(data[i][0], p);
  7664. store.x.push(time);
  7665. item = this.parseItem(data[i][1]);
  7666. if (item) store.y.push(item);
  7667. }
  7668. }
  7669. function DataWriterTickSource(model, name) {
  7670. sup(this, model, name);
  7671. this.lastSource = null;
  7672. }
  7673. ClassExtend(DataWriterTickSource, DataWriter);
  7674. DataWriterTickSource.prototype.setNewData = function(c, type, data) {
  7675. if (!is_array(data) || !is_array(data[0])) return;
  7676. this.lastSource = type;
  7677. var store = this.getStore(c, type);
  7678. for (var i = 0; i < data.length; i++) {
  7679. store.x.push(parseInt(data[i][0]) * 1000 + parseInt(data[i][1]));
  7680. store.y.push([parseFloat(data[i][2]), parseFloat(data[i][3])]);
  7681. }
  7682. if (store.x.length > this.maxdata) {
  7683. store.x = store.x.slice(this.maxdata / 2);
  7684. store.y = store.y.slice(this.maxdata / 2);
  7685. }
  7686. }
  7687. function DataReaderadx(model, writer, name) {
  7688. sup(this, model, writer, name);
  7689. }
  7690. ClassExtend(DataReaderadx, DataReader);
  7691. function DataReaderAjax(model, writer, name) {
  7692. this.isinit = false;
  7693. sup(this, model, writer, name);
  7694. this.data = {};
  7695. this.lastdata = {};
  7696. }
  7697. ClassExtend(DataReaderAjax, DataReader);
  7698. DataReaderAjax.prototype.setParam = function(param) {
  7699. if (this.isinit) return;
  7700. this.isinit = true;
  7701. var url = param[1];
  7702. var _this = this;
  7703. $.get(url, function(data) {
  7704. _this.setAjaxData(data);
  7705. }, "json");
  7706. }
  7707. DataReaderAjax.prototype.setAjaxData = function(data) {
  7708. this.data = data;
  7709. this.model.ready = true;
  7710. this.model.controller.flag("down");
  7711. //this.model.ready = false; //不更新图表了
  7712. this.main = this;
  7713. return this;
  7714. }
  7715. DataReaderAjax.prototype.getX = function() {
  7716. return this.data.x;
  7717. }
  7718. DataReaderAjax.prototype.getY = function() {
  7719. return this.data.y;
  7720. }
  7721. DataReaderAjax.prototype.getData = function(number, readconfig) {
  7722. var start = this.getStart(number);
  7723. this.lastdata = this.data.y[0];
  7724. start = this.getStart(number);
  7725. index = 0;
  7726. var x = [];
  7727. var y = [];
  7728. for (var i = start; i < this.data.x.length; i++) {
  7729. x[index] = this.data.x[i];
  7730. y[index] = this.data.y[i];
  7731. index++;
  7732. if (index >= number) {
  7733. break;
  7734. }
  7735. }
  7736. var data = {};
  7737. data.x = x;
  7738. data.y = array_copy2d(y);
  7739. return data;
  7740. }
  7741. DataReaderAjax.prototype.last = function() {
  7742. return this.lastdata;
  7743. }
  7744. DataReaderAjax.prototype.close = function(index) {
  7745. if (!index || index < 0) index = 0;
  7746. return this.data.y[index][Data.CLOSE];
  7747. }
  7748. DataReaderAjax.prototype.getEndPos = function() {
  7749. var x = this.data.x;
  7750. return x.length - 1;
  7751. }
  7752. DataReaderAjax.prototype.startXValue = function() {
  7753. var x = this.data.x;
  7754. return x[x.length - 1];
  7755. }
  7756. DataReaderAjax.prototype.endXValue = function() {
  7757. var x = this.data.x;
  7758. return x[0];
  7759. }
  7760. //现在,这样处理,一旦指标被注册了,
  7761. //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
  7762. //后面的数据,就会绑定在K线的下载结果里面
  7763. //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
  7764. //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
  7765. //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
  7766. function DataReaderatr(model, writer, name) {
  7767. sup(this, model, writer, name);
  7768. }
  7769. ClassExtend(DataReaderatr, DataReader);
  7770. //���ڣ�����������һ��ָ�걻ע���ˣ�
  7771. //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
  7772. //���������ݣ��ͻ�������K�ߵ����ؽ�������
  7773. //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
  7774. //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
  7775. //Ȼ�����غ�����ָ��,���ؽ����Ժ󣬺ϲ�������������ָ�꣬���󣬳�ʼ��������
  7776. //
  7777. //��ȡ����ͼ������
  7778. //
  7779. function DataReaderbdensity(model, writer, name) {
  7780. sup(this, model, writer, name);
  7781. }
  7782. ClassExtend(DataReaderbdensity, DataReader);
  7783. DataReaderbdensity.prototype.getYminmax = function(y) {
  7784. var ymax = -Infinity;
  7785. var ymin = Infinity;
  7786. var maxIndex=0;
  7787. var minIndex=0;
  7788. if (!y) {
  7789. return [ymin, ymax,minIndex,maxIndex];
  7790. }
  7791. var nIndex = 0;
  7792. for (var i = 0; i < y.length; i++) {
  7793. for (var j = 0; j < y[i].length; j++) {
  7794. nIndex = (j / 4) * 4 + 2
  7795. if (j % 4 <= 1 && y[i][nIndex] != 0) {
  7796. var value = y[i][j];
  7797. if (value > ymax) {
  7798. ymax = value;
  7799. maxIndex=i;
  7800. }
  7801. if (value < ymin) {
  7802. ymin = value;
  7803. minIndex=i;
  7804. }
  7805. }
  7806. }
  7807. }
  7808. console.log("ymin:"+ymin+",ymax:"+ymax);
  7809. return [ymin, ymax,minIndex,maxIndex];
  7810. }
  7811. //现在,这样处理,一旦指标被注册了,
  7812. //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
  7813. //后面的数据,就会绑定在K线的下载结果里面
  7814. //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
  7815. //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
  7816. //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
  7817. function DataReaderBolling(model, writer, name) {
  7818. sup(this, model, writer, name);
  7819. }
  7820. ClassExtend(DataReaderBolling, DataReader);
  7821. //现在,这样处理,一旦指标被注册了,
  7822. //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
  7823. //后面的数据,就会绑定在K线的下载结果里面
  7824. //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
  7825. //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
  7826. //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
  7827. function DataReaderBollingDesity(model, writer, name) {
  7828. sup(this, model, writer, name);
  7829. this.sourcedata = null;
  7830. }
  7831. ClassExtend(DataReaderBollingDesity, DataReader);
  7832. DataReaderBollingDesity.prototype.formatData = function(x, y) {
  7833. var data = {};
  7834. data.x = x;
  7835. data.y = y;
  7836. data.xunit = this.xunit;
  7837. data.yunit = this.yunit;
  7838. data.maxX = x[0];
  7839. data.minX = x[x.length - 1];
  7840. data.maxIndex=0;
  7841. data.minIndex=0;
  7842. var min = Infinity
  7843. var max = -Infinity;
  7844. for (var i = 0; i < y.length; i++) {
  7845. for (var j = 0; j < y.length; j += 2) {
  7846. if (y[i][j] == -1) {
  7847. continue;
  7848. }
  7849. if (max < y[i][j]) {
  7850. max = y[i][j];
  7851. data.maxIndex=i;
  7852. }
  7853. if (min > y[i][j]) {
  7854. min = y[i][j];
  7855. data.minIndex=i;
  7856. }
  7857. }
  7858. }
  7859. data.maxY = max;
  7860. data.minY = min;
  7861. return data;
  7862. }
  7863. //
  7864. //读取蜡烛图的数据
  7865. //
  7866. function DataReaderCandle(model, writer, name) {
  7867. sup(this, model, writer, name);
  7868. }
  7869. ClassExtend(DataReaderCandle, DataReader);
  7870. //抽象函数,不提供任何的功能。
  7871. DataReaderCandle.prototype.getDataByNumber = function(number, readconfig) {
  7872. if (readconfig & DataReader.EXTEND) {
  7873. //以扩展的方式读取
  7874. return this.getDataByNumberExtend(number, readconfig);
  7875. }
  7876. //普通的读取方式
  7877. //这里,如果读取到末尾了,要修正start
  7878. var x = new Array(number);
  7879. var y = new Array(number);;
  7880. var index = 0;
  7881. start = this.getStart(number);
  7882. for (var i = start; i < this.store.time.length; i++) {
  7883. x[index] = this.store.time[i];
  7884. y[index] = this.store.ohlc[i];
  7885. index++;
  7886. if (index >= number) {
  7887. break;
  7888. }
  7889. }
  7890. if (index < number) {
  7891. x = x.slice(0, index - 1);
  7892. y = y.slice(0, index - 1);
  7893. }
  7894. //深度复制
  7895. y = array_copy2d(y);
  7896. return { x: x, y: y };
  7897. }
  7898. DataReaderCandle.prototype.getData = function(number, readconfig) {
  7899. return this.getDataByNumber(number, readconfig);
  7900. }
  7901. DataReaderCandle.prototype.getDataByNumberExtend = function(number, readconfig) {
  7902. // console.log("number:"+number);
  7903. var x = new Array(number);
  7904. var y = new Array(number);
  7905. var index = 0;
  7906. //普通的读取方式
  7907. //这里,如果读取到末尾了,要修正start
  7908. var start = this.getStart(number);
  7909. var xdata = this.writer.getX(this.c, this.p);
  7910. var ydata = this.writer.getY(this.c, this.p);
  7911. var length = xdata.length;
  7912. if (length == 0) {
  7913. return { x: [], y: [] };
  7914. }
  7915. x[index] = xdata[start];
  7916. y[index] = ydata[start];
  7917. for (var i = start; i < length - 1; i++) {
  7918. var ctime = xdata[i]; //当前时间
  7919. var ptime = xdata[i + 1]; //前一个时间
  7920. //1.
  7921. if (ctime - ptime == this.step || ctime - ptime > this.maxstep) { //连续,或者相差太大。加入
  7922. index++;
  7923. x[index] = xdata[i + 1];
  7924. y[index] = ydata[i + 1];
  7925. } else { //需要补全,x值每次 加step y用 ptime对应的值
  7926. var close = ydata[i + 1][Data.CLOSE];
  7927. var candle = [close, close, close, close, ydata[i + 1][Data.VOLUMES]];
  7928. for (var newtime = xdata[i] - this.step; newtime > xdata[i + 1]; newtime -= this.step) {
  7929. index++;
  7930. x[index] = newtime;
  7931. y[index] = candle;
  7932. }
  7933. index++;
  7934. x[index] = xdata[i + 1];
  7935. y[index] = ydata[i + 1];
  7936. }
  7937. if (index + 1 >= number) {
  7938. break;
  7939. }
  7940. }
  7941. index++;
  7942. if (index < number) {
  7943. x = x.slice(0, index);
  7944. y = y.slice(0, index);
  7945. }
  7946. y = array_copy2d(y);
  7947. return { x: x, y: y };
  7948. }
  7949. //和main的时间进行对齐,对于稀疏的数据,这个非常重要
  7950. DataReaderCandle.prototype.extendByMain = function(xdata, ydata) {
  7951. var mainX = this.getMainData().x;
  7952. var x = new Array();
  7953. var y = new Array();
  7954. var j = 0;
  7955. //1. 如果时间值超过了Main[0],那么直接忽略
  7956. //2. 如果某个值开始小于main[0],那么,main 开始加。直到main[i] < 这个值。
  7957. //3. 我们的索引加
  7958. if (xdata.length == 0 || xdata[xdata.length - 1] > mainX[mainX.length - 1]) {
  7959. //无效,这样的情况无法进行补全。
  7960. return { x: [], y: [] };
  7961. }
  7962. //计算第一个数据
  7963. var current = 0,
  7964. count = 0;
  7965. var close = ydata[current][Data.CLOSE];
  7966. candle = [close, close, close, close, ydata[current][Data.VOLUMES]];
  7967. for (var i = 0; i < mainX.length; i++) {
  7968. if (xdata[current] > mainX[i]) //这样的情况是无效的,从程序的条件可以看出,current 不会越界。
  7969. {
  7970. while (xdata[current] > mainX[i]) {
  7971. current++;
  7972. }
  7973. if (!ydata[current]) {
  7974. alert(current); //debug 的信息
  7975. }
  7976. close = ydata[current][Data.CLOSE];
  7977. candle = [close, close, close, close, ydata[current][Data.VOLUMES]];
  7978. }
  7979. if (mainX[i] > xdata[current]) {
  7980. y[count++] = candle;
  7981. } else if (mainX[i] == xdata[current]) {
  7982. y[count++] = ydata[current];
  7983. }
  7984. }
  7985. x = array_copy1d(mainX);
  7986. y = array_copy2d(y);
  7987. return { x: x, y: y };
  7988. }
  7989. DataReaderCandle.prototype.close = function(index) {
  7990. if (!index || index < 0) index = 0;
  7991. return this.store.ohlc[index][Data.CLOSE];
  7992. }
  7993. DataReaderCandle.prototype.formatData = function(x, y) {
  7994. var data = {};
  7995. data.x = x;
  7996. data.y = y;
  7997. data.xunit = this.xunit;
  7998. data.yunit = this.yunit;
  7999. data.maxX = x[0];
  8000. var nLen = y.length;
  8001. if (nLen > this.model.plotnum) {
  8002. nLen = this.model.plotnum;
  8003. }
  8004. data.minX = x[nLen - 1];
  8005. data.maxIndex=0;
  8006. data.minIndex=0;
  8007. var min = Infinity
  8008. var max = -Infinity;
  8009. //console.log("model=",this.model.plotnum,x);
  8010. for (var i = 0; i < y.length && i < this.model.plotnum; i++)
  8011. //for(var i=y.length-1;i>=0&& (y.length-i)<=this.model.plotnum;i--)
  8012. {
  8013. if (y[i][Data.HIGH] > max) {
  8014. max = y[i][Data.HIGH];
  8015. data.maxIndex=i;
  8016. }
  8017. if (y[i][Data.LOW] < min) {
  8018. min = y[i][Data.LOW];
  8019. data.minIndex=i;
  8020. }
  8021. }
  8022. data.maxY = max;
  8023. data.minY = min;
  8024. return data;
  8025. }
  8026. DataReaderCandle.prototype.getYminmax = function(y) {
  8027. var ymax = -Infinity;
  8028. var ymin = Infinity;
  8029. var minIndex=0;
  8030. var maxIndex=0;
  8031. if (!y) {
  8032. return [ymin, ymax,minIndex,maxIndex];
  8033. }
  8034. //for(var i=y.length-1;i>=0&& (y.length-i)<=this.model.plotnum;i--)
  8035. for (var i = 0; i < y.length && i < this.model.plotnum; i++) {
  8036. for (var j = 0; j < 4; j++) {
  8037. var value = y[i][j];
  8038. if (value > ymax) {
  8039. ymax = value;
  8040. maxIndex=i;
  8041. }
  8042. if (value < ymin) {
  8043. ymin = value;
  8044. minIndex=i;
  8045. }
  8046. }
  8047. }
  8048. return [ymin, ymax,minIndex,maxIndex];
  8049. }
  8050. function PlotEasyforex(plot, canvas) {
  8051. this.plot = plot;
  8052. this.canvas = canvas;
  8053. this.last = last;
  8054. this.initMyPlot();
  8055. }
  8056. //X Y 轴都要根据数据,绘制图形。
  8057. //分离 主绘图区域 的数据 和 candle的 绘制。
  8058. //使得数据 和 绘图分离,提高复用能力。
  8059. //
  8060. PlotEasyforex.prototype.initMyPlot = function() {
  8061. }
  8062. //���ڣ�����������һ��ָ�걻ע���ˣ�
  8063. //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
  8064. //���������ݣ��ͻ�������K�ߵ����ؽ�������
  8065. //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
  8066. //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
  8067. //Ȼ�����غ�����ָ��,���ؽ����Ժ󣬺ϲ�������������ָ�꣬���󣬳�ʼ��������
  8068. //
  8069. //��ȡ����ͼ������
  8070. //
  8071. function DataReaderFractals(model, writer, name) {
  8072. sup(this, model, writer, name);
  8073. }
  8074. ClassExtend(DataReaderFractals, DataReader);
  8075. DataReaderFractals.prototype.getYminmax = function(y) {
  8076. var ymax = -Infinity;
  8077. var ymin = Infinity;
  8078. var minIndex=0;
  8079. var maxIndex=0;
  8080. if (!y) {
  8081. return [ymin, ymax,minIndex,maxIndex];
  8082. }
  8083. for (var i = 0; i < y.length; i++) {
  8084. var value = y[i][1];
  8085. if (value > ymax) {
  8086. ymax = value;
  8087. maxIndex=i;
  8088. }
  8089. if (value < ymin) {
  8090. ymin = value;
  8091. minmax=i;
  8092. }
  8093. }
  8094. return [ymin, ymax,minIndex,maxIndex];
  8095. }
  8096. function DataReaderIndicators(model, writer, name) {
  8097. sup(this, model, writer, name);
  8098. this.data = {};
  8099. this.lastdata = {};
  8100. }
  8101. ClassExtend(DataReaderIndicators, DataReader);
  8102. DataReaderIndicators.prototype.minmax = function(start, n) {
  8103. var high = -Infinity;
  8104. var low = Infinity;
  8105. for (var i = start; i < start + n && i < this.y.length; i++) {
  8106. if (this.y[i][Data.HIGH] > high) {
  8107. high = this.y[i][Data.HIGH];
  8108. }
  8109. if (this.y[i][Data.LOW] < low) {
  8110. low = this.y[i][Data.LOW];
  8111. }
  8112. }
  8113. // console.log(this.name, high, low);
  8114. return [high, low];
  8115. }
  8116. DataReaderIndicators.prototype.sum = function(start, length) {
  8117. if (this.y.length < start + length) {
  8118. return false;
  8119. }
  8120. var sum = 0;
  8121. for (var i = start; i < start + length; i++) {
  8122. sum += this.y[i][Data.CLOSE];
  8123. }
  8124. return sum;
  8125. }
  8126. DataReaderIndicators.prototype.setParam = function(param) {
  8127. this.param = param;
  8128. }
  8129. DataReaderIndicators.prototype.setDependData = function(name, data) {
  8130. this.data[name] = data;
  8131. }
  8132. //大多数指标可以这样初始化。如果子类初始化不一样,可以做处理
  8133. DataReaderIndicators.prototype.dataInit = function(name) {
  8134. //init 先计算前n个值
  8135. //y是一个二维数组
  8136. if (!name) {
  8137. name = this.param[0][0];
  8138. }
  8139. if (this.data[name] && this.data[name].y) {
  8140. //[read only] 如果需要修改,请先复制。否则会改动原始数据。
  8141. this.y = this.data[name].y;
  8142. this.x = this.data[name].x;
  8143. } else {
  8144. return false;
  8145. }
  8146. //默认数据源是倒序排列的
  8147. if (this.n > this.y.length) {
  8148. return false;
  8149. }
  8150. if (!this.y) {
  8151. return false;
  8152. }
  8153. if (this.y && this.y.length == 0) {
  8154. return false;
  8155. }
  8156. return true;
  8157. }
  8158. //常用指标的实现
  8159. DataReaderIndicators.prototype.wpr = function(n) {
  8160. var data = [];
  8161. var minmax = this.minmax(0, n);
  8162. var low = minmax[1];
  8163. var high = minmax[0];
  8164. var wr;
  8165. if (low == high) {
  8166. wr = 0;
  8167. } else {
  8168. wr = 100 * (this.y[0][Data.CLOSE] - high) / (high - low);
  8169. }
  8170. data.push(wr);
  8171. var index = 0;
  8172. for (var i = 1; i < this.y.length - n; i++) {
  8173. index = i + n - 1; //from i to index, total n number data.
  8174. if (this.y[index][Data.LOW] > low && this.y[index][Data.HIGH] < high && this.y[i][Data.LOW] > low && this.y[i][Data.HIGH] < high) {
  8175. //do nothing, high and low 不会变化
  8176. } else {
  8177. minmax = this.minmax(i, n);
  8178. low = minmax[1];
  8179. high = minmax[0];
  8180. }
  8181. if (low == high) {
  8182. wr = 0;
  8183. } else {
  8184. wr = 100 * (this.y[i][Data.CLOSE] - high) / (high - low);
  8185. }
  8186. data.push(wr);
  8187. }
  8188. //后面为空的补零,这样和时间才能对齐。
  8189. for (var i = 0; i < n; i++) {
  8190. data.push(0);
  8191. }
  8192. return data;
  8193. }
  8194. DataReaderIndicators.prototype.ma = function(n) {
  8195. var avg = [];
  8196. var sum = this.sum(0, n);
  8197. avg.push(sum / n);
  8198. for (var i = 1; i < this.y.length - n; i++) {
  8199. sum -= this.y[i - 1][Data.CLOSE];
  8200. sum += this.y[i + n - 1][Data.CLOSE];
  8201. avg.push(sum / n);
  8202. }
  8203. for (var i = 0; i < n; i++) {
  8204. avg.push(0);
  8205. }
  8206. return avg;
  8207. }
  8208. DataReaderIndicators.prototype.strength = function(n) {
  8209. var data = [];
  8210. var high = -Infinity;
  8211. var low = Infinity;
  8212. var index, item;
  8213. for (var i = 0; i < this.y.length - n; i++) {
  8214. index = i + n - 1;
  8215. item = this.y[i][Data.CLOSE] - this.y[index][Data.CLOSE];
  8216. if (high < item) {
  8217. high = item;
  8218. }
  8219. if (low > item) {
  8220. low = item;
  8221. }
  8222. data.push(item);
  8223. }
  8224. for (var i = 0; i < data.length; i++) {
  8225. data[i] = (data[i] / (high - low)) * 100;
  8226. }
  8227. //后面为空的补零,这样和时间才能对齐。
  8228. for (var i = 0; i < n; i++) {
  8229. data.push(0);
  8230. }
  8231. return data;
  8232. }
  8233. DataReaderIndicators.prototype.last = function() {
  8234. return this.lastdata;
  8235. }
  8236. //���ڣ�����������һ��ָ�걻ע���ˣ�
  8237. //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
  8238. //���������ݣ��ͻ�������K�ߵ����ؽ�������
  8239. //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
  8240. //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
  8241. //Ȼ�����غ�����ָ��,���ؽ����Ժ󣬺ϲ�������������ָ�꣬���󣬳�ʼ��������
  8242. //
  8243. //��ȡ����ͼ������
  8244. //
  8245. function DataReaderKshape(model, writer, name) {
  8246. sup(this, model, writer, name);
  8247. }
  8248. ClassExtend(DataReaderKshape, DataReader);
  8249. DataReaderKshape.prototype.getYminmax = function(y) {
  8250. var ymax = -Infinity;
  8251. var ymin = Infinity;
  8252. var maxIndex=0;
  8253. var minIndex=0;
  8254. if (!y) {
  8255. return [ymin, ymax,minIndex,maxIndex];
  8256. }
  8257. for (var i = 0; i < y.length; i++) {
  8258. var value = y[i][0];
  8259. if (value > ymax) {
  8260. ymax = value;
  8261. maxIndex=i;
  8262. }
  8263. if (value < ymin) {
  8264. ymin = value;
  8265. minIndex=i;
  8266. }
  8267. }
  8268. //console.log(ymax)
  8269. //console.log(ymin)
  8270. return [ymin, ymax,minIndex,maxIndex];
  8271. }
  8272. function DataReaderMa(data, period, shift) {
  8273. if (!period) {
  8274. period = 14;
  8275. }
  8276. if (!shift) {
  8277. shift = 0;
  8278. }
  8279. this.data = data;
  8280. this.period = period;
  8281. $.cookie('period',period);
  8282. this.shift = shift;
  8283. this.X = [];
  8284. this.Y = [];
  8285. }
  8286. ClassExtend(DataReaderMa, DataReader);
  8287. DataReaderMa.prototype.calc = function(start, count, time, data) {
  8288. //计算移动平均线
  8289. //start:
  8290. var sum = 0;
  8291. var i, j;
  8292. for (i = start, j = 0; j < count; i++, j++) {
  8293. this.X[j] = time[i];
  8294. }
  8295. }
  8296. //现在,这样处理,一旦指标被注册了,
  8297. //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
  8298. //后面的数据,就会绑定在K线的下载结果里面
  8299. //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
  8300. //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
  8301. //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
  8302. function DataReaderMacd(model, writer, name) {
  8303. sup(this, model, writer, name);
  8304. }
  8305. ClassExtend(DataReaderMacd, DataReader);
  8306. function DataReaderMaex(model, writer, name) {
  8307. sup(this, model, writer, name);
  8308. }
  8309. ClassExtend(DataReaderMaex, DataReader);
  8310. function DataReaderMath(model, writer, name) {
  8311. this.data = {};
  8312. this.lastdata = {};
  8313. sup(this, model, writer, name);
  8314. this.start = 0;
  8315. this.end = 0;
  8316. this.number = 0;
  8317. this.xunit = 0;
  8318. this.yunit = 0;
  8319. }
  8320. ClassExtend(DataReaderMath, DataReader);
  8321. //对数学公式来说,只要设置一个 x轴的区间 和 要划分的 数目就可以了
  8322. DataReaderMath.prototype.setXArea = function(start, end, number) {
  8323. this.start = start;
  8324. this.end = end;
  8325. this.number = number;
  8326. if (number <= 0) {
  8327. return;
  8328. }
  8329. var x = [];
  8330. var step = (this.end - this.start) / this.number;
  8331. var i = this.start;
  8332. while (i <= this.end) {
  8333. x.push(i);
  8334. i += step;
  8335. }
  8336. this.data.x = x.reverse();
  8337. }
  8338. DataReaderMath.prototype.setParam = function(param) {
  8339. if (param.length >= 2) {
  8340. param = param[1].split(",");
  8341. for (var i = 0; i < param.length; i++) {
  8342. param[i] = parseInt(param[i]);
  8343. }
  8344. this.setXArea(param[0], param[1], param[2]);
  8345. }
  8346. }
  8347. DataReaderMath.prototype.last = function() {
  8348. return this.lastdata;
  8349. }
  8350. DataReaderMath.prototype.getEndPos = function() {
  8351. var x = this.data.x;
  8352. return x.length - 1;
  8353. }
  8354. DataReaderMath.prototype.startXValue = function() {
  8355. var x = this.data.x;
  8356. return x[x.length - 1];
  8357. }
  8358. DataReaderMath.prototype.endXValue = function() {
  8359. var x = this.data.x;
  8360. return x[0];
  8361. }
  8362. DataReaderMath.prototype.formatData = function(x, y) {
  8363. var data = {};
  8364. data.x = x;
  8365. data.y = y;
  8366. data.maxX = x[0];
  8367. data.minX = x[x.length - 1];
  8368. data.maxIndex=0;
  8369. data.minIndex=0;
  8370. var _minmax = minmax(y);
  8371. data.maxY = _minmax[1];
  8372. data.minY = _minmax[0];
  8373. data.maxIndex=_minmax[3];
  8374. data.minIndex=_minmax[2];
  8375. data.xunit = this.getUnit(data.minX, data.maxX);
  8376. data.yunit = this.getUnit(data.minY, data.maxY);
  8377. return data;
  8378. }
  8379. DataReaderMath.prototype.getUnit = function(min, max) {
  8380. var step = (max - min) / this.number;
  8381. return Math.pow(10, Math.floor(Math.log(step) / Math.LN10));
  8382. }
  8383. //现在,这样处理,一旦指标被注册了,
  8384. //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
  8385. //后面的数据,就会绑定在K线的下载结果里面
  8386. //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
  8387. //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
  8388. //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
  8389. function DataReaderOrder(model, writer, name) {
  8390. sup(this, model, writer, name);
  8391. }
  8392. ClassExtend(DataReaderOrder, DataReader);
  8393. //
  8394. //读取蜡烛图的数据
  8395. //
  8396. function DataReaderProfit(model, writer, name) {
  8397. sup(this, model, writer, name);
  8398. }
  8399. ClassExtend(DataReaderProfit, DataReader);
  8400. DataReaderProfit.prototype.getYminmax = function(y) {
  8401. var ymax = -Infinity;
  8402. var ymin = Infinity;
  8403. var maxIndex=0;
  8404. var minIndex=0;
  8405. if (!y) {
  8406. return [ymin, ymax,minIndex,maxIndex];
  8407. }
  8408. for (var i = 0; i < y.length; i++) {
  8409. for (var j = 0; j < y[i].length; j++) {
  8410. var value = y[i][j][1];
  8411. if (value > ymax) {
  8412. ymax = value;
  8413. maxIndex=i;
  8414. }
  8415. if (value < ymin) {
  8416. ymin = value;
  8417. minIndex=i;
  8418. }
  8419. }
  8420. }
  8421. return [ymin, ymax,minIndex,maxIndex];
  8422. }
  8423. function DataReaderTickSource(model, writer, name) {
  8424. sup(this, model, writer, name);
  8425. this.maxdata = this.config[name].maxdata;
  8426. this.data = {};
  8427. this.cmd = "";
  8428. this.number = 60;
  8429. this.nameToId = { 'FXDD': 0, 'FXPRO': 1, 'EXNESS': 2, 'IRONFX': 3, "FXCM": 4 };
  8430. this.idToName = ['FXDD', 'FXPRO', 'EXNESS', 'IRONFX', "FXCM"];
  8431. this.microsecond = 0;
  8432. this.lastStatus = { width: {}, offset: {}, time: {}, quick: { queue: {}, inquick: false } };
  8433. this.lastdata;
  8434. }
  8435. ClassExtend(DataReaderTickSource, DataReader);
  8436. DataReaderTickSource.prototype.setParam = function(param) {
  8437. this.param = param;
  8438. var cmd = this.param[1].split(",");
  8439. var tmp = cmd.shift();
  8440. tmp = tmp.split("/");
  8441. this.bidask = tmp[0];
  8442. this.number = parseInt(tmp[1]);
  8443. this.microsecond = parseInt(tmp[2]);
  8444. if (!this.c) {
  8445. return;
  8446. }
  8447. var r = [];
  8448. for (var i = 0; i < cmd.length; i++) {
  8449. r.push(this.c + "_" + cmd[i]);
  8450. }
  8451. this.cmd = "tick_source:" + r.join(",");
  8452. }
  8453. DataReaderTickSource.prototype.getWSCmd = function() {
  8454. this.setParam(this.param);
  8455. return this.cmd;
  8456. }
  8457. DataReaderTickSource.prototype.getData = function() {
  8458. var type, id;
  8459. var store, len;
  8460. var x, y, bidask;
  8461. var data = { x: [], y: {} };
  8462. this.lastdata = {};
  8463. this.lastStatus.time[this.writer.lastSource] = now();
  8464. for (var i = 0; i < this.idToName.length; i++) {
  8465. x = [];
  8466. y = [];
  8467. type = this.idToName[i];
  8468. id = this.nameToId[type];
  8469. store = this.writer.getStore(this.c, type);
  8470. len = store.x.length;
  8471. if (len == 0) {
  8472. continue;
  8473. }
  8474. if (this.bidask == "bid") {
  8475. bidask = 0;
  8476. } else if (this.bidask == "bid-ask") {
  8477. bidask = -1;
  8478. } else {
  8479. bidask = 1;
  8480. }
  8481. this.lastdata[type] = {};
  8482. this.lastdata[type].bidask = store.y[len - 1];
  8483. for (var j = 0; j < this.number && j < len; j++) {
  8484. var second = store.x[len - 1 - j];
  8485. if (this.microsecond) {
  8486. x[j] = second;
  8487. } else {
  8488. x[j] = parseInt(second / 1000) * 1000;
  8489. }
  8490. if (bidask < 0) {
  8491. y[j] = (store.y[len - 1 - j][0] + store.y[len - 1 - j][1]) / 2;
  8492. } else {
  8493. y[j] = store.y[len - 1 - j][bidask];
  8494. }
  8495. }
  8496. this.lastdata[type].x = x[0];
  8497. this.lastdata[type].y = y[0];
  8498. data.y[type] = { x: x, y: y };
  8499. }
  8500. return data;
  8501. }
  8502. DataReaderTickSource.prototype.formatData = function(x, y) {
  8503. var minX = Infinity;
  8504. var minY = Infinity;
  8505. var maxX = -Infinity;
  8506. var maxY = -Infinity;
  8507. var hasdata = false;
  8508. var len = 0;
  8509. for (var type in y) {
  8510. if (!is_object(y[type])) continue;
  8511. len = y[type].x.length;
  8512. if (len == 0) {
  8513. continue;
  8514. }
  8515. hasdata = true;
  8516. var data = this._formatData(y[type].x, y[type].y);
  8517. if (minX > data.minX) minX = data.minX;
  8518. if (minY > data.minY) minY = data.minY;
  8519. if (maxX < data.maxX) maxX = data.maxX;
  8520. if (maxY < data.maxY) maxY = data.maxY;
  8521. }
  8522. if (!hasdata) {
  8523. return { x: [], y: [] };
  8524. }
  8525. var data = this.lastInfo();
  8526. data.x = [minX, maxX];
  8527. data.xunit = 1;
  8528. data.yunit = this.yunit;
  8529. data.minX = minX;
  8530. data.minY = minY;
  8531. data.maxY = maxY;
  8532. data.maxX = maxX;
  8533. data.y = [minY, maxY]
  8534. data.data = y;
  8535. return data;
  8536. }
  8537. DataReaderTickSource.prototype.last = function() {
  8538. return this.lastdata;
  8539. }
  8540. DataReaderTickSource.prototype.lastInfo = function() {
  8541. //计算平均值
  8542. var avg = 0;
  8543. var num = 0;
  8544. var timemax = -Infinity;
  8545. var timemin = Infinity;
  8546. var tick_timemax = -Infinity;
  8547. var tick_timemin = Infinity;
  8548. var maxname, minname;
  8549. var tick_maxname, tick_minname;
  8550. var last = this.lastdata;
  8551. for (var key in last) {
  8552. if (!is_object(last[key])) {
  8553. continue;
  8554. }
  8555. if (this.lastStatus.time[key] > timemax) {
  8556. timemax = this.lastStatus.time[key];
  8557. maxname = key;
  8558. }
  8559. if (this.lastStatus.time[key] < timemin) {
  8560. timemin = this.lastStatus.time[key];
  8561. minname = key;
  8562. }
  8563. if (last[key].x > tick_timemax) {
  8564. tick_timemax = last[key].x;
  8565. tick_maxname = key;
  8566. }
  8567. if (last[key].x < tick_timemin) {
  8568. tick_timemin = last[key].x;
  8569. tick_minname = key;
  8570. }
  8571. if (typeof this.lastStatus.width[key] === "undefined") {
  8572. this.lastStatus.width[key] = 3;
  8573. }
  8574. num++;
  8575. avg += last[key].y;
  8576. }
  8577. avg = avg / num;
  8578. this.lastStatus.offset.local = now() - tick_timemax;
  8579. this.lastStatus.offset.delt = timemax - timemin;
  8580. //存在突破,要显示最后的bid ask 时间
  8581. if (this.lastStatus.quick.inquick == true) {
  8582. var quick = this.lastStatus.quick;
  8583. quick.queue[this.writer.lastSource] = 1;
  8584. qnumber = 0;
  8585. for (var key in quick.queue) {
  8586. if (quick.queue[key] === 1) {
  8587. qnumber++;
  8588. }
  8589. }
  8590. if (qnumber == num) {
  8591. quick.end = maxname;
  8592. quick.inquick = false;
  8593. quick.delt = this.lastStatus.time[quick.end] - this.lastStatus.time[quick.start];
  8594. }
  8595. }
  8596. var show = false;
  8597. var point = Math.abs(Math.floor(last[maxname].y / this.yunit) - Math.floor(avg / this.yunit));
  8598. if (this.lastStatus.quick.inquick == false && point >= 4) {
  8599. show = true;
  8600. this.lastStatus.quick = {};
  8601. this.lastStatus.quick.bidask = {};
  8602. this.lastStatus.quick.start = maxname;
  8603. this.lastStatus.quick.inquick = true;
  8604. this.lastStatus.quick.queue = {};
  8605. this.lastStatus.quick.point = point;
  8606. this.lastStatus.quick.queue[maxname] = 1;
  8607. for (var key in this.lastStatus.width) {
  8608. if (this.lastStatus.width[key] === 6) this.lastStatus.width[key] = 3;
  8609. this.lastStatus.quick.bidask[key] = this.lastdata[key] ? this.lastdata[key].bidask : [];
  8610. }
  8611. this.lastStatus.width[maxname] = 6;
  8612. }
  8613. if (Math.abs(Math.floor(last[minname].y / this.yunit) - Math.floor(avg / this.yunit)) >= 4) {
  8614. show = true;
  8615. for (var key in this.lastStatus.width) {
  8616. if (this.lastStatus.width[key] === 0.5) this.lastStatus.width[key] = 3;
  8617. }
  8618. this.lastStatus.width[minname] = 0.5;
  8619. }
  8620. this.lastStatus.show = show;
  8621. return this.lastStatus;
  8622. //计算最快值和最慢值
  8623. }
  8624. function PlotCandleBollingDesity(plot, canvas) {
  8625. this.name = "BollingDesity";
  8626. this.plot = plot;
  8627. this.grid = this.plot.grid;
  8628. this.api = plot.api;
  8629. this.time = [];
  8630. this.data = []; //所有的数据
  8631. this.cdata = new Point([], []); //当前要绘制的点
  8632. this.config = {
  8633. Long: { Up: 0, Low: 2, Color: "Yellow" },
  8634. Mid1: { Up: 4, Low: 6, Color: "Red" },
  8635. Mid2: { Up: 8, Low: 10, Color: "Purple" },
  8636. Short1: { Up: 12, Low: 14, Color: "Green" },
  8637. Short2: { Up: 16, Low: 18, Color: "LightSeaGreen" }
  8638. };
  8639. this.init = false;
  8640. this.databuf = [];
  8641. }
  8642. //PlotCandle 有一个指标列表,在相应的处理上,加上这个这些接口
  8643. //提供下面的接口,用于下载数据,更新数据: 先更新time_start 和 mid_time
  8644. //再更新剩下来的部分
  8645. PlotCandleBollingDesity.prototype.init = function(time_start, mid_time, time_end) {
  8646. if (time_start == mid_time) {
  8647. this.initComplete();
  8648. return;
  8649. }
  8650. var _this = this;
  8651. $.get(this.api, { action: 'indicator', name: this.name, 'ts': time_start, 'te': mid_time }, function(data) {
  8652. _this.processHistoryData(data);
  8653. if (mid_time == time_end) {
  8654. this.initComplete();
  8655. }
  8656. }, 'json');
  8657. if (mid_time < time_end) {
  8658. $.get(this.api, { action: 'indicator', name: this.name, 'ts': mid_time + 1, 'te': time_end }, function(data) {
  8659. _this.processHistoryData(data);
  8660. //处理原来下载的数据
  8661. this.initComplete();
  8662. }, 'json');
  8663. }
  8664. }
  8665. PlotCandleBollingDesity.prototype.initComplete = function() {
  8666. for (var i = 0; i < this.databuf.length; i++) {
  8667. this.processHistoryData(this.databuf[i]);
  8668. }
  8669. this.databuf = [];
  8670. this.init = true;
  8671. }
  8672. PlotCandleBollingDesity.prototype.draw = function() {
  8673. var X = array_copy(this.cdata.x);
  8674. var Y = array_copy(this.cdata.y);
  8675. //分成5种线来绘制
  8676. var yset = {};
  8677. for (var i = 0; i < X.length; i++) {
  8678. for (var key in this.config) {
  8679. if (typeof key == "string" && key != "undefined") {
  8680. var max_index = this.config[key].Up;
  8681. var min_index = this.config[key].Low;
  8682. var color = this.config[key].Color;
  8683. if (yset[key] === undefined) {
  8684. yset[key] = {};
  8685. }
  8686. if (Y[i][max_index] != 0) {
  8687. if (yset[key].Up === undefined) {
  8688. yset[key].Up = new Point([], [], []);
  8689. }
  8690. yset[key].Up.x.push(X[i]);
  8691. yset[key].Up.y.push(Y[i][max_index]);
  8692. yset[key].Up.z.push(Y[i][max_index + 1]);
  8693. }
  8694. if (Y[i][min_index] != 0) {
  8695. if (yset[key].Low === undefined) {
  8696. yset[key].Low = new Point([], [], []);
  8697. }
  8698. yset[key].Low.x.push(X[i]);
  8699. yset[key].Low.y.push(Y[i][min_index]);
  8700. yset[key].Low.z.push(Y[i][min_index + 1]);
  8701. }
  8702. }
  8703. }
  8704. }
  8705. var minmax = this.getMinMaxDensity();
  8706. for (var key in yset) {
  8707. if (typeof key == "string" && key != "undefined") {
  8708. if (yset[key].Up) {
  8709. this.drawOne(yset[key].Up, this.config[key].Color, minmax);
  8710. }
  8711. if (yset[key].Low) {
  8712. this.drawOne(yset[key].Low, this.config[key].Color, minmax);
  8713. }
  8714. }
  8715. }
  8716. }
  8717. PlotCandleBollingDesity.prototype.getLineHeight = function(min, max, data) {
  8718. for (var i = 0; i < data.length; i++) {
  8719. data[i] = Math.floor(((data[i] - min) / (max - min)) * 5) + 1;
  8720. }
  8721. return data;
  8722. }
  8723. PlotCandleBollingDesity.prototype.drawOne = function(data, color, minmax) {
  8724. data.y = this.grid.getY(data.y);
  8725. data.z = this.getLineHeight(minmax[0], minmax[1], data.z);
  8726. var ctx = this.grid.ctx;
  8727. ctx.fillStyle = color;
  8728. for (var i = 0; i < data.x.length; i++) {
  8729. ctx.fillRect(data.x[i] - this.plot.box_pixel, data.y[i] - data.z[i], 2 * this.plot.box_pixel + 1, data.z[i]);
  8730. }
  8731. }
  8732. PlotCandleBollingDesity.prototype.updateNew = function(time) {
  8733. //do nothing
  8734. }
  8735. PlotCandleBollingDesity.prototype.down = function(time_start, time_end) {
  8736. var _this = this;
  8737. $.get(this.api, { action: 'indicator', name: this.name, 'ts': time_start, 'te': time_end }, function(data) {
  8738. if (this.init) {
  8739. _this.processHistoryData(data);
  8740. } else {
  8741. _this.databuf.push(data);
  8742. }
  8743. }, 'json');
  8744. }
  8745. PlotCandleBollingDesity.prototype.processHistoryData = function(data) {
  8746. var newdata = data[this.name];
  8747. if (!is_array(newdata) || newdata.length == 0) {
  8748. return;
  8749. }
  8750. for (var i = 0; i < newdata.length; i++) {
  8751. var item = newdata[i];
  8752. this.time.push(parseInt(item.pop()));
  8753. var flag = item.shift();
  8754. if (flag == null) {
  8755. item = null;
  8756. } else {
  8757. for (var j = 0; j < item.length; j++) {
  8758. item[j] = parseFloat(item[j]);
  8759. }
  8760. }
  8761. this.data.push(item);
  8762. }
  8763. }
  8764. PlotCandleBollingDesity.prototype.getDrawData = function(start_index, end_index) {
  8765. var y = this.data.slice(start_index, end_index + 1);
  8766. this.cdata.y = [];
  8767. this.cdata.x = [];
  8768. for (var i = 0; i < y.length - 1; i++) {
  8769. if (y[i] != null) {
  8770. this.cdata.y.push(y[i]);
  8771. this.cdata.x.push(this.plot.X[i]);
  8772. }
  8773. }
  8774. return this.cdata;
  8775. }
  8776. PlotCandleBollingDesity.prototype.getMinMax = function() {
  8777. var data = this.cdata.y;
  8778. var max = -Infinity;
  8779. var min = Infinity;
  8780. for (var i = 0; i < data.length; i++) {
  8781. for (var key in this.config) {
  8782. if (typeof key == "string" && key != "undefined") {
  8783. var max_index = this.config[key].Up;
  8784. var min_index = this.config[key].Low;
  8785. if (data[i][max_index] > 0 && max < data[i][max_index]) {
  8786. max = data[i][max_index]
  8787. }
  8788. if (data[i][min_index] > 0 && min > data[i][min_index]) {
  8789. min = data[i][min_index];
  8790. }
  8791. }
  8792. }
  8793. }
  8794. return [min, max];
  8795. }
  8796. PlotCandleBollingDesity.prototype.getMinMaxDensity = function() {
  8797. var data = this.cdata.y;
  8798. var max = -Infinity;
  8799. var min = Infinity;
  8800. for (var i = 0; i < data.length; i++) {
  8801. for (var key in this.config) {
  8802. if (typeof key == "string" && key != "undefined") {
  8803. var max_index = this.config[key].Up;
  8804. var min_index = this.config[key].Low;
  8805. max = Math.max(max, data[i][max_index + 1], data[i][min_index + 1]);
  8806. min = Math.min(min, data[i][max_index + 1], data[i][min_index + 1]);
  8807. }
  8808. }
  8809. }
  8810. return [min, max];
  8811. }
  8812. //arr 从小到大
  8813. //reverse = true arr 从大到小
  8814. function bsearch(arr, match, reverse) {
  8815. var start = 0;
  8816. var end = arr.length - 1;
  8817. if (!reverse) {
  8818. reverse = false;
  8819. }
  8820. while (start <= end) {
  8821. mid = Math.floor((end - start) / 2) + start;
  8822. if (arr[mid] > match) {
  8823. if (reverse) {
  8824. start = mid + 1;
  8825. } else {
  8826. end = mid - 1;
  8827. }
  8828. } else if (arr[mid] < match) {
  8829. if (reverse) {
  8830. end = mid - 1;
  8831. } else {
  8832. start = mid + 1;
  8833. }
  8834. } else { //macth
  8835. return mid;
  8836. }
  8837. }
  8838. return -1;
  8839. }
  8840. //
  8841. //读取蜡烛图的数据
  8842. //
  8843. function DataReaderTrendLine(model, writer, name) {
  8844. sup(this, model, writer, name);
  8845. }
  8846. ClassExtend(DataReaderTrendLine, DataReader);
  8847. DataReaderTrendLine.prototype.getYminmax = function(y) {
  8848. var ymax = -Infinity;
  8849. var ymin = Infinity;
  8850. var maxIndex=0;
  8851. var minIndex=0;
  8852. //console.log("DataReaderTrendLine.prototype.getYminmax");
  8853. if (!y) {
  8854. return [ymin, ymax,minIndex,maxIndex];
  8855. }
  8856. for (var i = 0; i < y.length; i++) {
  8857. var value = y[i][0];
  8858. if (value > ymax) {
  8859. ymax = value;
  8860. maxIndex=i;
  8861. }
  8862. if (value < ymin) {
  8863. ymin = value;
  8864. minIndex=i;
  8865. }
  8866. }
  8867. return [ymin, ymax,minIndex,maxIndex];
  8868. }
  8869. //���ڣ�����������һ��ָ�걻ע���ˣ�
  8870. //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
  8871. //���������ݣ��ͻ�������K�ߵ����ؽ�������
  8872. //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
  8873. //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
  8874. //Ȼ�����غ�����ָ��,���ؽ����Ժ󣬺ϲ�������������ָ�꣬���󣬳�ʼ��������
  8875. //
  8876. //��ȡ����ͼ������
  8877. //
  8878. function DataReadervolumes(model, writer, name) {
  8879. sup(this, model, writer, name);
  8880. }
  8881. ClassExtend(DataReadervolumes, DataReader);
  8882. DataReadervolumes.prototype.getDataByMain = function(readconfig) {
  8883. this.mainData = this.getMainData();
  8884. //var start = this.mainData.x[this.mainData.x.length - 1];
  8885. //var end = this.mainData.x[0];
  8886. var x = new Array();
  8887. var y = new Array();
  8888. for (var i = 0; i < this.mainData.x.length && i < this.model.plotnum; i++) {
  8889. x.push(this.mainData.x[i]);
  8890. if (this.mainData.y[i][Data.OPEN] <= this.mainData.y[i][Data.CLOSE]) {
  8891. y.push([this.mainData.y[i][4]]);
  8892. } else {
  8893. y.push([this.mainData.y[i][4], 0]);
  8894. }
  8895. }
  8896. y = array_copy(y);
  8897. return { x: x, y: y };
  8898. }
  8899. DataReadervolumes.prototype.getYminmax = function(y) {
  8900. var ymax = -Infinity;
  8901. var ymin = 0;
  8902. var minIndex=0;
  8903. var maxIndex=0;
  8904. if (!y) {
  8905. return [ymin, ymax,minIndex,maxIndex];
  8906. }
  8907. for (var i = 0; i < y.length && i < this.model.plotnum; i++)
  8908. //for(var i=y.length-1;i>=0&& (y.length-i)<=this.model.plotnum;i--)
  8909. {
  8910. var value = y[i][0];
  8911. if (value > ymax) {
  8912. ymax = value;
  8913. maxIndex=i;
  8914. }
  8915. }
  8916. return [0, ymax,minIndex,maxIndex];
  8917. }
  8918. //���ڣ�����������һ��ָ�걻ע���ˣ�
  8919. //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
  8920. //���������ݣ��ͻ�������K�ߵ����ؽ�������
  8921. //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
  8922. //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
  8923. //Ȼ�����غ�����ָ��,���ؽ����Ժ󣬺ϲ�������������ָ�꣬���󣬳�ʼ��������
  8924. //
  8925. //��ȡ����ͼ������
  8926. //
  8927. function DataReadervolumes2(model, writer, name) {
  8928. sup(this, model, writer, name);
  8929. }
  8930. ClassExtend(DataReadervolumes2, DataReader);
  8931. DataReadervolumes2.prototype.getDataByMain = function(readconfig) {
  8932. this.mainData = this.getMainData();
  8933. var x = new Array();
  8934. var y = new Array();
  8935. for (var i = 0; i < this.mainData.x.length && i < this.model.plotnum; i++) {
  8936. x.push(this.mainData.x[i]);
  8937. y.push([this.mainData.y[i][5]]);
  8938. }
  8939. y = array_copy(y);
  8940. return { x: x, y: y };
  8941. }
  8942. DataReadervolumes2.prototype.getYminmax = function(y) {
  8943. var ymax = -Infinity;
  8944. var ymin = Infinity;
  8945. var minIndex=0;
  8946. var maxIndex=0;
  8947. if (!y) {
  8948. return [ymin, ymax,minIndex,maxIndex];
  8949. }
  8950. //for(var i=y.length-1;i>=0&& (y.length-i)<=this.model.plotnum;i--)
  8951. for (var i = 0; i < y.length && i < this.model.plotnum; i++) {
  8952. var value = y[i][0];
  8953. if (value > ymax) {
  8954. ymax = value;
  8955. maxIndex=i;
  8956. }
  8957. if (value < ymin) {
  8958. ymin = value;
  8959. minIndex=i;
  8960. }
  8961. }
  8962. return [0, ymax,minIndex,maxIndex];
  8963. }
  8964. function DataReaderWave(model, writer, name) {
  8965. sup(this, model, writer, name);
  8966. }
  8967. ClassExtend(DataReaderWave, DataReader);
  8968. //���ڣ�����������һ��ָ�걻ע���ˣ�
  8969. //�ͻ���������֪K���Ͻ��г�ʼ��������������ʼ������������K��ʱ�䷶Χ������
  8970. //���������ݣ��ͻ�������K�ߵ����ؽ�������
  8971. //��ָ����ʼ��δ������ʱ������������ʱ����ָ���������������ݣ���ô�ͻᱣ����һ�����������档
  8972. //ָ����ʼ����������K�ߵij�ʼ���������£������ص�һ��1000��K�ߵ�ָ�ꡣ��ʾ������
  8973. //Ȼ�����غ�����ָ��,���ؽ����Ժ󣬺ϲ�������������ָ�꣬���󣬳�ʼ��������
  8974. //
  8975. //��ȡ����ͼ������
  8976. //
  8977. function DataReaderwdensity(model, writer, name) {
  8978. sup(this, model, writer, name);
  8979. }
  8980. ClassExtend(DataReaderwdensity, DataReader);
  8981. DataReaderwdensity.prototype.getYminmax = function(y) {
  8982. var ymax = -Infinity;
  8983. var ymin = Infinity;
  8984. var minIndex=0;
  8985. var maxIndex=0;
  8986. if (!y) {
  8987. return [ymin, ymax,minIndex,maxIndex];
  8988. }
  8989. for (var i = 0; i < y.length; i++) {
  8990. for (var j = 0; j < y[i].length / 2; j++) {
  8991. if (y[i][j * 2] != 0 && y[i][j * 2 + 1] != 0) {
  8992. var value = y[i][j * 2];
  8993. if (value > ymax) {
  8994. ymax = value;
  8995. maxIndex=i;
  8996. }
  8997. if (value < ymin) {
  8998. ymin = value;
  8999. minIndex=i;
  9000. }
  9001. }
  9002. }
  9003. }
  9004. return [ymin, ymax,minIndex,maxIndex];
  9005. }
  9006. //现在,这样处理,一旦指标被注册了,
  9007. //就会首先在已知K线上进行初始化操作。这个初始化操作是已有K线时间范围的数据
  9008. //后面的数据,就会绑定在K线的下载结果里面
  9009. //在指标初始化未结束的时候,如果这个时候,指标绑定下载了数据,那么就会保存在一个缓冲区里面。
  9010. //指标初始化过程类似K线的初始化过程如下:先下载第一个1000个K线的指标。显示出来,
  9011. //然后下载后面的指标,下载结束以后,合并缓冲区里面的指标,最后,初始化结束。
  9012. function DataReaderWpr(model, writer, name) {
  9013. sup(this, model, writer, name);
  9014. }
  9015. ClassExtend(DataReaderWpr, DataReader);
  9016. function DataReaderMathCos(model, writer, name) {
  9017. sup(this, model, writer, name);
  9018. this.setXArea(-10, 10, 100);
  9019. }
  9020. ClassExtend(DataReaderMathCos, DataReaderMath);
  9021. DataReaderMathCos.prototype.getData = function() {
  9022. if (this.number <= 0 || this.start == this.end) {
  9023. return { x: [], y: [] };
  9024. }
  9025. var y = [];
  9026. var x = this.data.x;
  9027. for (var i = 0; i < x.length; i++) {
  9028. y.push(Math.cos(x[i]));
  9029. }
  9030. this.lastdata = y[0];
  9031. this.data.y = y;
  9032. return this.data;
  9033. }
  9034. function DataReaderMathSin(model, writer, name) {
  9035. sup(this, model, writer, name);
  9036. this.setXArea(-10, 10, 100);
  9037. }
  9038. ClassExtend(DataReaderMathSin, DataReaderMath);
  9039. DataReaderMathSin.prototype.getData = function() {
  9040. if (this.number <= 0 || this.start == this.end) {
  9041. return { x: [], y: [] };
  9042. }
  9043. var x = this.data.x;
  9044. var y = [];
  9045. for (var i = 0; i < x.length; i++) {
  9046. y.push(Math.sin(x[i]));
  9047. }
  9048. this.lastdata = y[0];
  9049. this.data.y = y;
  9050. return this.data;
  9051. }
  9052. function DataReaderIndicatorsBolling(model, writer, name) {
  9053. sup(this, model, writer, name);
  9054. this.nPeriod = 12;
  9055. this.nDev = 2;
  9056. this.vlast = [0, 0, 0];
  9057. }
  9058. ClassExtend(DataReaderIndicatorsBolling, DataReaderIndicators);
  9059. DataReaderIndicatorsBolling.prototype.setParam = function(param) {
  9060. //这个函数里面做一定的初始化工作。特别是shift
  9061. this.param = param;
  9062. n = param[1].split(",");
  9063. this.nPeriod = parseInt(n[0]);
  9064. this.nDev = parseInt(n[1]);
  9065. this.shift = this.nPeriod;
  9066. }
  9067. DataReaderIndicatorsBolling.prototype.getData = function() {
  9068. var mx = this.model.maindata.x;
  9069. var my = this.model.maindata.y
  9070. if (mx.length < this.nPeriod) {
  9071. return { x: [], y: [] };
  9072. }
  9073. var sum = 0;
  9074. for (var i = 0; i < this.nPeriod; i++) {
  9075. sum += my[i][Data.CLOSE];
  9076. }
  9077. var avg = [];
  9078. var matime = [];
  9079. var sma = 0.0,
  9080. dev = 0.0;
  9081. sma = sum / this.nPeriod;
  9082. for (var i = 0; i < this.nPeriod; i++) {
  9083. dev += Math.pow((my[i][Data.CLOSE] - sma), 2);
  9084. }
  9085. dev = Math.sqrt(dev / this.nPeriod);
  9086. avg.push([sma, (sma + this.nDev * dev), (sma - this.nDev * dev)]);
  9087. matime.push(mx[0]);
  9088. for (var i = 1; i <= (mx.length - this.nPeriod) && i < this.model.plotnum; i++) {
  9089. sum -= my[i - 1][Data.CLOSE];
  9090. sum += my[i + this.nPeriod - 1][Data.CLOSE];
  9091. sma = sum / this.nPeriod;
  9092. dev = 0;
  9093. for (var j = 0; j < this.nPeriod; j++) {
  9094. dev += Math.pow((my[i + j][Data.CLOSE] - sma), 2);
  9095. }
  9096. dev = Math.sqrt(dev / this.nPeriod);
  9097. avg.push([sma, (sma + this.nDev * dev), (sma - this.nDev * dev)]);
  9098. matime.push(mx[i]);
  9099. }
  9100. this.vlast = [sma, (sma + this.nDev * dev), (sma - this.nDev * dev)];
  9101. return { x: matime, y: avg };
  9102. }
  9103. DataReaderIndicatorsBolling.prototype.last = function() {
  9104. return this.vlast;
  9105. }
  9106. function DataReaderIndicatorsDWPR(model, writer, name) {
  9107. sup(this, model, writer, name);
  9108. }
  9109. ClassExtend(DataReaderIndicatorsDWPR, DataReaderIndicators);
  9110. //对指标,数据部分由
  9111. DataReaderIndicatorsDWPR.prototype.setN = function(n) {
  9112. this.n = parseInt(n);
  9113. this.shift = parseInt(n);
  9114. }
  9115. DataReaderIndicatorsDWPR.prototype.setParam = function(param) {
  9116. //这个函数里面做一定的初始化工作。特别是shift
  9117. this.param = param;
  9118. this.n = param[1].split(",");
  9119. this.n[0] = parseInt(this.n[0]);
  9120. this.n[1] = parseInt(this.n[1]);
  9121. this.reffer = this.param[0];
  9122. this.shift = Math.max(this.n[0], this.n[1]);
  9123. }
  9124. DataReaderIndicatorsDWPR.prototype.getData = function() {
  9125. //
  9126. if (!this.dataInit(this.reffer[0])) {
  9127. return { x: [], y: [] };
  9128. }
  9129. var data1 = this.wpr(this.n[0]);
  9130. if (!this.dataInit(this.reffer[1])) {
  9131. return { x: [], y: [] };
  9132. }
  9133. var data2 = this.wpr(this.n[1]);
  9134. if (data1.length != data2.length) {
  9135. return { x: [], y: [] };
  9136. }
  9137. var data = [];
  9138. for (var i = 0; i < data1.length; i++) {
  9139. data[i] = data1[i] - data2[i];
  9140. }
  9141. this.lastdata = data[0];
  9142. return { x: this.x, y: data };
  9143. }
  9144. function DataReaderIndicatorsKDJ(model, writer, name) {
  9145. sup(this, model, writer, name);
  9146. this.nPeriod = 9;
  9147. this.factor_1 = 2.0 / 3.0;
  9148. this.factor_2 = 1.0 / 3.0;
  9149. this.vlast = [0, 0, 0];
  9150. }
  9151. ClassExtend(DataReaderIndicatorsKDJ, DataReaderIndicators);
  9152. DataReaderIndicatorsKDJ.prototype.setParam = function(param) {
  9153. //这个函数里面做一定的初始化工作。特别是shift
  9154. this.param = param;
  9155. n = param[1].split(",");
  9156. this.nPeriod = parseInt(n[0]);
  9157. this.shift = this.nPeriod;
  9158. }
  9159. DataReaderIndicatorsKDJ.prototype.getData = function() {
  9160. var mx = this.model.maindata.x.reverse();
  9161. var my = this.model.maindata.y.reverse();
  9162. if (mx.length < this.nPeriod) {
  9163. return { x: [], y: [] };
  9164. }
  9165. var k, d, j, rsv;
  9166. var yvalue = [];
  9167. var matime = [];
  9168. var cn, ln, hn;
  9169. var kpre = 50;
  9170. var dpre = 50;
  9171. for (i = this.nPeriod - 1; i < mx.length; i++) {
  9172. ln = Infinity;
  9173. hn = -Infinity;
  9174. cn = my[i][Data.CLOSE];
  9175. for (j = 0; j < this.nPeriod; j++) {
  9176. if (ln > my[i - j][Data.LOW]) {
  9177. ln = my[i - j][Data.LOW];
  9178. }
  9179. if (hn < my[i - j][Data.HIGH]) {
  9180. hn = my[i - j][Data.HIGH];
  9181. }
  9182. }
  9183. if ((hn - ln) == 0) {
  9184. rsv = 50;
  9185. } else {
  9186. rsv = (cn - ln) / (hn - ln) * 100;
  9187. }
  9188. k = this.factor_1 * kpre + this.factor_2 * rsv;
  9189. d = this.factor_1 * dpre + this.factor_2 * k;
  9190. j = 3 * d - 2 * k;
  9191. kpre = k;
  9192. dpre = d;
  9193. yvalue.push([k, d, j]);
  9194. matime.push(mx[i]);
  9195. }
  9196. matime = matime.reverse();
  9197. yvalue = yvalue.reverse();
  9198. this.vlast = [k, d, j];
  9199. return { x: matime, y: yvalue };
  9200. }
  9201. DataReaderIndicatorsKDJ.prototype.last = function() {
  9202. return this.vlast;
  9203. }
  9204. function DataReaderIndicatorsMa(model, writer, name) {
  9205. sup(this, model, writer, name);
  9206. }
  9207. ClassExtend(DataReaderIndicatorsMa, DataReaderIndicators);
  9208. //对指标,数据部分由
  9209. DataReaderIndicatorsMa.prototype.setN = function(n) {
  9210. this.n = parseInt(n);
  9211. this.shift = parseInt(n);
  9212. }
  9213. DataReaderIndicatorsMa.prototype.setParam = function(param) {
  9214. //这个函数里面做一定的初始化工作。特别是shift
  9215. this.param = param;
  9216. this.setN(this.param[1]);
  9217. }
  9218. DataReaderIndicatorsMa.prototype.getData = function() {
  9219. var mx = this.model.maindata.x;
  9220. var my = this.model.maindata.y
  9221. if (mx.length < this.n) {
  9222. return { x: [], y: [] };
  9223. }
  9224. var sum = 0;
  9225. //---- initial accumulation
  9226. //移动平均线的做法:前n个平均数目,那可以从 0 遍历到 length - this.n
  9227. //和一般求解指标不同,我这里采用倒过来求解的办法
  9228. //先初始化平均值
  9229. for (var i = 0; i < this.n; i++) {
  9230. sum += my[i][Data.CLOSE];
  9231. }
  9232. var avg = [];
  9233. var matime = [];
  9234. avg.push(sum / this.n);
  9235. matime.push(mx[0]);
  9236. for (var i = 1; i <= (mx.length - this.n) && i < this.model.plotnum; i++) {
  9237. sum -= my[i - 1][Data.CLOSE];
  9238. sum += my[i + this.n - 1][Data.CLOSE];
  9239. avg.push(sum / this.n);
  9240. matime.push(mx[i]);
  9241. }
  9242. //后面为空的补零,这样和时间才能对齐。
  9243. /*for (var i = 0; i < this.n; i++)
  9244. {
  9245. avg.push(0);
  9246. }*/
  9247. this.lastdata = avg[0];
  9248. return { x: matime, y: avg };
  9249. }
  9250. function DataReaderIndicatorsMacd(model, writer, name) {
  9251. sup(this, model, writer, name);
  9252. this.nFastPeriod = 12;
  9253. this.nSlowPeriod = 26;
  9254. this.nSignalPeriod = 9;
  9255. this.vlast = [0, 0];
  9256. }
  9257. ClassExtend(DataReaderIndicatorsMacd, DataReaderIndicators);
  9258. DataReaderIndicatorsMacd.prototype.setParam = function(param) {
  9259. //这个函数里面做一定的初始化工作。特别是shift
  9260. this.param = param;
  9261. n = param[1].split(",");
  9262. this.nFastPeriod = parseInt(n[0]);
  9263. this.nSlowPeriod = parseInt(n[1]);
  9264. if (this.nFastPeriod > this.nSlowPeriod) {
  9265. nTmp = this.nFastPeriod;
  9266. this.nFastPeriod = this.nSlowPeriod;
  9267. this.nSlowPeriod = nTmp;
  9268. }
  9269. this.nSignalPeriod = parseInt(n[2]);
  9270. this.shift = this.nSlowPeriod + this.nSignalPeriod;
  9271. }
  9272. DataReaderIndicatorsMacd.prototype.getData = function() {
  9273. var mx = this.model.maindata.x;
  9274. var my = this.model.maindata.y
  9275. if (mx.length < this.shift) {
  9276. return { x: [], y: [] };
  9277. }
  9278. var sumfast = 0.0;
  9279. for (var i = 1; i <= this.nFastPeriod; i++) {
  9280. sumfast += my[mx.length - i][Data.CLOSE];
  9281. }
  9282. var sumslow = sumfast;
  9283. var vfast = sumfast / this.nFastPeriod;
  9284. var prfast = 2.0 / (this.nFastPeriod + 1.0);
  9285. for (var i = this.nFastPeriod + 1; i <= this.nSlowPeriod; i++) {
  9286. sumslow += my[mx.length - i][Data.CLOSE];
  9287. vfast = vfast * (1 - prfast) + prfast * my[mx.length - i][Data.CLOSE];
  9288. }
  9289. var vslow = sumslow / this.nSlowPeriod;
  9290. var prslow = 2.0 / (this.nSlowPeriod + 1.0);
  9291. var matime = [];
  9292. var macdy = [];
  9293. matime.push(mx[mx.length - this.nSlowPeriod]);
  9294. macdy.push([vfast - vslow, NaN]);
  9295. var summacd = vfast - vslow;
  9296. for (var i = this.nSlowPeriod + 1; i < this.nSlowPeriod + this.nSignalPeriod; i++) {
  9297. vfast = vfast * (1 - prfast) + prfast * my[mx.length - i][Data.CLOSE];
  9298. vslow = vslow * (1 - prslow) + prslow * my[mx.length - i][Data.CLOSE];
  9299. summacd += vfast - vslow;
  9300. matime.push(mx[mx.length - i]);
  9301. if (i < (this.nSlowPeriod + this.nSignalPeriod - 1)) {
  9302. macdy.push([vfast - vslow, NaN]);
  9303. } else {
  9304. macdy.push([vfast - vslow, summacd / this.nSignalPeriod]);
  9305. }
  9306. }
  9307. for (var i = this.nSlowPeriod + this.nSignalPeriod; i <= mx.length; i++) {
  9308. vfast = vfast * (1 - prfast) + prfast * my[mx.length - i][Data.CLOSE];
  9309. vslow = vslow * (1 - prslow) + prslow * my[mx.length - i][Data.CLOSE];
  9310. summacd += vfast - vslow;
  9311. summacd -= macdy[macdy.length - this.nSignalPeriod][0];
  9312. matime.push(mx[mx.length - i]);
  9313. macdy.push([vfast - vslow, summacd / this.nSignalPeriod]);
  9314. }
  9315. this.vlast = [vfast - vslow, summacd / this.nSignalPeriod]
  9316. return { x: matime, y: macdy };
  9317. }
  9318. DataReaderIndicatorsMacd.prototype.last = function() {
  9319. return this.vlast;
  9320. }
  9321. // DataReaderIndicatorsMacd.prototype.getYminmax = function(y) {
  9322. // var ymax = -Infinity;
  9323. // var ymin = Infinity;
  9324. // if (!y) {
  9325. // return [ymin, ymax];
  9326. // }
  9327. // for (var i = 1; i <= y.length && i <= this.model.plotnum; i++) {
  9328. // for (var j = 0; j < y[y.length - i].length; j++) {
  9329. // var value = y[y.length - i][j];
  9330. // if (!isNaN(value)) {
  9331. // if (value > ymax) {
  9332. // ymax = value;
  9333. // }
  9334. // if (value < ymin) {
  9335. // ymin = value;
  9336. // }
  9337. // }
  9338. // }
  9339. // }
  9340. // return [ymin, ymax];
  9341. // }
  9342. DataReaderIndicatorsMacd.prototype.getYminmax = function(y) {
  9343. var ymax = -Infinity;
  9344. var maxIndex=0;
  9345. var minIndex=0;
  9346. var ymin = Infinity;
  9347. if (!y) {
  9348. return [ymin, ymax,minIndex,maxIndex];
  9349. }
  9350. for (var i = 1; i <= y.length && i <= this.model.plotnum; i++) {
  9351. for (var j = 0; j < y[y.length - i].length; j++) {
  9352. var value = y[y.length - i][j];
  9353. if (!isNaN(value)) {
  9354. if (value > ymax) {
  9355. maxIndex=i;
  9356. ymax = value;
  9357. }
  9358. if (value < ymin) {
  9359. minIndex=i;
  9360. ymin = value;
  9361. }
  9362. }
  9363. }
  9364. }
  9365. return [ymin, ymax,minIndex,maxIndex];
  9366. }
  9367. function DataReaderIndicatorsMaTrend(model, writer, name) {
  9368. sup(this, model, writer, name);
  9369. }
  9370. ClassExtend(DataReaderIndicatorsMaTrend, DataReaderIndicators);
  9371. DataReaderIndicatorsMaTrend.prototype.setParam = function(param) {
  9372. //这个函数里面做一定的初始化工作。特别是shift
  9373. this.param = param;
  9374. this.n = param[1].split(",");
  9375. for (var i = 0; i < this.n.length; i++) {
  9376. this.n[i] = parseInt(this.n[i]);
  9377. }
  9378. this.n = this.n.sort(function(a, b) {
  9379. return a - b
  9380. });
  9381. this.reffer = this.param[0];
  9382. this.shift = Math.max.apply(this, this.n);
  9383. }
  9384. DataReaderIndicatorsMaTrend.prototype.getData = function() {
  9385. var ma = [];
  9386. var trend = [];
  9387. if (!this.dataInit()) {
  9388. return { x: [], y: [] };
  9389. }
  9390. for (var i = 0; i < this.n.length; i++) {
  9391. // alert(this.n[i]);
  9392. ma[i] = this.ma(this.n[i]);
  9393. }
  9394. var num, delt;
  9395. for (var i = 0; i < this.y.length - 1; i++) {
  9396. num = 0;
  9397. delt = 0;
  9398. for (var j = 0; j < this.n.length; j++) {
  9399. if (ma[j][i] > ma[j][i + 1]) {
  9400. num++;
  9401. } else if (ma[j][i] < ma[j][i + 1]) {
  9402. num--;
  9403. }
  9404. delt++;
  9405. for (var k = j + 1; k < this.n.length; k++) {
  9406. if (ma[j][i] > ma[k][i]) {
  9407. num++;
  9408. } else if (ma[j][i] < ma[k][i]) {
  9409. num--;
  9410. }
  9411. delt++;
  9412. }
  9413. }
  9414. num = num / delt;
  9415. trend[i] = num;
  9416. }
  9417. trend[this.y.length - 1] = 0;
  9418. this.lastdata = trend[0];
  9419. return { x: this.x, y: trend };
  9420. }
  9421. function DataReaderIndicatorsRSI(model, writer, name) {
  9422. sup(this, model, writer, name);
  9423. }
  9424. ClassExtend(DataReaderIndicatorsRSI, DataReaderIndicators);
  9425. //对指标,数据部分由
  9426. DataReaderIndicatorsRSI.prototype.setN = function(n) {
  9427. this.n = parseInt(n);
  9428. this.shift = parseInt(n);
  9429. }
  9430. DataReaderIndicatorsRSI.prototype.setParam = function(param) {
  9431. //这个函数里面做一定的初始化工作。特别是shift
  9432. this.param = param;
  9433. this.reffer = this.param[0];
  9434. this.setN(param[1]);
  9435. }
  9436. DataReaderIndicatorsRSI.prototype.empty = function() {
  9437. return {
  9438. x: [],
  9439. y: []
  9440. };
  9441. }
  9442. DataReaderIndicatorsRSI.prototype.getData = function() {
  9443. if (!this.dataInit(this.reffer[1])) {
  9444. return this.empty();
  9445. }
  9446. var K = this.strength(this.n);
  9447. if (!this.dataInit(this.reffer[0])) {
  9448. return this.empty();
  9449. }
  9450. var E = this.strength(this.n);
  9451. if (K.length != E.length) {
  9452. return this.empty();
  9453. }
  9454. var H = [];
  9455. for (var i = 0; i < K.length; i++) {
  9456. H[i] = (K[i] - E[i] + 200) / 4;
  9457. }
  9458. this.lastdata = H[0];
  9459. return { x: this.x, y: H };
  9460. }
  9461. function DataReaderIndicatorsWPR(model, writer, name) {
  9462. sup(this, model, writer, name);
  9463. }
  9464. ClassExtend(DataReaderIndicatorsWPR, DataReaderIndicators);
  9465. //对指标,数据部分由
  9466. DataReaderIndicatorsWPR.prototype.setN = function(n) {
  9467. this.n = parseInt(n);
  9468. this.shift = parseInt(n);
  9469. }
  9470. DataReaderIndicatorsWPR.prototype.setParam = function(param) {
  9471. //这个函数里面做一定的初始化工作。特别是shift
  9472. this.param = param;
  9473. this.setN(this.param[1]);
  9474. }
  9475. DataReaderIndicatorsWPR.prototype.getData = function() {
  9476. if (!this.dataInit()) {
  9477. return { x: [], y: [] };
  9478. }
  9479. var data = this.wpr(this.n);
  9480. this.lastdata = data[0];
  9481. return { x: this.x, y: data };
  9482. }
  9483. function html5chart(api,type,period) {
  9484. if (type&&period) {
  9485. $('#'+type.toLowerCase()).addClass('active');
  9486. //$.clearCookie();
  9487. api.initPair(type, period);
  9488. $.cookie('symbol', type);
  9489. $.cookie('period',period);
  9490. // $.cookie('period',period);
  9491. // var indstr="main:ma|main|5|color=black:ma|main|10|color=yellow:ma|main|20|color=red:ma|main|30|color=green:";
  9492. // api.setInd(indstr);
  9493. api.initInd('MAC');
  9494. // console.log($('li[name="ETH"]'));
  9495. } else {
  9496. $.cookie('symbol', 'BCCBTC');
  9497. $.cookie('period', 'H1');
  9498. // sessionStorage.setItem('period','H1');
  9499. api.initPair('BCCBTC', "H1");
  9500. api.initInd('MAC');
  9501. }
  9502. return;
  9503. }