| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668 | /*! * ==================================================== * kityminder-editor - v1.0.67 - 2022-05-25 * https://github.com/fex-team/kityminder-editor * GitHub: https://github.com/fex-team/kityminder-editor  * Copyright (c) 2022 ; Licensed  * ==================================================== */(function () {var _p = {    r: function(index) {        if (_p[index].inited) {            return _p[index].value;        }        if (typeof _p[index].value === "function") {            var module = {                exports: {}            }, returnValue = _p[index].value(null, module.exports, module);            _p[index].inited = true;            _p[index].value = returnValue;            if (returnValue !== undefined) {                return returnValue;            } else {                for (var key in module.exports) {                    if (module.exports.hasOwnProperty(key)) {                        _p[index].inited = true;                        _p[index].value = module.exports;                        return module.exports;                    }                }            }        } else {            _p[index].inited = true;            return _p[index].value;        }    }};//src/editor.js_p[0] = {    value: function(require, exports, module) {        /**     * 运行时     */        var runtimes = [];        function assemble(runtime) {            runtimes.push(runtime);        }        function KMEditor(selector) {            this.selector = selector;            for (var i = 0; i < runtimes.length; i++) {                if (typeof runtimes[i] == "function") {                    runtimes[i].call(this, this);                }            }        }        KMEditor.assemble = assemble;        assemble(_p.r(7));        assemble(_p.r(9));        assemble(_p.r(14));        assemble(_p.r(18));        assemble(_p.r(11));        assemble(_p.r(12));        assemble(_p.r(5));        assemble(_p.r(6));        assemble(_p.r(8));        assemble(_p.r(15));        assemble(_p.r(10));        assemble(_p.r(13));        assemble(_p.r(16));        assemble(_p.r(17));        return module.exports = KMEditor;    }};//src/expose-editor.js/** * @fileOverview * * 打包暴露 * * @author: techird * @copyright: Baidu FEX, 2014 */_p[1] = {    value: function(require, exports, module) {        return module.exports = kityminder.Editor = _p.r(0);    }};//src/hotbox.js_p[2] = {    value: function(require, exports, module) {        return module.exports = window.HotBox;    }};//src/lang.js_p[3] = {    value: function(require, exports, module) {}};//src/minder.js_p[4] = {    value: function(require, exports, module) {        return module.exports = window.kityminder.Minder;    }};//src/runtime/clipboard-mimetype.js/** * @Desc: 新增一个用于处理系统ctrl+c ctrl+v等方式导入导出节点的MIMETYPE处理,如系统不支持clipboardEvent或者是FF则不初始化改class * @Editor: Naixor * @Date: 2015.9.21 */_p[5] = {    value: function(require, exports, module) {        function MimeType() {            /**		 * 私有变量		 */            var SPLITOR = "\ufeff";            var MIMETYPE = {                "application/km": ""            };            var SIGN = {                "\ufeff": "SPLITOR",                "": "application/km"            };            /**		 * 用于将一段纯文本封装成符合其数据格式的文本		 * @method process 			private		 * @param  {MIMETYPE} mimetype 数据格式		 * @param  {String} text     原始文本		 * @return {String}          符合该数据格式下的文本		 * @example		 * 			var str = "123";		 * 			str = process('application/km', str); // 返回的内容再经过MimeType判断会读取出其数据格式为application/km		 * 			process('text/plain', str); // 若接受到一个非纯文本信息,则会将其转换为新的数据格式		 */            function process(mimetype, text) {                if (!this.isPureText(text)) {                    var _mimetype = this.whichMimeType(text);                    if (!_mimetype) {                        throw new Error("unknow mimetype!");                    }                    text = this.getPureText(text);                }                if (mimetype === false) {                    return text;                }                return mimetype + SPLITOR + text;            }            /**		 * 注册数据类型的标识		 * @method registMimeTypeProtocol  	public		 * @param  {String} type 数据类型		 * @param  {String} sign 标识		 */            this.registMimeTypeProtocol = function(type, sign) {                if (sign && SIGN[sign]) {                    throw new Error("sing has registed!");                }                if (type && !!MIMETYPE[type]) {                    throw new Error("mimetype has registed!");                }                SIGN[sign] = type;                MIMETYPE[type] = sign;            };            /**		 * 获取已注册数据类型的协议		 * @method getMimeTypeProtocol  	public		 * @param  {String} type 数据类型		 * @param  {String} text|undefiend  文本内容或不传入		 * @return {String|Function} 		 * @example 		 * 			text若不传入则直接返回对应数据格式的处理(process)方法		 * 			若传入文本则直接调用对应的process方法进行处理,此时返回处理后的内容		 * 			var m = new MimeType();		 * 			var kmprocess = m.getMimeTypeProtocol('application/km');		 * 			kmprocess("123") === m.getMimeTypeProtocol('application/km', "123");		 * 					 */            this.getMimeTypeProtocol = function(type, text) {                var mimetype = MIMETYPE[type] || false;                if (text === undefined) {                    return process.bind(this, mimetype);                }                return process(mimetype, text);            };            this.getSpitor = function() {                return SPLITOR;            };            this.getMimeType = function(sign) {                if (sign !== undefined) {                    return SIGN[sign] || null;                }                return MIMETYPE;            };        }        MimeType.prototype.isPureText = function(text) {            return !~text.indexOf(this.getSpitor());        };        MimeType.prototype.getPureText = function(text) {            if (this.isPureText(text)) {                return text;            }            return text.split(this.getSpitor())[1];        };        MimeType.prototype.whichMimeType = function(text) {            if (this.isPureText(text)) {                return null;            }            return this.getMimeType(text.split(this.getSpitor())[0]);        };        function MimeTypeRuntime() {            if (this.minder.supportClipboardEvent && !kity.Browser.gecko) {                this.MimeType = new MimeType();            }        }        return module.exports = MimeTypeRuntime;    }};//src/runtime/clipboard.js/** * @Desc: 处理editor的clipboard事件,只在支持ClipboardEvent并且不是FF的情况下工作 * @Editor: Naixor * @Date: 2015.9.21 */_p[6] = {    value: function(require, exports, module) {        function ClipboardRuntime() {            var minder = this.minder;            var Data = window.kityminder.data;            if (!minder.supportClipboardEvent || kity.Browser.gecko) {                return;            }            var fsm = this.fsm;            var receiver = this.receiver;            var MimeType = this.MimeType;            var kmencode = MimeType.getMimeTypeProtocol("application/km"), decode = Data.getRegisterProtocol("json").decode;            var _selectedNodes = [];            /*		 * 增加对多节点赋值粘贴的处理		 */            function encode(nodes) {                var _nodes = [];                for (var i = 0, l = nodes.length; i < l; i++) {                    _nodes.push(minder.exportNode(nodes[i]));                }                return kmencode(Data.getRegisterProtocol("json").encode(_nodes));            }            var beforeCopy = function(e) {                if (document.activeElement == receiver.element) {                    var clipBoardEvent = e;                    var state = fsm.state();                    switch (state) {                      case "input":                        {                            break;                        }                      case "normal":                        {                            var nodes = [].concat(minder.getSelectedNodes());                            if (nodes.length) {                                // 这里由于被粘贴复制的节点的id信息也都一样,故做此算法                                // 这里有个疑问,使用node.getParent()或者node.parent会离奇导致出现非选中节点被渲染成选中节点,因此使用isAncestorOf,而没有使用自行回溯的方式                                if (nodes.length > 1) {                                    var targetLevel;                                    nodes.sort(function(a, b) {                                        return a.getLevel() - b.getLevel();                                    });                                    targetLevel = nodes[0].getLevel();                                    if (targetLevel !== nodes[nodes.length - 1].getLevel()) {                                        var plevel, pnode, idx = 0, l = nodes.length, pidx = l - 1;                                        pnode = nodes[pidx];                                        while (pnode.getLevel() !== targetLevel) {                                            idx = 0;                                            while (idx < l && nodes[idx].getLevel() === targetLevel) {                                                if (nodes[idx].isAncestorOf(pnode)) {                                                    nodes.splice(pidx, 1);                                                    break;                                                }                                                idx++;                                            }                                            pidx--;                                            pnode = nodes[pidx];                                        }                                    }                                }                                var str = encode(nodes);                                clipBoardEvent.clipboardData.setData("text/plain", str);                            }                            e.preventDefault();                            break;                        }                    }                }            };            var beforeCut = function(e) {                if (document.activeElement == receiver.element) {                    if (minder.getStatus() !== "normal") {                        e.preventDefault();                        return;                    }                    var clipBoardEvent = e;                    var state = fsm.state();                    switch (state) {                      case "input":                        {                            break;                        }                      case "normal":                        {                            var nodes = minder.getSelectedNodes();                            if (nodes.length) {                                clipBoardEvent.clipboardData.setData("text/plain", encode(nodes));                                minder.execCommand("removenode");                            }                            e.preventDefault();                            break;                        }                    }                }            };            var beforePaste = function(e) {                if (document.activeElement == receiver.element) {                    if (minder.getStatus() !== "normal") {                        e.preventDefault();                        return;                    }                    var clipBoardEvent = e;                    var state = fsm.state();                    var textData = clipBoardEvent.clipboardData.getData("text/plain");                    switch (state) {                      case "input":                        {                            // input状态下如果格式为application/km则不进行paste操作                            if (!MimeType.isPureText(textData)) {                                e.preventDefault();                                return;                            }                            break;                        }                      case "normal":                        {                            /*						 * 针对normal状态下通过对选中节点粘贴导入子节点文本进行单独处理						 */                            var sNodes = minder.getSelectedNodes();                            if (MimeType.whichMimeType(textData) === "application/km") {                                var nodes = decode(MimeType.getPureText(textData));                                var _node;                                sNodes.forEach(function(node) {                                    // 由于粘贴逻辑中为了排除子节点重新排序导致逆序,因此复制的时候倒过来                                    for (var i = nodes.length - 1; i >= 0; i--) {                                        _node = minder.createNode(null, node);                                        minder.importNode(_node, nodes[i]);                                        _selectedNodes.push(_node);                                        node.appendChild(_node);                                    }                                });                                minder.select(_selectedNodes, true);                                _selectedNodes = [];                                minder.refresh();                            } else if (clipBoardEvent.clipboardData && clipBoardEvent.clipboardData.items[0].type.indexOf("image") > -1) {                                var imageFile = clipBoardEvent.clipboardData.items[0].getAsFile();                                var serverService = angular.element(document.body).injector().get("server");                                return serverService.uploadImage(imageFile).then(function(json) {                                    var resp = json.data;                                    if (resp.errno === 0) {                                        minder.execCommand("image", resp.data.url);                                    }                                });                            } else {                                sNodes.forEach(function(node) {                                    minder.Text2Children(node, textData);                                });                            }                            e.preventDefault();                            break;                        }                    }                }            };            /**		 * 由editor的receiver统一处理全部事件,包括clipboard事件		 * @Editor: Naixor		 * @Date: 2015.9.24		 */            document.addEventListener("copy", beforeCopy);            document.addEventListener("cut", beforeCut);            document.addEventListener("paste", beforePaste);        }        return module.exports = ClipboardRuntime;    }};//src/runtime/container.js/** * @fileOverview * * 初始化编辑器的容器 * * @author: techird * @copyright: Baidu FEX, 2014 */_p[7] = {    value: function(require, exports, module) {        /**     * 最先执行的 Runtime,初始化编辑器容器     */        function ContainerRuntime() {            var container;            if (typeof this.selector == "string") {                container = document.querySelector(this.selector);            } else {                container = this.selector;            }            if (!container) throw new Error("Invalid selector: " + this.selector);            // 这个类名用于给编辑器添加样式            container.classList.add("km-editor");            // 暴露容器给其他运行时使用            this.container = container;        }        return module.exports = ContainerRuntime;    }};//src/runtime/drag.js/** * @fileOverview * * 用于拖拽节点时屏蔽键盘事件 * * @author: techird * @copyright: Baidu FEX, 2014 */_p[8] = {    value: function(require, exports, module) {        var Hotbox = _p.r(2);        var Debug = _p.r(19);        var debug = new Debug("drag");        function DragRuntime() {            var fsm = this.fsm;            var minder = this.minder;            var hotbox = this.hotbox;            var receiver = this.receiver;            var receiverElement = receiver.element;            // setup everything to go            setupFsm();            // listen the fsm changes, make action.            function setupFsm() {                // when jumped to drag mode, enter                fsm.when("* -> drag", function() {});                fsm.when("drag -> *", function(exit, enter, reason) {                    if (reason == "drag-finish") {}                });            }            var downX, downY;            var MOUSE_HAS_DOWN = 0;            var MOUSE_HAS_UP = 1;            var BOUND_CHECK = 20;            var flag = MOUSE_HAS_UP;            var maxX, maxY, osx, osy, containerY;            var freeHorizen = false, freeVirtical = false;            var frame;            function move(direction, speed) {                if (!direction) {                    freeHorizen = freeVirtical = false;                    frame && kity.releaseFrame(frame);                    frame = null;                    return;                }                if (!frame) {                    frame = kity.requestFrame(function(direction, speed, minder) {                        return function(frame) {                            switch (direction) {                              case "left":                                minder._viewDragger.move({                                    x: -speed,                                    y: 0                                }, 0);                                break;                              case "top":                                minder._viewDragger.move({                                    x: 0,                                    y: -speed                                }, 0);                                break;                              case "right":                                minder._viewDragger.move({                                    x: speed,                                    y: 0                                }, 0);                                break;                              case "bottom":                                minder._viewDragger.move({                                    x: 0,                                    y: speed                                }, 0);                                break;                              default:                                return;                            }                            frame.next();                        };                    }(direction, speed, minder));                }            }            minder.on("mousedown", function(e) {                flag = MOUSE_HAS_DOWN;                var rect = minder.getPaper().container.getBoundingClientRect();                downX = e.originEvent.clientX;                downY = e.originEvent.clientY;                containerY = rect.top;                maxX = rect.width;                maxY = rect.height;            });            minder.on("mousemove", function(e) {                if (fsm.state() === "drag" && flag == MOUSE_HAS_DOWN && minder.getSelectedNode() && (Math.abs(downX - e.originEvent.clientX) > BOUND_CHECK || Math.abs(downY - e.originEvent.clientY) > BOUND_CHECK)) {                    osx = e.originEvent.clientX;                    osy = e.originEvent.clientY - containerY;                    if (osx < BOUND_CHECK) {                        move("right", BOUND_CHECK - osx);                    } else if (osx > maxX - BOUND_CHECK) {                        move("left", BOUND_CHECK + osx - maxX);                    } else {                        freeHorizen = true;                    }                    if (osy < BOUND_CHECK) {                        move("bottom", osy);                    } else if (osy > maxY - BOUND_CHECK) {                        move("top", BOUND_CHECK + osy - maxY);                    } else {                        freeVirtical = true;                    }                    if (freeHorizen && freeVirtical) {                        move(false);                    }                }                if (fsm.state() !== "drag" && flag === MOUSE_HAS_DOWN && minder.getSelectedNode() && (Math.abs(downX - e.originEvent.clientX) > BOUND_CHECK || Math.abs(downY - e.originEvent.clientY) > BOUND_CHECK)) {                    if (fsm.state() === "hotbox") {                        hotbox.active(Hotbox.STATE_IDLE);                    }                    return fsm.jump("drag", "user-drag");                }            });            window.addEventListener("mouseup", function() {                flag = MOUSE_HAS_UP;                if (fsm.state() === "drag") {                    move(false);                    return fsm.jump("normal", "drag-finish");                }            }, false);        }        return module.exports = DragRuntime;    }};//src/runtime/fsm.js/** * @fileOverview * * 编辑器状态机 * * @author: techird * @copyright: Baidu FEX, 2014 */_p[9] = {    value: function(require, exports, module) {        var Debug = _p.r(19);        var debug = new Debug("fsm");        function handlerConditionMatch(condition, when, exit, enter) {            if (condition.when != when) return false;            if (condition.enter != "*" && condition.enter != enter) return false;            if (condition.exit != "*" && condition.exit != exit) return;            return true;        }        function FSM(defaultState) {            var currentState = defaultState;            var BEFORE_ARROW = " - ";            var AFTER_ARROW = " -> ";            var handlers = [];            /**         * 状态跳转         *         * 会通知所有的状态跳转监视器         *         * @param  {string} newState  新状态名称         * @param  {any} reason 跳转的原因,可以作为参数传递给跳转监视器         */            this.jump = function(newState, reason) {                if (!reason) throw new Error("Please tell fsm the reason to jump");                var oldState = currentState;                var notify = [ oldState, newState ].concat([].slice.call(arguments, 1));                var i, handler;                // 跳转前                for (i = 0; i < handlers.length; i++) {                    handler = handlers[i];                    if (handlerConditionMatch(handler.condition, "before", oldState, newState)) {                        if (handler.apply(null, notify)) return;                    }                }                currentState = newState;                debug.log("[{0}] {1} -> {2}", reason, oldState, newState);                // 跳转后                for (i = 0; i < handlers.length; i++) {                    handler = handlers[i];                    if (handlerConditionMatch(handler.condition, "after", oldState, newState)) {                        handler.apply(null, notify);                    }                }                return currentState;            };            /**         * 返回当前状态         * @return {string}         */            this.state = function() {                return currentState;            };            /**         * 添加状态跳转监视器         *          * @param {string} condition         *     监视的时机         *         "* => *" (默认)         *         * @param  {Function} handler         *     监视函数,当状态跳转的时候,会接收三个参数         *         * from - 跳转前的状态         *         * to - 跳转后的状态         *         * reason - 跳转的原因         */            this.when = function(condition, handler) {                if (arguments.length == 1) {                    handler = condition;                    condition = "* -> *";                }                var when, resolved, exit, enter;                resolved = condition.split(BEFORE_ARROW);                if (resolved.length == 2) {                    when = "before";                } else {                    resolved = condition.split(AFTER_ARROW);                    if (resolved.length == 2) {                        when = "after";                    }                }                if (!when) throw new Error("Illegal fsm condition: " + condition);                exit = resolved[0];                enter = resolved[1];                handler.condition = {                    when: when,                    exit: exit,                    enter: enter                };                handlers.push(handler);            };        }        function FSMRumtime() {            this.fsm = new FSM("normal");        }        return module.exports = FSMRumtime;    }};//src/runtime/history.js/** * @fileOverview * * 历史管理 * * @author: techird * @copyright: Baidu FEX, 2014 */_p[10] = {    value: function(require, exports, module) {        var jsonDiff = _p.r(22);        function HistoryRuntime() {            var minder = this.minder;            var hotbox = this.hotbox;            var MAX_HISTORY = 100;            var lastSnap;            var patchLock;            var undoDiffs;            var redoDiffs;            function reset() {                undoDiffs = [];                redoDiffs = [];                lastSnap = minder.exportJson();            }            function makeUndoDiff() {                var headSnap = minder.exportJson();                var diff = jsonDiff(headSnap, lastSnap);                if (diff.length) {                    undoDiffs.push(diff);                    while (undoDiffs.length > MAX_HISTORY) {                        undoDiffs.shift();                    }                    lastSnap = headSnap;                    return true;                }            }            function makeRedoDiff() {                var revertSnap = minder.exportJson();                redoDiffs.push(jsonDiff(revertSnap, lastSnap));                lastSnap = revertSnap;            }            function undo() {                patchLock = true;                var undoDiff = undoDiffs.pop();                if (undoDiff) {                    minder.applyPatches(undoDiff);                    makeRedoDiff();                }                patchLock = false;            }            function redo() {                patchLock = true;                var redoDiff = redoDiffs.pop();                if (redoDiff) {                    minder.applyPatches(redoDiff);                    makeUndoDiff();                }                patchLock = false;            }            function changed() {                if (patchLock) return;                if (makeUndoDiff()) redoDiffs = [];            }            function hasUndo() {                return !!undoDiffs.length;            }            function hasRedo() {                return !!redoDiffs.length;            }            function updateSelection(e) {                if (!patchLock) return;                var patch = e.patch;                switch (patch.express) {                  case "node.add":                    minder.select(patch.node.getChild(patch.index), true);                    break;                  case "node.remove":                  case "data.replace":                  case "data.remove":                  case "data.add":                    minder.select(patch.node, true);                    break;                }            }            this.history = {                reset: reset,                undo: undo,                redo: redo,                hasUndo: hasUndo,                hasRedo: hasRedo            };            reset();            minder.on("contentchange", changed);            minder.on("import", reset);            minder.on("patch", updateSelection);            var main = hotbox.state("main");            main.button({                position: "top",                label: "撤销",                key: "Ctrl + Z",                enable: hasUndo,                action: undo,                next: "idle"            });            main.button({                position: "top",                label: "重做",                key: "Ctrl + Y",                enable: hasRedo,                action: redo,                next: "idle"            });        }        window.diff = jsonDiff;        return module.exports = HistoryRuntime;    }};//src/runtime/hotbox.js/** * @fileOverview * * 热盒 Runtime * * @author: techird * @copyright: Baidu FEX, 2014 */_p[11] = {    value: function(require, exports, module) {        var Hotbox = _p.r(2);        function HotboxRuntime() {            var fsm = this.fsm;            var minder = this.minder;            var receiver = this.receiver;            var container = this.container;            var hotbox = new Hotbox(container);            hotbox.setParentFSM(fsm);            fsm.when("normal -> hotbox", function(exit, enter, reason) {                var node = minder.getSelectedNode();                var position;                if (node) {                    var box = node.getRenderBox();                    position = {                        x: box.cx,                        y: box.cy                    };                }                hotbox.active("main", position);            });            fsm.when("normal -> normal", function(exit, enter, reason, e) {                if (reason == "shortcut-handle") {                    var handleResult = hotbox.dispatch(e);                    if (handleResult) {                        e.preventDefault();                    } else {                        minder.dispatchKeyEvent(e);                    }                }            });            fsm.when("modal -> normal", function(exit, enter, reason, e) {                if (reason == "import-text-finish") {                    receiver.element.focus();                }            });            this.hotbox = hotbox;        }        return module.exports = HotboxRuntime;    }};//src/runtime/input.js/** * @fileOverview * * 文本输入支持 * * @author: techird * @copyright: Baidu FEX, 2014 */_p[12] = {    value: function(require, exports, module) {        _p.r(21);        var Debug = _p.r(19);        var debug = new Debug("input");        function InputRuntime() {            var fsm = this.fsm;            var minder = this.minder;            var hotbox = this.hotbox;            var receiver = this.receiver;            var receiverElement = receiver.element;            var isGecko = window.kity.Browser.gecko;            // setup everything to go            setupReciverElement();            setupFsm();            setupHotbox();            // expose editText()            this.editText = editText;            // listen the fsm changes, make action.            function setupFsm() {                // when jumped to input mode, enter                fsm.when("* -> input", enterInputMode);                // when exited, commit or exit depends on the exit reason                fsm.when("input -> *", function(exit, enter, reason) {                    switch (reason) {                      case "input-cancel":                        return exitInputMode();                      case "input-commit":                      default:                        return commitInputResult();                    }                });                // lost focus to commit                receiver.onblur(function(e) {                    if (fsm.state() == "input") {                        fsm.jump("normal", "input-commit");                    }                });                minder.on("beforemousedown", function() {                    if (fsm.state() == "input") {                        fsm.jump("normal", "input-commit");                    }                });                minder.on("dblclick", function() {                    if (minder.getSelectedNode() && minder._status !== "readonly") {                        editText();                    }                });            }            // let the receiver follow the current selected node position            function setupReciverElement() {                if (debug.flaged) {                    receiverElement.classList.add("debug");                }                receiverElement.onmousedown = function(e) {                    e.stopPropagation();                };                minder.on("layoutallfinish viewchange viewchanged selectionchange", function(e) {                    // viewchange event is too frequenced, lazy it                    if (e.type == "viewchange" && fsm.state() != "input") return;                    updatePosition();                });                updatePosition();            }            // edit entrance in hotbox            function setupHotbox() {                hotbox.state("main").button({                    position: "center",                    label: "编辑",                    key: "F2",                    enable: function() {                        return minder.queryCommandState("text") != -1;                    },                    action: editText                });            }            /**         * 增加对字体的鉴别,以保证用户在编辑状态ctrl/cmd + b/i所触发的加粗斜体与显示一致         * @editor Naixor         * @Date 2015-12-2         */            // edit for the selected node            function editText() {                var node = minder.getSelectedNode();                if (!node) {                    return;                }                var textContainer = receiverElement;                receiverElement.innerText = "";                if (node.getData("font-weight") === "bold") {                    var b = document.createElement("b");                    textContainer.appendChild(b);                    textContainer = b;                }                if (node.getData("font-style") === "italic") {                    var i = document.createElement("i");                    textContainer.appendChild(i);                    textContainer = i;                }                textContainer.innerText = minder.queryCommandValue("text");                if (isGecko) {                    receiver.fixFFCaretDisappeared();                }                fsm.jump("input", "input-request");                receiver.selectAll();            }            /**         * 增加对字体的鉴别,以保证用户在编辑状态ctrl/cmd + b/i所触发的加粗斜体与显示一致         * @editor Naixor         * @Date 2015-12-2         */            function enterInputMode() {                var node = minder.getSelectedNode();                if (node) {                    var fontSize = node.getData("font-size") || node.getStyle("font-size");                    receiverElement.style.fontSize = fontSize + "px";                    receiverElement.style.minWidth = 0;                    receiverElement.style.minWidth = receiverElement.clientWidth + "px";                    receiverElement.style.fontWeight = node.getData("font-weight") || "";                    receiverElement.style.fontStyle = node.getData("font-style") || "";                    receiverElement.classList.add("input");                    receiverElement.focus();                }            }            /**         * 按照文本提交操作处理         * @Desc: 从其他节点复制文字到另一个节点时部分浏览器(chrome)会自动包裹一个span标签,这样试用一下逻辑出来的就不是text节点二是span节点因此导致undefined的情况发生         * @Warning: 下方代码使用[].slice.call来将HTMLDomCollection处理成为Array,ie8及以下会有问题         * @Editor: Naixor         * @Date: 2015.9.16         */            function commitInputText(textNodes) {                var text = "";                var TAB_CHAR = "\t", ENTER_CHAR = "\n", STR_CHECK = /\S/, SPACE_CHAR = " ", // 针对FF,SG,BD,LB,IE等浏览器下SPACE的charCode存在为32和160的情况做处理                SPACE_CHAR_REGEXP = new RegExp("( |" + String.fromCharCode(160) + ")"), BR = document.createElement("br");                var isBold = false, isItalic = false;                for (var str, _divChildNodes, space_l, space_num, tab_num, i = 0, l = textNodes.length; i < l; i++) {                    str = textNodes[i];                    switch (Object.prototype.toString.call(str)) {                      // 正常情况处理                        case "[object HTMLBRElement]":                        {                            text += ENTER_CHAR;                            break;                        }                      case "[object Text]":                        {                            // SG下会莫名其妙的加上 影响后续判断,干掉!                            /**                         * FF下的wholeText会导致如下问题:                         *     |123| -> 在一个节点中输入一段字符,此时TextNode为[#Text 123]                         *     提交并重新编辑,在后面追加几个字符                         *     |123abc| -> 此时123为一个TextNode为[#Text 123, #Text abc],但是对这两个任意取值wholeText均为全部内容123abc                         * 上述BUG仅存在在FF中,故将wholeText更改为textContent                         */                            str = str.textContent.replace(" ", " ");                            if (!STR_CHECK.test(str)) {                                space_l = str.length;                                while (space_l--) {                                    if (SPACE_CHAR_REGEXP.test(str[space_l])) {                                        text += SPACE_CHAR;                                    } else if (str[space_l] === TAB_CHAR) {                                        text += TAB_CHAR;                                    }                                }                            } else {                                text += str;                            }                            break;                        }                      // ctrl + b/i 会给字体加上<b>/<i>标签来实现黑体和斜体                        case "[object HTMLElement]":                        {                            switch (str.nodeName) {                              case "B":                                {                                    isBold = true;                                    break;                                }                              case "I":                                {                                    isItalic = true;                                    break;                                }                              default:                                {}                            }                            [].splice.apply(textNodes, [ i, 1 ].concat([].slice.call(str.childNodes)));                            l = textNodes.length;                            i--;                            break;                        }                      // 被增加span标签的情况会被处理成正常情况并会推交给上面处理                        case "[object HTMLSpanElement]":                        {                            [].splice.apply(textNodes, [ i, 1 ].concat([].slice.call(str.childNodes)));                            l = textNodes.length;                            i--;                            break;                        }                      // 若标签为image标签,则判断是否为合法url,是将其加载进来                        case "[object HTMLImageElement]":                        {                            if (str.src) {                                if (/http(|s):\/\//.test(str.src)) {                                    minder.execCommand("Image", str.src, str.alt);                                } else {}                            }                            break;                        }                      // 被增加div标签的情况会被处理成正常情况并会推交给上面处理                        case "[object HTMLDivElement]":                        {                            _divChildNodes = [];                            for (var di = 0, l = str.childNodes.length; di < l; di++) {                                _divChildNodes.push(str.childNodes[di]);                            }                            _divChildNodes.push(BR);                            [].splice.apply(textNodes, [ i, 1 ].concat(_divChildNodes));                            l = textNodes.length;                            i--;                            break;                        }                      default:                        {                            if (str && str.childNodes.length) {                                _divChildNodes = [];                                for (var di = 0, l = str.childNodes.length; di < l; di++) {                                    _divChildNodes.push(str.childNodes[di]);                                }                                _divChildNodes.push(BR);                                [].splice.apply(textNodes, [ i, 1 ].concat(_divChildNodes));                                l = textNodes.length;                                i--;                            } else {                                if (str && str.textContent !== undefined) {                                    text += str.textContent;                                } else {                                    text += "";                                }                            }                        }                    }                }                text = text.replace(/^\n*|\n*$/g, "");                text = text.replace(new RegExp("(\n|\r|\n\r)( |" + String.fromCharCode(160) + "){4}", "g"), "$1\t");                minder.getSelectedNode().setText(text);                if (isBold) {                    minder.queryCommandState("bold") || minder.execCommand("bold");                } else {                    minder.queryCommandState("bold") && minder.execCommand("bold");                }                if (isItalic) {                    minder.queryCommandState("italic") || minder.execCommand("italic");                } else {                    minder.queryCommandState("italic") && minder.execCommand("italic");                }                exitInputMode();                return text;            }            /**         * 判断节点的文本信息是否是         * @Desc: 从其他节点复制文字到另一个节点时部分浏览器(chrome)会自动包裹一个span标签,这样使用以下逻辑出来的就不是text节点二是span节点因此导致undefined的情况发生         * @Notice: 此处逻辑应该拆分到 kityminder-core/core/data中去,单独增加一个对某个节点importJson的事件         * @Editor: Naixor         * @Date: 2015.9.16         */            function commitInputNode(node, text) {                try {                    minder.decodeData("text", text).then(function(json) {                        function importText(node, json, minder) {                            var data = json.data;                            node.setText(data.text || "");                            var childrenTreeData = json.children || [];                            for (var i = 0; i < childrenTreeData.length; i++) {                                var childNode = minder.createNode(null, node);                                importText(childNode, childrenTreeData[i], minder);                            }                            return node;                        }                        importText(node, json, minder);                        minder.fire("contentchange");                        minder.getRoot().renderTree();                        minder.layout(300);                    });                } catch (e) {                    minder.fire("contentchange");                    minder.getRoot().renderTree();                    // 无法被转换成脑图节点则不处理                    if (e.toString() !== "Error: Invalid local format") {                        throw e;                    }                }            }            function commitInputResult() {                /**             * @Desc: 进行如下处理:             *             根据用户的输入判断是否生成新的节点             *        fix #83 https://github.com/fex-team/kityminder-editor/issues/83             * @Editor: Naixor             * @Date: 2015.9.16             */                var textNodes = [].slice.call(receiverElement.childNodes);                /**             * @Desc: 增加setTimeout的原因:ie下receiverElement.innerHTML=""会导致后             * 		  面commitInputText中使用textContent报错,不要问我什么原因!             * @Editor: Naixor             * @Date: 2015.12.14             */                setTimeout(function() {                    // 解决过大内容导致SVG窜位问题                    receiverElement.innerHTML = "";                }, 0);                var node = minder.getSelectedNode();                textNodes = commitInputText(textNodes);                commitInputNode(node, textNodes);                if (node.type == "root") {                    var rootText = minder.getRoot().getText();                    minder.fire("initChangeRoot", {                        text: rootText                    });                }            }            function exitInputMode() {                receiverElement.classList.remove("input");                receiver.selectAll();            }            function updatePosition() {                var planed = updatePosition;                var focusNode = minder.getSelectedNode();                if (!focusNode) return;                if (!planed.timer) {                    planed.timer = setTimeout(function() {                        var box = focusNode.getRenderBox("TextRenderer");                        receiverElement.style.left = Math.round(box.x) + "px";                        receiverElement.style.top = (debug.flaged ? Math.round(box.bottom + 30) : Math.round(box.y)) + "px";                        //receiverElement.focus();                        planed.timer = 0;                    });                }            }        }        return module.exports = InputRuntime;    }};//src/runtime/jumping.js/** * @fileOverview * * 根据按键控制状态机的跳转 * * @author: techird * @copyright: Baidu FEX, 2014 */_p[13] = {    value: function(require, exports, module) {        var Hotbox = _p.r(2);        // Nice: http://unixpapa.com/js/key.html        function isIntendToInput(e) {            if (e.ctrlKey || e.metaKey || e.altKey) return false;            // a-zA-Z            if (e.keyCode >= 65 && e.keyCode <= 90) return true;            // 0-9 以及其上面的符号            if (e.keyCode >= 48 && e.keyCode <= 57) return true;            // 小键盘区域 (除回车外)            if (e.keyCode != 108 && e.keyCode >= 96 && e.keyCode <= 111) return true;            // 小键盘区域 (除回车外)            // @yinheli from pull request            if (e.keyCode != 108 && e.keyCode >= 96 && e.keyCode <= 111) return true;            // 输入法            if (e.keyCode == 229 || e.keyCode === 0) return true;            return false;        }        /**     * @Desc: 下方使用receiver.enable()和receiver.disable()通过     *        修改div contenteditable属性的hack来解决开启热核后依然无法屏蔽浏览器输入的bug;     *        特别: win下FF对于此种情况必须要先blur在focus才能解决,但是由于这样做会导致用户     *             输入法状态丢失,因此对FF暂不做处理     * @Editor: Naixor     * @Date: 2015.09.14     */        function JumpingRuntime() {            var fsm = this.fsm;            var minder = this.minder;            var receiver = this.receiver;            var container = this.container;            var receiverElement = receiver.element;            var hotbox = this.hotbox;            var compositionLock = false;            // normal -> *            receiver.listen("normal", function(e) {                // 为了防止处理进入edit模式而丢失处理的首字母,此时receiver必须为enable                receiver.enable();                // normal -> hotbox                if (e.is("Space")) {                    e.preventDefault();                    // safari下Space触发hotbox,然而这时Space已在receiver上留下作案痕迹,因此抹掉                    if (kity.Browser.safari) {                        receiverElement.innerHTML = "";                    }                    return fsm.jump("hotbox", "space-trigger");                }                /**             * check             * @editor Naixor             * @Date 2015-12-2             */                switch (e.type) {                  case "keydown":                    {                        if (minder.getSelectedNode()) {                            if (isIntendToInput(e)) {                                return fsm.jump("input", "user-input");                            }                        } else {                            receiverElement.innerHTML = "";                        }                        // normal -> normal shortcut                        fsm.jump("normal", "shortcut-handle", e);                        break;                    }                  case "keyup":                    {                        break;                    }                  default:                    {}                }            });            // hotbox -> normal            receiver.listen("hotbox", function(e) {                receiver.disable();                e.preventDefault();                var handleResult = hotbox.dispatch(e);                if (hotbox.state() == Hotbox.STATE_IDLE && fsm.state() == "hotbox") {                    return fsm.jump("normal", "hotbox-idle");                }            });            // input => normal            receiver.listen("input", function(e) {                receiver.enable();                if (e.type == "keydown") {                    if (e.is("Enter")) {                        e.preventDefault();                        return fsm.jump("normal", "input-commit");                    }                    if (e.is("Esc")) {                        e.preventDefault();                        return fsm.jump("normal", "input-cancel");                    }                    if (e.is("Tab") || e.is("Shift + Tab")) {                        e.preventDefault();                    }                } else if (e.type == "keyup" && e.is("Esc")) {                    e.preventDefault();                    if (!compositionLock) {                        return fsm.jump("normal", "input-cancel");                    }                } else if (e.type == "compositionstart") {                    compositionLock = true;                } else if (e.type == "compositionend") {                    setTimeout(function() {                        compositionLock = false;                    });                }            });            //////////////////////////////////////////////            /// 右键呼出热盒            /// 判断的标准是:按下的位置和结束的位置一致            //////////////////////////////////////////////            var downX, downY;            var MOUSE_RB = 2;            // 右键            container.addEventListener("mousedown", function(e) {                if (e.button == MOUSE_RB) {                    e.preventDefault();                }                if (fsm.state() == "hotbox") {                    hotbox.active(Hotbox.STATE_IDLE);                    fsm.jump("normal", "blur");                } else if (fsm.state() == "normal" && e.button == MOUSE_RB) {                    downX = e.clientX;                    downY = e.clientY;                }            }, false);            container.addEventListener("mousewheel", function(e) {                if (fsm.state() == "hotbox") {                    hotbox.active(Hotbox.STATE_IDLE);                    fsm.jump("normal", "mousemove-blur");                }            }, false);            container.addEventListener("contextmenu", function(e) {                e.preventDefault();            });            container.addEventListener("mouseup", function(e) {                if (fsm.state() != "normal") {                    return;                }                if (e.button != MOUSE_RB || e.clientX != downX || e.clientY != downY) {                    return;                }                if (!minder.getSelectedNode()) {                    return;                }                fsm.jump("hotbox", "content-menu");            }, false);            // 阻止热盒事件冒泡,在热盒正确执行前导致热盒关闭            hotbox.$element.addEventListener("mousedown", function(e) {                e.stopPropagation();            });        }        return module.exports = JumpingRuntime;    }};//src/runtime/minder.js/** * @fileOverview * * 脑图示例运行时 * * @author: techird * @copyright: Baidu FEX, 2014 */_p[14] = {    value: function(require, exports, module) {        var Minder = _p.r(4);        function MinderRuntime() {            // 不使用 kityminder 的按键处理,由 ReceiverRuntime 统一处理            var minder = new Minder({                enableKeyReceiver: false,                enableAnimation: true            });            // 渲染,初始化            minder.renderTo(this.selector);            minder.setTheme(null);            minder.select(minder.getRoot(), true);            minder.execCommand("text", "中心主题");            // 导出给其它 Runtime 使用            this.minder = minder;        }        return module.exports = MinderRuntime;    }};//src/runtime/node.js_p[15] = {    value: function(require, exports, module) {        function NodeRuntime() {            var runtime = this;            var minder = this.minder;            var hotbox = this.hotbox;            var fsm = this.fsm;            var main = hotbox.state("main");            var buttons = [ "前移:Alt+Up:ArrangeUp", "下级:Tab|Insert:AppendChildNode", "同级:Enter:AppendSiblingNode", "后移:Alt+Down:ArrangeDown", "删除:Delete|Backspace:RemoveNode", "上级:Shift+Tab|Shift+Insert:AppendParentNode" ];            var AppendLock = 0;            buttons.forEach(function(button) {                var parts = button.split(":");                var label = parts.shift();                var key = parts.shift();                var command = parts.shift();                main.button({                    position: "ring",                    label: label,                    key: key,                    action: function() {                        if (command.indexOf("Append") === 0) {                            AppendLock++;                            minder.execCommand(command, "分支主题");                            // provide in input runtime                            function afterAppend() {                                if (!--AppendLock) {                                    runtime.editText();                                }                                minder.off("layoutallfinish", afterAppend);                            }                            minder.on("layoutallfinish", afterAppend);                        } else {                            minder.execCommand(command);                            fsm.jump("normal", "command-executed");                        }                    },                    enable: function() {                        return minder.queryCommandState(command) != -1;                    }                });            });            main.button({                position: "bottom",                label: "导入节点",                key: "Alt + V",                enable: function() {                    var selectedNodes = minder.getSelectedNodes();                    return selectedNodes.length == 1;                },                action: importNodeData,                next: "idle"            });            main.button({                position: "bottom",                label: "导出节点",                key: "Alt + C",                enable: function() {                    var selectedNodes = minder.getSelectedNodes();                    return selectedNodes.length == 1;                },                action: exportNodeData,                next: "idle"            });            function importNodeData() {                minder.fire("importNodeData");            }            function exportNodeData() {                minder.fire("exportNodeData");            }        }        return module.exports = NodeRuntime;    }};//src/runtime/priority.js_p[16] = {    value: function(require, exports, module) {        function PriorityRuntime() {            var minder = this.minder;            var hotbox = this.hotbox;            var main = hotbox.state("main");            main.button({                position: "top",                label: "优先级",                key: "P",                next: "priority",                enable: function() {                    return minder.queryCommandState("priority") != -1;                }            });            var priority = hotbox.state("priority");            "123456789".replace(/./g, function(p) {                priority.button({                    position: "ring",                    label: "P" + p,                    key: p,                    action: function() {                        minder.execCommand("Priority", p);                    }                });            });            priority.button({                position: "center",                label: "移除",                key: "Del",                action: function() {                    minder.execCommand("Priority", 0);                }            });            priority.button({                position: "top",                label: "返回",                key: "esc",                next: "back"            });        }        return module.exports = PriorityRuntime;    }};//src/runtime/progress.js_p[17] = {    value: function(require, exports, module) {        function ProgressRuntime() {            var minder = this.minder;            var hotbox = this.hotbox;            var main = hotbox.state("main");            main.button({                position: "top",                label: "进度",                key: "G",                next: "progress",                enable: function() {                    return minder.queryCommandState("progress") != -1;                }            });            var progress = hotbox.state("progress");            "012345678".replace(/./g, function(p) {                progress.button({                    position: "ring",                    label: "G" + p,                    key: p,                    action: function() {                        minder.execCommand("Progress", parseInt(p) + 1);                    }                });            });            progress.button({                position: "center",                label: "移除",                key: "Del",                action: function() {                    minder.execCommand("Progress", 0);                }            });            progress.button({                position: "top",                label: "返回",                key: "esc",                next: "back"            });        }        return module.exports = ProgressRuntime;    }};//src/runtime/receiver.js/** * @fileOverview * * 键盘事件接收/分发器 * * @author: techird * @copyright: Baidu FEX, 2014 */_p[18] = {    value: function(require, exports, module) {        var key = _p.r(23);        var hotbox = _p.r(2);        function ReceiverRuntime() {            var fsm = this.fsm;            var minder = this.minder;            var me = this;            // 接收事件的 div            var element = document.createElement("div");            element.contentEditable = true;            /**         * @Desc: 增加tabindex属性使得element的contenteditable不管是trur还是false都能有focus和blur事件         * @Editor: Naixor         * @Date: 2015.09.14         */            element.setAttribute("tabindex", -1);            element.classList.add("receiver");            element.onkeydown = element.onkeypress = element.onkeyup = dispatchKeyEvent;            element.addEventListener("compositionstart", dispatchKeyEvent);            // element.addEventListener('compositionend', dispatchKeyEvent);            this.container.appendChild(element);            // receiver 对象            var receiver = {                element: element,                selectAll: function() {                    // 保证有被选中的                    if (!element.innerHTML) element.innerHTML = " ";                    var range = document.createRange();                    var selection = window.getSelection();                    range.selectNodeContents(element);                    selection.removeAllRanges();                    selection.addRange(range);                    element.focus();                },                /**             * @Desc: 增加enable和disable方法用于解决热核态的输入法屏蔽问题             * @Editor: Naixor             * @Date: 2015.09.14             */                enable: function() {                    element.setAttribute("contenteditable", true);                },                disable: function() {                    element.setAttribute("contenteditable", false);                },                /**             * @Desc: hack FF下div contenteditable的光标丢失BUG             * @Editor: Naixor             * @Date: 2015.10.15             */                fixFFCaretDisappeared: function() {                    element.removeAttribute("contenteditable");                    element.setAttribute("contenteditable", "true");                    element.blur();                    element.focus();                },                /**             * 以此事件代替通过mouse事件来判断receiver丢失焦点的事件             * @editor Naixor             * @Date 2015-12-2             */                onblur: function(handler) {                    element.onblur = handler;                }            };            receiver.selectAll();            minder.on("beforemousedown", receiver.selectAll);            minder.on("receiverfocus", receiver.selectAll);            minder.on("readonly", function() {                // 屏蔽minder的事件接受,删除receiver和hotbox                minder.disable();                editor.receiver.element.parentElement.removeChild(editor.receiver.element);                editor.hotbox.$container.removeChild(editor.hotbox.$element);            });            // 侦听器,接收到的事件会派发给所有侦听器            var listeners = [];            // 侦听指定状态下的事件,如果不传 state,侦听所有状态            receiver.listen = function(state, listener) {                if (arguments.length == 1) {                    listener = state;                    state = "*";                }                listener.notifyState = state;                listeners.push(listener);            };            function dispatchKeyEvent(e) {                e.is = function(keyExpression) {                    var subs = keyExpression.split("|");                    for (var i = 0; i < subs.length; i++) {                        if (key.is(this, subs[i])) return true;                    }                    return false;                };                var listener, jumpState;                for (var i = 0; i < listeners.length; i++) {                    listener = listeners[i];                    // 忽略不在侦听状态的侦听器                    if (listener.notifyState != "*" && listener.notifyState != fsm.state()) {                        continue;                    }                    /**                 *                 * 对于所有的侦听器,只允许一种处理方式:跳转状态。                 * 如果侦听器确定要跳转,则返回要跳转的状态。                 * 每个事件只允许一个侦听器进行状态跳转                 * 跳转动作由侦听器自行完成(因为可能需要在跳转时传递 reason),返回跳转结果即可。                 * 比如:                 *                 * ```js                 *  receiver.listen('normal', function(e) {                 *      if (isSomeReasonForJumpState(e)) {                 *          return fsm.jump('newstate', e);                 *      }                 *  });                 * ```                 */                    if (listener.call(null, e)) {                        return;                    }                }            }            this.receiver = receiver;        }        return module.exports = ReceiverRuntime;    }};//src/tool/debug.js/** * @fileOverview * * 支持各种调试后门 * * @author: techird * @copyright: Baidu FEX, 2014 */_p[19] = {    value: function(require, exports, module) {        var format = _p.r(20);        function noop() {}        function stringHash(str) {            var hash = 0;            for (var i = 0; i < str.length; i++) {                hash += str.charCodeAt(i);            }            return hash;        }        /* global console */        function Debug(flag) {            var debugMode = this.flaged = window.location.search.indexOf(flag) != -1;            if (debugMode) {                var h = stringHash(flag) % 360;                var flagStyle = format("background: hsl({0}, 50%, 80%); " + "color: hsl({0}, 100%, 30%); " + "padding: 2px 3px; " + "margin: 1px 3px 0 0;" + "border-radius: 2px;", h);                var textStyle = "background: none; color: black;";                this.log = function() {                    var output = format.apply(null, arguments);                    console.log(format("%c{0}%c{1}", flag, output), flagStyle, textStyle);                };            } else {                this.log = noop;            }        }        return module.exports = Debug;    }};//src/tool/format.js_p[20] = {    value: function(require, exports, module) {        function format(template, args) {            if (typeof args != "object") {                args = [].slice.call(arguments, 1);            }            return String(template).replace(/\{(\w+)\}/gi, function(match, $key) {                return args[$key] || $key;            });        }        return module.exports = format;    }};//src/tool/innertext.js/** * @fileOverview * * innerText polyfill * * @author: techird * @copyright: Baidu FEX, 2014 */_p[21] = {    value: function(require, exports, module) {        if (!("innerText" in document.createElement("a")) && "getSelection" in window) {            HTMLElement.prototype.__defineGetter__("innerText", function() {                var selection = window.getSelection(), ranges = [], str, i;                // Save existing selections.                for (i = 0; i < selection.rangeCount; i++) {                    ranges[i] = selection.getRangeAt(i);                }                // Deselect everything.                selection.removeAllRanges();                // Select `el` and all child nodes.                // 'this' is the element .innerText got called on                selection.selectAllChildren(this);                // Get the string representation of the selected nodes.                str = selection.toString();                // Deselect everything. Again.                selection.removeAllRanges();                // Restore all formerly existing selections.                for (i = 0; i < ranges.length; i++) {                    selection.addRange(ranges[i]);                }                // Oh look, this is what we wanted.                // String representation of the element, close to as rendered.                return str;            });            HTMLElement.prototype.__defineSetter__("innerText", function(text) {                /**             * @Desc: 解决FireFox节点内容删除后text为null,出现报错的问题             * @Editor: Naixor             * @Date: 2015.9.16             */                this.innerHTML = (text || "").replace(/</g, "<").replace(/>/g, ">").replace(/\n/g, "<br>");            });        }    }};//src/tool/jsondiff.js/** * @fileOverview * * * * @author: techird * @copyright: Baidu FEX, 2014 */_p[22] = {    value: function(require, exports, module) {        /*!    * https://github.com/Starcounter-Jack/Fast-JSON-Patch    * json-patch-duplex.js 0.5.0    * (c) 2013 Joachim Wester    * MIT license    */        var _objectKeys = function() {            if (Object.keys) return Object.keys;            return function(o) {                var keys = [];                for (var i in o) {                    if (o.hasOwnProperty(i)) {                        keys.push(i);                    }                }                return keys;            };        }();        function escapePathComponent(str) {            if (str.indexOf("/") === -1 && str.indexOf("~") === -1) return str;            return str.replace(/~/g, "~0").replace(/\//g, "~1");        }        function deepClone(obj) {            if (typeof obj === "object") {                return JSON.parse(JSON.stringify(obj));            } else {                return obj;            }        }        // Dirty check if obj is different from mirror, generate patches and update mirror        function _generate(mirror, obj, patches, path) {            var newKeys = _objectKeys(obj);            var oldKeys = _objectKeys(mirror);            var changed = false;            var deleted = false;            for (var t = oldKeys.length - 1; t >= 0; t--) {                var key = oldKeys[t];                var oldVal = mirror[key];                if (obj.hasOwnProperty(key)) {                    var newVal = obj[key];                    if (typeof oldVal == "object" && oldVal != null && typeof newVal == "object" && newVal != null) {                        _generate(oldVal, newVal, patches, path + "/" + escapePathComponent(key));                    } else {                        if (oldVal != newVal) {                            changed = true;                            patches.push({                                op: "replace",                                path: path + "/" + escapePathComponent(key),                                value: deepClone(newVal)                            });                        }                    }                } else {                    patches.push({                        op: "remove",                        path: path + "/" + escapePathComponent(key)                    });                    deleted = true;                }            }            if (!deleted && newKeys.length == oldKeys.length) {                return;            }            for (var t = 0; t < newKeys.length; t++) {                var key = newKeys[t];                if (!mirror.hasOwnProperty(key)) {                    patches.push({                        op: "add",                        path: path + "/" + escapePathComponent(key),                        value: deepClone(obj[key])                    });                }            }        }        function compare(tree1, tree2) {            var patches = [];            _generate(tree1, tree2, patches, "");            return patches;        }        return module.exports = compare;    }};//src/tool/key.js_p[23] = {    value: function(require, exports, module) {        var keymap = _p.r(24);        var CTRL_MASK = 4096;        var ALT_MASK = 8192;        var SHIFT_MASK = 16384;        function hash(unknown) {            if (typeof unknown == "string") {                return hashKeyExpression(unknown);            }            return hashKeyEvent(unknown);        }        function is(a, b) {            return a && b && hash(a) == hash(b);        }        exports.hash = hash;        exports.is = is;        function hashKeyEvent(keyEvent) {            var hashCode = 0;            if (keyEvent.ctrlKey || keyEvent.metaKey) {                hashCode |= CTRL_MASK;            }            if (keyEvent.altKey) {                hashCode |= ALT_MASK;            }            if (keyEvent.shiftKey) {                hashCode |= SHIFT_MASK;            }            // Shift, Control, Alt KeyCode ignored.            if ([ 16, 17, 18, 91 ].indexOf(keyEvent.keyCode) === -1) {                /**             * 解决浏览器输入法状态下对keyDown的keyCode判断不准确的问题,使用keyIdentifier,             * 可以解决chrome和safari下的各种问题,其他浏览器依旧有问题,然而那并不影响我们对特             * 需判断的按键进行判断(比如Space在safari输入法态下就是229,其他的就不是)             * @editor Naixor             * @Date 2015-12-2             */                if (keyEvent.keyCode === 229 && keyEvent.keyIdentifier) {                    return hashCode |= parseInt(keyEvent.keyIdentifier.substr(2), 16);                }                hashCode |= keyEvent.keyCode;            }            return hashCode;        }        function hashKeyExpression(keyExpression) {            var hashCode = 0;            keyExpression.toLowerCase().split(/\s*\+\s*/).forEach(function(name) {                switch (name) {                  case "ctrl":                  case "cmd":                    hashCode |= CTRL_MASK;                    break;                  case "alt":                    hashCode |= ALT_MASK;                    break;                  case "shift":                    hashCode |= SHIFT_MASK;                    break;                  default:                    hashCode |= keymap[name];                }            });            return hashCode;        }    }};//src/tool/keymap.js_p[24] = {    value: function(require, exports, module) {        var keymap = {            Shift: 16,            Control: 17,            Alt: 18,            CapsLock: 20,            BackSpace: 8,            Tab: 9,            Enter: 13,            Esc: 27,            Space: 32,            PageUp: 33,            PageDown: 34,            End: 35,            Home: 36,            Insert: 45,            Left: 37,            Up: 38,            Right: 39,            Down: 40,            Direction: {                37: 1,                38: 1,                39: 1,                40: 1            },            Del: 46,            NumLock: 144,            Cmd: 91,            CmdFF: 224,            F1: 112,            F2: 113,            F3: 114,            F4: 115,            F5: 116,            F6: 117,            F7: 118,            F8: 119,            F9: 120,            F10: 121,            F11: 122,            F12: 123,            "`": 192,            "=": 187,            "-": 189,            "/": 191,            ".": 190        };        // 小写适配        for (var key in keymap) {            if (keymap.hasOwnProperty(key)) {                keymap[key.toLowerCase()] = keymap[key];            }        }        var aKeyCode = 65;        var aCharCode = "a".charCodeAt(0);        // letters        "abcdefghijklmnopqrstuvwxyz".split("").forEach(function(letter) {            keymap[letter] = aKeyCode + (letter.charCodeAt(0) - aCharCode);        });        // numbers        var n = 9;        do {            keymap[n.toString()] = n + 48;        } while (--n);        module.exports = keymap;    }};var moduleMapping = {    "expose-editor": 1};function use(name) {    _p.r([ moduleMapping[name] ]);}angular.module('kityminderEditor', [    'ui.bootstrap',	'ui.codemirror',	'ui.colorpicker'])	.config(["$sceDelegateProvider", function($sceDelegateProvider) {		$sceDelegateProvider.resourceUrlWhitelist([			// Allow same origin resource loads.			'self',			// Allow loading from our assets domain.  Notice the difference between * and **.			'http://agroup.baidu.com:8910/**',            'http://cq01-fe-rdtest01.vm.baidu.com:8910/**',            'http://agroup.baidu.com:8911/**'		]);	}]);angular.module('kityminderEditor').run(['$templateCache', function($templateCache) {  'use strict';  $templateCache.put('ui/directive/appendNode/appendNode.html',    "<div class=\"km-btn-group append-group\"><div class=\"km-btn-item append-child-node\" ng-disabled=\"minder.queryCommandState('AppendChildNode') === -1\" ng-click=\"minder.queryCommandState('AppendChildNode') === -1 || execCommand('AppendChildNode')\" title=\"{{ 'appendchildnode' | lang:'ui/command' }}\"><i class=\"km-btn-icon\"></i> <span class=\"km-btn-caption\">{{ 'appendchildnode' | lang:'ui/command' }}</span></div><div class=\"km-btn-item append-parent-node\" ng-disabled=\"minder.queryCommandState('AppendParentNode') === -1\" ng-click=\"minder.queryCommandState('AppendParentNode') === -1 || execCommand('AppendParentNode')\" title=\"{{ 'appendparentnode' | lang:'ui/command' }}\"><i class=\"km-btn-icon\"></i> <span class=\"km-btn-caption\">{{ 'appendparentnode' | lang:'ui/command' }}</span></div><div class=\"km-btn-item append-sibling-node\" ng-disabled=\"minder.queryCommandState('AppendSiblingNode') === -1\" ng-click=\"minder.queryCommandState('AppendSiblingNode') === -1 ||execCommand('AppendSiblingNode')\" title=\"{{ 'appendsiblingnode' | lang:'ui/command' }}\"><i class=\"km-btn-icon\"></i> <span class=\"km-btn-caption\">{{ 'appendsiblingnode' | lang:'ui/command' }}</span></div></div>"  );  $templateCache.put('ui/directive/arrange/arrange.html',    "<div class=\"km-btn-group arrange-group\"><div class=\"km-btn-item arrange-up\" ng-disabled=\"minder.queryCommandState('ArrangeUp') === -1\" ng-click=\"minder.queryCommandState('ArrangeUp') === -1 || minder.execCommand('ArrangeUp')\" title=\"{{ 'arrangeup' | lang:'ui/command' }}\"><i class=\"km-btn-icon\"></i> <span class=\"km-btn-caption\">{{ 'arrangeup' | lang:'ui/command' }}</span></div><div class=\"km-btn-item arrange-down\" ng-disabled=\"minder.queryCommandState('ArrangeDown') === -1\" ng-click=\"minder.queryCommandState('ArrangeDown') === -1 || minder.execCommand('ArrangeDown');\" title=\"{{ 'arrangedown' | lang:'ui/command' }}\"><i class=\"km-btn-icon\"></i> <span class=\"km-btn-caption\">{{ 'arrangedown' | lang:'ui/command' }}</span></div></div>"  );  $templateCache.put('ui/directive/colorPanel/colorPanel.html',    "<div class=\"bg-color-wrap\"><span class=\"quick-bg-color\" ng-click=\"minder.queryCommandState('background') === -1 || minder.execCommand('background', bgColor)\" ng-disabled=\"minder.queryCommandState('background') === -1\"></span> <span color-picker class=\"bg-color\" set-color=\"setDefaultBg()\" ng-disabled=\"minder.queryCommandState('background') === -1\"><span class=\"caret\"></span></span> <span class=\"bg-color-preview\" ng-style=\"{ 'background-color': bgColor }\" ng-click=\"minder.queryCommandState('background') === -1 || minder.execCommand('background', bgColor)\" ng-disabled=\"minder.queryCommandState('background') === -1\"></span></div>"  );  $templateCache.put('ui/directive/expandLevel/expandLevel.html',    "<div class=\"btn-group-vertical\" dropdown is-open=\"isopen\"><button type=\"button\" class=\"btn btn-default expand\" title=\"{{ 'expandtoleaf' | lang:'ui' }}\" ng-class=\"{'active': isopen}\" ng-click=\"minder.execCommand('ExpandToLevel', 9999)\"></button> <button type=\"button\" class=\"btn btn-default expand-caption dropdown-toggle\" title=\"{{ 'expandtoleaf' | lang:'ui' }}\" dropdown-toggle><span class=\"caption\">{{ 'expandtoleaf' | lang:'ui' }}</span> <span class=\"caret\"></span> <span class=\"sr-only\">{{ 'expandtoleaf' | lang:'ui' }}</span></button><ul class=\"dropdown-menu\" role=\"menu\"><li ng-repeat=\"level in levels\"><a href ng-click=\"minder.execCommand('ExpandToLevel', level)\">{{ 'expandtolevel' + level | lang:'ui/command' }}</a></li></ul></div>"  );  $templateCache.put('ui/directive/fontOperator/fontOperator.html',    "<div class=\"font-operator\"><div class=\"dropdown font-family-list\" dropdown><div class=\"dropdown-toggle current-font-item\" dropdown-toggle ng-disabled=\"minder.queryCommandState('fontfamily') === -1\"><a href class=\"current-font-family\" title=\"{{ 'fontfamily' | lang: 'ui' }}\">{{ getFontfamilyName(minder.queryCommandValue('fontfamily')) || '字体' }}</a> <span class=\"caret\"></span></div><ul class=\"dropdown-menu font-list\"><li ng-repeat=\"f in fontFamilyList\" class=\"font-item-wrap\"><a ng-click=\"minder.execCommand('fontfamily', f.val)\" class=\"font-item\" ng-class=\"{ 'font-item-selected' : f == minder.queryCommandValue('fontfamily') }\" ng-style=\"{'font-family': f.val }\">{{ f.name }}</a></li></ul></div><div class=\"dropdown font-size-list\" dropdown><div class=\"dropdown-toggle current-font-item\" dropdown-toggle ng-disabled=\"minder.queryCommandState('fontsize') === -1\"><a href class=\"current-font-size\" title=\"{{ 'fontsize' | lang: 'ui' }}\">{{ minder.queryCommandValue('fontsize') || '字号' }}</a> <span class=\"caret\"></span></div><ul class=\"dropdown-menu font-list\"><li ng-repeat=\"f in fontSizeList\" class=\"font-item-wrap\"><a ng-click=\"minder.execCommand('fontsize', f)\" class=\"font-item\" ng-class=\"{ 'font-item-selected' : f == minder.queryCommandValue('fontsize') }\" ng-style=\"{'font-size': f + 'px'}\">{{ f }}</a></li></ul></div><span class=\"s-btn-icon font-bold\" ng-click=\"minder.queryCommandState('bold') === -1 || minder.execCommand('bold')\" ng-class=\"{'font-bold-selected' : minder.queryCommandState('bold') == 1}\" ng-disabled=\"minder.queryCommandState('bold') === -1\"></span> <span class=\"s-btn-icon font-italics\" ng-click=\"minder.queryCommandState('italic') === -1 || minder.execCommand('italic')\" ng-class=\"{'font-italics-selected' : minder.queryCommandState('italic') == 1}\" ng-disabled=\"minder.queryCommandState('italic') === -1\"></span><div class=\"font-color-wrap\"><span class=\"quick-font-color\" ng-click=\"minder.queryCommandState('forecolor') === -1 || minder.execCommand('forecolor', foreColor)\" ng-disabled=\"minder.queryCommandState('forecolor') === -1\">A</span> <span color-picker class=\"font-color\" set-color=\"setDefaultColor()\" ng-disabled=\"minder.queryCommandState('forecolor') === -1\"><span class=\"caret\"></span></span> <span class=\"font-color-preview\" ng-style=\"{ 'background-color': foreColor }\" ng-click=\"minder.queryCommandState('forecolor') === -1 || minder.execCommand('forecolor', foreColor)\" ng-disabled=\"minder.queryCommandState('forecolor') === -1\"></span></div><color-panel minder=\"minder\" class=\"inline-directive\"></color-panel></div>"  );  $templateCache.put('ui/directive/hyperLink/hyperLink.html',    "<div class=\"btn-group-vertical\" dropdown is-open=\"isopen\"><button type=\"button\" class=\"btn btn-default hyperlink\" title=\"{{ 'link' | lang:'ui' }}\" ng-class=\"{'active': isopen}\" ng-click=\"addHyperlink()\" ng-disabled=\"minder.queryCommandState('HyperLink') === -1\"></button> <button type=\"button\" class=\"btn btn-default hyperlink-caption dropdown-toggle\" ng-disabled=\"minder.queryCommandState('HyperLink') === -1\" title=\"{{ 'link' | lang:'ui' }}\" dropdown-toggle><span class=\"caption\">{{ 'link' | lang:'ui' }}</span> <span class=\"caret\"></span> <span class=\"sr-only\">{{ 'link' | lang:'ui' }}</span></button><ul class=\"dropdown-menu\" role=\"menu\"><li><a href ng-click=\"addHyperlink()\">{{ 'insertlink' | lang:'ui' }}</a></li><li><a href ng-click=\"minder.execCommand('HyperLink', null)\">{{ 'removelink' | lang:'ui' }}</a></li></ul></div>"  );  $templateCache.put('ui/directive/imageBtn/imageBtn.html',    "<div class=\"btn-group-vertical\" dropdown is-open=\"isopen\"><button type=\"button\" class=\"btn btn-default image-btn\" title=\"{{ 'image' | lang:'ui' }}\" ng-class=\"{'active': isopen}\" ng-click=\"addImage()\" ng-disabled=\"minder.queryCommandState('Image') === -1\"></button> <button type=\"button\" class=\"btn btn-default image-btn-caption dropdown-toggle\" ng-disabled=\"minder.queryCommandState('Image') === -1\" title=\"{{ 'image' | lang:'ui' }}\" dropdown-toggle><span class=\"caption\">{{ 'image' | lang:'ui' }}</span> <span class=\"caret\"></span> <span class=\"sr-only\">{{ 'image' | lang:'ui' }}</span></button><ul class=\"dropdown-menu\" role=\"menu\"><li><a href ng-click=\"addImage()\">{{ 'insertimage' | lang:'ui' }}</a></li><li><a href ng-click=\"minder.execCommand('Image', '')\">{{ 'removeimage' | lang:'ui' }}</a></li></ul></div>"  );  $templateCache.put('ui/directive/kityminderEditor/kityminderEditor.html',    "<div class=\"minder-editor-container\"><div class=\"top-tab\" top-tab=\"minder\" editor=\"editor\" ng-if=\"minder\"></div><div search-box minder=\"minder\" ng-if=\"minder\"></div><div class=\"minder-editor\"></div><div class=\"km-note\" note-editor minder=\"minder\" ng-if=\"minder\"></div><div class=\"note-previewer\" note-previewer ng-if=\"minder\"></div><div class=\"navigator\" navigator minder=\"minder\" ng-if=\"minder\"></div></div>"  );  $templateCache.put('ui/directive/kityminderViewer/kityminderViewer.html',    "<div class=\"minder-editor-container\"><div class=\"minder-viewer\"></div><div class=\"note-previewer\" note-previewer ng-if=\"minder\"></div><div class=\"navigator\" navigator minder=\"minder\" ng-if=\"minder\"></div></div>"  );  $templateCache.put('ui/directive/layout/layout.html',    "<div class=\"readjust-layout\"><a ng-click=\"minder.queryCommandState('resetlayout') === -1 || minder.execCommand('resetlayout')\" class=\"btn-wrap\" ng-disabled=\"minder.queryCommandState('resetlayout') === -1\"><span class=\"btn-icon reset-layout-icon\"></span> <span class=\"btn-label\">{{ 'resetlayout' | lang: 'ui/command' }}</span></a></div>"  );  $templateCache.put('ui/directive/navigator/navigator.html',    "<div class=\"nav-bar\"><div class=\"nav-btn zoom-in\" ng-click=\"minder.execCommand('zoomIn')\" title=\"{{ 'zoom-in' | lang : 'ui' }}\" ng-class=\"{ 'active' : getZoomRadio(zoom) == 0 }\"><div class=\"icon\"></div></div><div class=\"zoom-pan\"><div class=\"origin\" ng-style=\"{'transform': 'translate(0, ' + getHeight(100) + 'px)'}\" ng-click=\"minder.execCommand('zoom', 100);\"></div><div class=\"indicator\" ng-style=\"{\r" +    "\n" +    "             'transform': 'translate(0, ' + getHeight(zoom) + 'px)',\r" +    "\n" +    "             'transition': 'transform 200ms'\r" +    "\n" +    "             }\"></div></div><div class=\"nav-btn zoom-out\" ng-click=\"minder.execCommand('zoomOut')\" title=\"{{ 'zoom-out' | lang : 'ui' }}\" ng-class=\"{ 'active' : getZoomRadio(zoom) == 1 }\"><div class=\"icon\"></div></div><div class=\"nav-btn hand\" ng-click=\"minder.execCommand('hand')\" title=\"{{ 'hand' | lang : 'ui' }}\" ng-class=\"{ 'active' : minder.queryCommandState('hand') == 1 }\"><div class=\"icon\"></div></div><div class=\"nav-btn camera\" ng-click=\"minder.execCommand('camera', minder.getRoot(), 600);\" title=\"{{ 'camera' | lang : 'ui' }}\"><div class=\"icon\"></div></div><div class=\"nav-btn nav-trigger\" ng-class=\"{'active' : isNavOpen}\" ng-click=\"toggleNavOpen()\" title=\"{{ 'navigator' | lang : 'ui' }}\"><div class=\"icon\"></div></div></div><div class=\"nav-previewer\" ng-show=\"isNavOpen\"></div>"  );  $templateCache.put('ui/directive/noteBtn/noteBtn.html',    "<div class=\"btn-group-vertical note-btn-group\" dropdown is-open=\"isopen\"><button type=\"button\" class=\"btn btn-default note-btn\" title=\"{{ 'note' | lang:'ui' }}\" ng-class=\"{'active': isopen}\" ng-click=\"addNote()\" ng-disabled=\"minder.queryCommandState('note') === -1\"></button> <button type=\"button\" class=\"btn btn-default note-btn-caption dropdown-toggle\" ng-disabled=\"minder.queryCommandState('note') === -1\" title=\"{{ 'note' | lang:'ui' }}\" dropdown-toggle><span class=\"caption\">{{ 'note' | lang:'ui' }}</span> <span class=\"caret\"></span> <span class=\"sr-only\">{{ 'note' | lang:'ui' }}</span></button><ul class=\"dropdown-menu\" role=\"menu\"><li><a href ng-click=\"addNote()\">{{ 'insertnote' | lang:'ui' }}</a></li><li><a href ng-click=\"minder.execCommand('note', null)\">{{ 'removenote' | lang:'ui' }}</a></li></ul></div>"  );  $templateCache.put('ui/directive/noteEditor/noteEditor.html',    "<div class=\"panel panel-default\" ng-init=\"noteEditorOpen = false\" ng-show=\"noteEditorOpen\"><div class=\"panel-heading\"><h3 class=\"panel-title\">备注</h3><span>(<a class=\"help\" href=\"https://www.zybuluo.com/techird/note/46064\" target=\"_blank\">支持 GFM 语法书写</a>)</span> <i class=\"close-note-editor glyphicon glyphicon-remove\" ng-click=\"closeNoteEditor()\"></i></div><div class=\"panel-body\"><div ng-show=\"noteEnabled\" ui-codemirror=\"{ onLoad: codemirrorLoaded }\" ng-model=\"noteContent\" ui-codemirror-opts=\"{\r" +    "\n" +    "                gfm: true,\r" +    "\n" +    "                breaks: true,\r" +    "\n" +    "                lineWrapping : true,\r" +    "\n" +    "                mode: 'gfm',\r" +    "\n" +    "                dragDrop: false,\r" +    "\n" +    "                lineNumbers:true\r" +    "\n" +    "             }\"></div><p ng-show=\"!noteEnabled\" class=\"km-note-tips\">请选择节点编辑备注</p></div></div>"  );  $templateCache.put('ui/directive/notePreviewer/notePreviewer.html',    "<div id=\"previewer-content\" ng-show=\"showNotePreviewer\" ng-style=\"previewerStyle\" ng-bind-html=\"noteContent\"></div>"  );  $templateCache.put('ui/directive/operation/operation.html',    "<div class=\"km-btn-group operation-group\"><div class=\"km-btn-item edit-node\" ng-disabled=\"minder.queryCommandState('text') === -1\" ng-click=\"minder.queryCommandState('text') === -1 || editNode()\" title=\"{{ 'editnode' | lang:'ui/command' }}\"><i class=\"km-btn-icon\"></i> <span class=\"km-btn-caption\">{{ 'editnode' | lang:'ui/command' }}</span></div><div class=\"km-btn-item remove-node\" ng-disabled=\"minder.queryCommandState('RemoveNode') === -1\" ng-click=\"minder.queryCommandState('RemoveNode') === -1 || minder.execCommand('RemoveNode');\" title=\"{{ 'removenode' | lang:'ui/command' }}\"><i class=\"km-btn-icon\"></i> <span class=\"km-btn-caption\">{{ 'removenode' | lang:'ui/command' }}</span></div></div>"  );  $templateCache.put('ui/directive/priorityEditor/priorityEditor.html',    "<ul class=\"km-priority tool-group\" ng-disabled=\"commandDisabled\"><li class=\"km-priority-item tool-group-item\" ng-repeat=\"p in priorities\" ng-click=\"commandDisabled || minder.execCommand('priority', p)\" ng-class=\"{ active: commandValue == p }\" title=\"{{ getPriorityTitle(p) }}\"><div class=\"km-priority-icon tool-group-icon priority-{{p}}\"></div></li></ul>"  );  $templateCache.put('ui/directive/progressEditor/progressEditor.html',    "<ul class=\"km-progress tool-group\" ng-disabled=\"commandDisabled\"><li class=\"km-progress-item tool-group-item\" ng-repeat=\"p in progresses\" ng-click=\"commandDisabled || minder.execCommand('progress', p)\" ng-class=\"{ active: commandValue == p }\" title=\"{{ getProgressTitle(p) }}\"><div class=\"km-progress-icon tool-group-icon progress-{{p}}\"></div></li></ul>"  );  $templateCache.put('ui/directive/resourceEditor/resourceEditor.html',    "<div class=\"resource-editor\"><div class=\"input-group\"><input class=\"form-control\" type=\"text\" ng-model=\"newResourceName\" ng-required ng-keypress=\"$event.keyCode == 13 && addResource(newResourceName)\" ng-disabled=\"!enabled\"> <span class=\"input-group-btn\"><button class=\"btn btn-default\" ng-click=\"addResource(newResourceName)\" ng-disabled=\"!enabled\">添加</button></span></div><div class=\"resource-dropdown clearfix\" id=\"resource-dropdown\"><ul class=\"km-resource\" ng-init=\"resourceListOpen = false\" ng-class=\"{'open': resourceListOpen}\"><li ng-repeat=\"resource in used\" ng-disabled=\"!enabled\" ng-blur=\"blurCB()\"><label style=\"background: {{resourceColor(resource.name)}}\"><input type=\"checkbox\" ng-model=\"resource.selected\" ng-disabled=\"!enabled\"> <span>{{resource.name}}</span></label></li></ul><div class=\"resource-caret\" click-anywhere-but-here=\"resourceListOpen = false\" is-active=\"resourceListOpen\" ng-click=\"resourceListOpen = !resourceListOpen\"><span class=\"caret\"></span></div></div></div>"  );  $templateCache.put('ui/directive/searchBox/searchBox.html',    "<div id=\"search\" class=\"search-box clearfix\" ng-show=\"showSearch\"><div class=\"input-group input-group-sm search-input-wrap\"><input type=\"text\" id=\"search-input\" class=\"form-control search-input\" ng-model=\"keyword\" ng-keydown=\"handleKeyDown($event)\" aria-describedby=\"basic-addon2\"> <span class=\"input-group-addon search-addon\" id=\"basic-addon2\" ng-show=\"showTip\" ng-bind=\"'第 ' + curIndex + ' 条,共 ' + resultNum + ' 条'\"></span></div><div class=\"btn-group btn-group-sm prev-and-next-btn\" role=\"group\"><button type=\"button\" class=\"btn btn-default\" ng-click=\"doSearch(keyword, 'prev')\"><span class=\"glyphicon glyphicon-chevron-up\"></span></button> <button type=\"button\" class=\"btn btn-default\" ng-click=\"doSearch(keyword, 'next')\"><span class=\"glyphicon glyphicon-chevron-down\"></span></button></div><div class=\"close-search\" ng-click=\"exitSearch()\"><span class=\"glyphicon glyphicon-remove\"></span></div></div>"  );  $templateCache.put('ui/directive/searchBtn/searchBtn.html',    "<div class=\"btn-group-vertical\" dropdown is-open=\"isopen\"><button type=\"button\" class=\"btn btn-default search\" title=\"{{ 'search' | lang:'ui' }}\" ng-class=\"{'active': isopen}\" ng-click=\"enterSearch()\"></button> <button type=\"button\" class=\"btn btn-default search-caption dropdown-toggle\" ng-click=\"enterSearch()\" title=\"{{ 'search' | lang:'ui' }}\"><span class=\"caption\">{{ 'search' | lang:'ui' }}</span> <span class=\"sr-only\">{{ 'search' | lang:'ui' }}</span></button></div>"  );  $templateCache.put('ui/directive/selectAll/selectAll.html',    "<div class=\"btn-group-vertical\" dropdown is-open=\"isopen\"><button type=\"button\" class=\"btn btn-default select\" title=\"{{ 'selectall' | lang:'ui' }}\" ng-class=\"{'active': isopen}\" ng-click=\"select['all']()\"></button> <button type=\"button\" class=\"btn btn-default select-caption dropdown-toggle\" title=\"{{ 'selectall' | lang:'ui' }}\" dropdown-toggle><span class=\"caption\">{{ 'selectall' | lang:'ui' }}</span> <span class=\"caret\"></span> <span class=\"sr-only\">{{ 'selectall' | lang:'ui' }}</span></button><ul class=\"dropdown-menu\" role=\"menu\"><li ng-repeat=\"item in items\"><a href ng-click=\"select[item]()\">{{ 'select' + item | lang:'ui' }}</a></li></ul></div>"  );  $templateCache.put('ui/directive/styleOperator/styleOperator.html',    "<div class=\"style-operator\"><a ng-click=\"minder.queryCommandState('clearstyle') === -1 || minder.execCommand('clearstyle')\" class=\"btn-wrap clear-style\" ng-disabled=\"minder.queryCommandState('clearstyle') === -1\"><span class=\"btn-icon clear-style-icon\"></span> <span class=\"btn-label\">{{ 'clearstyle' | lang: 'ui' }}</span></a><div class=\"s-btn-group-vertical\"><a class=\"s-btn-wrap\" href ng-click=\"minder.queryCommandState('copystyle') === -1 || minder.execCommand('copystyle')\" ng-disabled=\"minder.queryCommandState('copystyle') === -1\"><span class=\"s-btn-icon copy-style-icon\"></span> <span class=\"s-btn-label\">{{ 'copystyle' | lang: 'ui' }}</span></a> <a class=\"s-btn-wrap paste-style-wrap\" href ng-click=\"minder.queryCommandState('pastestyle') === -1 || minder.execCommand('pastestyle')\" ng-disabled=\"minder.queryCommandState('pastestyle') === -1\"><span class=\"s-btn-icon paste-style-icon\"></span> <span class=\"s-btn-label\">{{ 'pastestyle' | lang: 'ui' }}</span></a></div></div>"  );  $templateCache.put('ui/directive/templateList/templateList.html',    "<div class=\"dropdown temp-panel\" dropdown on-toggle=\"toggled(open)\"><div class=\"dropdown-toggle current-temp-item\" ng-disabled=\"minder.queryCommandState('template') === -1\" dropdown-toggle><a href class=\"temp-item {{ minder.queryCommandValue('template') }}\" title=\"{{ minder.queryCommandValue('template') | lang: 'template' }}\"></a> <span class=\"caret\"></span></div><ul class=\"dropdown-menu temp-list\"><li ng-repeat=\"(key, templateObj) in templateList\" class=\"temp-item-wrap\"><a ng-click=\"minder.execCommand('template', key);\" class=\"temp-item {{key}}\" ng-class=\"{ 'temp-item-selected' : key == minder.queryCommandValue('template') }\" title=\"{{ key | lang: 'template' }}\"></a></li></ul></div>"  );  $templateCache.put('ui/directive/themeList/themeList.html',    "<div class=\"dropdown theme-panel\" dropdown><div class=\"dropdown-toggle theme-item-selected\" dropdown-toggle ng-disabled=\"minder.queryCommandState('theme') === -1\"><a href class=\"theme-item\" ng-style=\"getThemeThumbStyle(minder.queryCommandValue('theme'))\" title=\"{{ minder.queryCommandValue('theme') | lang: 'theme'; }}\">{{ minder.queryCommandValue('theme') | lang: 'theme'; }}</a> <span class=\"caret\"></span></div><ul class=\"dropdown-menu theme-list\"><li ng-repeat=\"key in themeKeyList\" class=\"theme-item-wrap\"><a ng-click=\"minder.execCommand('theme', key);\" class=\"theme-item\" ng-style=\"getThemeThumbStyle(key)\" title=\"{{ key | lang: 'theme'; }}\">{{ key | lang: 'theme'; }}</a></li></ul></div>"  );  $templateCache.put('ui/directive/topTab/topTab.html',    "<tabset><tab heading=\"{{ 'idea' | lang: 'ui/tabs'; }}\" ng-click=\"toggleTopTab('idea')\" select=\"setCurTab('idea')\"><undo-redo editor=\"editor\"></undo-redo><append-node minder=\"minder\"></append-node><arrange minder=\"minder\"></arrange><operation minder=\"minder\"></operation><hyper-link minder=\"minder\"></hyper-link><image-btn minder=\"minder\"></image-btn><note-btn minder=\"minder\"></note-btn><priority-editor minder=\"minder\"></priority-editor><progress-editor minder=\"minder\"></progress-editor><resource-editor minder=\"minder\"></resource-editor></tab><tab heading=\"{{ 'appearence' | lang: 'ui/tabs'; }}\" ng-click=\"toggleTopTab('appearance')\" select=\"setCurTab('appearance')\"><template-list minder=\"minder\" class=\"inline-directive\"></template-list><theme-list minder=\"minder\"></theme-list><layout minder=\"minder\" class=\"inline-directive\"></layout><style-operator minder=\"minder\" class=\"inline-directive\"></style-operator><font-operator minder=\"minder\" class=\"inline-directive\"></font-operator></tab><tab heading=\"{{ 'view' | lang: 'ui/tabs'; }}\" ng-click=\"toggleTopTab('view')\" select=\"setCurTab('view')\"><expand-level minder=\"minder\"></expand-level><select-all minder=\"minder\"></select-all><search-btn minder=\"minder\"></search-btn></tab></tabset>"  );  $templateCache.put('ui/directive/undoRedo/undoRedo.html',    "<div class=\"km-btn-group do-group\"><div class=\"km-btn-item undo\" ng-disabled=\"editor.history.hasUndo() == false\" ng-click=\"editor.history.hasUndo() == false || editor.history.undo();\" title=\"{{ 'undo' | lang:'ui' }}\"><i class=\"km-btn-icon\"></i></div><div class=\"km-btn-item redo\" ng-disabled=\"editor.history.hasRedo() == false\" ng-click=\"editor.history.hasRedo() == false || editor.history.redo()\" title=\"{{ 'redo' | lang:'ui' }}\"><i class=\"km-btn-icon\"></i></div></div>"  );  $templateCache.put('ui/dialog/hyperlink/hyperlink.tpl.html',    "<div class=\"modal-header\"><h3 class=\"modal-title\">链接</h3></div><div class=\"modal-body\"><form><div class=\"form-group\" id=\"link-url-wrap\" ng-class=\"{true: 'has-success', false: 'has-error'}[urlPassed]\"><label for=\"link-url\">链接地址:</label><input type=\"text\" class=\"form-control\" ng-model=\"url\" ng-blur=\"urlPassed = R_URL.test(url)\" ng-focus=\"this.value = url\" ng-keydown=\"shortCut($event)\" id=\"link-url\" placeholder=\"必填:以 http(s):// 或 ftp:// 开头\"></div><div class=\"form-group\" ng-class=\"{'has-success' : titlePassed}\"><label for=\"link-title\">提示文本:</label><input type=\"text\" class=\"form-control\" ng-model=\"title\" ng-blur=\"titlePassed = true\" id=\"link-title\" placeholder=\"选填:鼠标在链接上悬停时提示的文本\"></div></form></div><div class=\"modal-footer\"><button class=\"btn btn-primary\" ng-click=\"ok()\">确定</button> <button class=\"btn btn-warning\" ng-click=\"cancel()\">取消</button></div>"  );  $templateCache.put('ui/dialog/imExportNode/imExportNode.tpl.html',    "<div class=\"modal-header\"><h3 class=\"modal-title\">{{ title }}</h3></div><div class=\"modal-body\"><textarea type=\"text\" class=\"form-control single-input\" rows=\"8\" ng-keydown=\"shortCut($event);\" ng-model=\"value\" ng-readonly=\"type === 'export'\">\r" +    "\n" +    "    </textarea></div><div class=\"modal-footer\"><button class=\"btn btn-primary\" ng-click=\"ok()\" ng-disabled=\"type === 'import' && value == ''\">OK</button> <button class=\"btn btn-warning\" ng-click=\"cancel()\">Cancel</button></div>"  );  $templateCache.put('ui/dialog/image/image.tpl.html',    "<div class=\"modal-header\"><h3 class=\"modal-title\">图片</h3></div><div class=\"modal-body\"><tabset><tab heading=\"图片搜索\"><form class=\"form-inline\"><div class=\"form-group\"><label for=\"search-keyword\">关键词:</label><input type=\"text\" class=\"form-control\" ng-model=\"data.searchKeyword2\" id=\"search-keyword\" placeholder=\"请输入搜索的关键词\"></div><button class=\"btn btn-primary\" ng-click=\"searchImage()\">百度一下</button></form><div class=\"search-result\" id=\"search-result\"><ul><li ng-repeat=\"image in list\" id=\"{{ 'img-item' + $index }}\" ng-class=\"{'selected' : isSelected}\" ng-click=\"selectImage($event)\"><img id=\"{{ 'img-' + $index }}\" ng-src=\"{{ image.src || '' }}\" alt=\"{{ image.title }}\" onerror=\"this.parentNode.removeChild(this)\"> <span>{{ image.title }}</span></li></ul></div></tab><tab heading=\"外链图片\"><form><div class=\"form-group\" ng-class=\"{true: 'has-success', false: 'has-error'}[urlPassed]\"><label for=\"image-url\">链接地址:</label><input type=\"text\" class=\"form-control\" ng-model=\"data.url\" ng-blur=\"urlPassed = data.R_URL.test(data.url)\" ng-focus=\"this.value = data.url\" ng-keydown=\"shortCut($event)\" id=\"image-url\" placeholder=\"必填:以 http(s):// 开头\"></div><div class=\"form-group\" ng-class=\"{'has-success' : titlePassed}\"><label for=\"image-title\">提示文本:</label><input type=\"text\" class=\"form-control\" ng-model=\"data.title\" ng-blur=\"titlePassed = true\" id=\"image-title\" placeholder=\"选填:鼠标在图片上悬停时提示的文本\"></div><div class=\"form-group\"><label for=\"image-preview\">图片预览:</label><img class=\"image-preview\" id=\"image-preview\" ng-src=\"{{ data.url }}\" alt=\"{{ data.title }}\"></div></form></tab><tab heading=\"上传图片\" active=\"true\"><form><div class=\"form-group\"><input type=\"file\" name=\"upload-image\" id=\"upload-image\" class=\"upload-image\" accept=\".jpg,.JPG,jpeg,JPEG,.png,.PNG,.gif,.GIF\" onchange=\"angular.element(this).scope().uploadImage()\"><label for=\"upload-image\" class=\"btn btn-primary\"><span>选择文件…</span></label></div><div class=\"form-group\" ng-class=\"{'has-success' : titlePassed}\"><label for=\"image-title\">提示文本:</label><input type=\"text\" class=\"form-control\" ng-model=\"data.title\" ng-blur=\"titlePassed = true\" id=\"image-title\" placeholder=\"选填:鼠标在图片上悬停时提示的文本\"></div><div class=\"form-group\"><label for=\"image-preview\">图片预览:</label><img class=\"image-preview\" id=\"image-preview\" ng-src=\"{{ data.url }}\" title=\"{{ data.title }}\" alt=\"{{ data.title }}\"></div></form></tab></tabset></div><div class=\"modal-footer\"><button class=\"btn btn-primary\" ng-click=\"ok()\">确定</button> <button class=\"btn btn-warning\" ng-click=\"cancel()\">取消</button></div>"  );}]);angular.module('kityminderEditor').service('commandBinder', function() {	return {		bind: function(minder, command, scope) {			minder.on('interactchange', function() {				scope.commandDisabled = minder.queryCommandState(command) === -1;				scope.commandValue = minder.queryCommandValue(command);				scope.$apply();			});		}	};});angular.module('kityminderEditor')	.provider('config',  function() {		this.config = {			// 右侧面板最小宽度			ctrlPanelMin: 250,			// 右侧面板宽度			ctrlPanelWidth: parseInt(window.localStorage.__dev_minder_ctrlPanelWidth) || 250,			// 分割线宽度			dividerWidth: 3,			// 默认语言			defaultLang: 'zh-cn',			// 放大缩小比例			zoom: [10, 20, 30, 50, 80, 100, 120, 150, 200],            // 图片上传接口            imageUpload: 'server/imageUpload.php'		};		this.set = function(key, value) {            var supported = Object.keys(this.config);            var configObj = {};            // 支持全配置            if (typeof key === 'object') {                configObj = key;            }            else {                configObj[key] = value;            }            for (var i in configObj) {                if (configObj.hasOwnProperty(i) && supported.indexOf(i) !== -1) {                    this.config[i] = configObj[i];                }                else {                    console.error('Unsupported config key: ', key, ', please choose in :', supported.join(', '));                    return false;                }            }            return true;		};		this.$get = function () {			var me = this;			return {				get: function (key) {                    if (arguments.length === 0) {                        return me.config;                    }					if (me.config.hasOwnProperty(key)) {						return me.config[key];					}					console.warn('Missing config key pair for : ', key);					return '';				}			};		}	});angular.module('kityminderEditor')	.service('lang.zh-cn', function() {		return {			'zh-cn': {				'template': {					'default': '思维导图',					'tianpan': '天盘图',					'structure': '组织结构图',					'filetree': '目录组织图',					'right': '逻辑结构图',					'fish-bone': '鱼骨头图'				},				'theme': {					'classic': '脑图经典',					'classic-compact': '紧凑经典',					'snow': '温柔冷光',					'snow-compact': '紧凑冷光',					'fish': '鱼骨图',					'wire': '线框',					'fresh-red': '清新红',					'fresh-soil': '泥土黄',					'fresh-green': '文艺绿',					'fresh-blue': '天空蓝',					'fresh-purple': '浪漫紫',					'fresh-pink': '脑残粉',					'fresh-red-compat': '紧凑红',					'fresh-soil-compat': '紧凑黄',					'fresh-green-compat': '紧凑绿',					'fresh-blue-compat': '紧凑蓝',					'fresh-purple-compat': '紧凑紫',					'fresh-pink-compat': '紧凑粉',					'tianpan':'经典天盘',					'tianpan-compact': '紧凑天盘'				},				'maintopic': '中心主题',				'topic': '分支主题',				'panels': {					'history': '历史',					'template': '模板',					'theme': '皮肤',					'layout': '布局',					'style': '样式',					'font': '文字',					'color': '颜色',					'background': '背景',					'insert': '插入',					'arrange': '调整',					'nodeop': '当前',					'priority': '优先级',					'progress': '进度',					'resource': '资源',					'note': '备注',					'attachment': '附件',					'word': '文字'				},				'error_message': {					'title': '哎呀,脑图出错了',					'err_load': '加载脑图失败',					'err_save': '保存脑图失败',					'err_network': '网络错误',					'err_doc_resolve': '文档解析失败',					'err_unknown': '发生了奇怪的错误',					'err_localfile_read': '文件读取错误',					'err_download': '文件下载失败',					'err_remove_share': '取消分享失败',					'err_create_share': '分享失败',					'err_mkdir': '目录创建失败',					'err_ls': '读取目录失败',					'err_share_data': '加载分享内容出错',					'err_share_sync_fail': '分享内容同步失败',					'err_move_file': '文件移动失败',					'err_rename': '重命名失败',					'unknownreason': '可能是外星人篡改了代码...',					'pcs_code': {						3: "不支持此接口",						4: "没有权限执行此操作",						5: "IP未授权",						110: "用户会话已过期,请重新登录",						31001: "数据库查询错误",						31002: "数据库连接错误",						31003: "数据库返回空结果",						31021: "网络错误",						31022: "暂时无法连接服务器",						31023: "输入参数错误",						31024: "app id为空",						31025: "后端存储错误",						31041: "用户的cookie不是合法的百度cookie",						31042: "用户未登陆",						31043: "用户未激活",						31044: "用户未授权",						31045: "用户不存在",						31046: "用户已经存在",						31061: "文件已经存在",						31062: "文件名非法",						31063: "文件父目录不存在",						31064: "无权访问此文件",						31065: "目录已满",						31066: "文件不存在",						31067: "文件处理出错",						31068: "文件创建失败",						31069: "文件拷贝失败",						31070: "文件删除失败",						31071: "不能读取文件元信息",						31072: "文件移动失败",						31073: "文件重命名失败",						31079: "未找到文件MD5,请使用上传API上传整个文件。",						31081: "superfile创建失败",						31082: "superfile 块列表为空",						31083: "superfile 更新失败",						31101: "tag系统内部错误",						31102: "tag参数错误",						31103: "tag系统错误",						31110: "未授权设置此目录配额",						31111: "配额管理只支持两级目录",						31112: "超出配额",						31113: "配额不能超出目录祖先的配额",						31114: "配额不能比子目录配额小",						31141: "请求缩略图服务失败",						31201: "签名错误",						31202: "文件不存在",						31203: "设置acl失败",						31204: "请求acl验证失败",						31205: "获取acl失败",						31206: "acl不存在",						31207: "bucket已存在",						31208: "用户请求错误",						31209: "服务器错误",						31210: "服务器不支持",						31211: "禁止访问",						31212: "服务不可用",						31213: "重试出错",						31214: "上传文件data失败",						31215: "上传文件meta失败",						31216: "下载文件data失败",						31217: "下载文件meta失败",						31218: "容量超出限额",						31219: "请求数超出限额",						31220: "流量超出限额",						31298: "服务器返回值KEY非法",						31299: "服务器返回值KEY不存在"					}				},				'ui': {					'shared_file_title': '[分享的] {0} (只读)',					'load_share_for_edit': '正在加载分享的文件...',					'share_sync_success': '分享内容已同步',					'recycle_clear_confirm': '确认清空回收站么?清空后的文件无法恢复。',					'fullscreen_exit_hint': '按 Esc 或 F11 退出全屏',					'error_detail': '详细信息',					'copy_and_feedback': '复制并反馈',					'move_file_confirm': '确定把 "{0}" 移动到 "{1}" 吗?',					'rename': '重命名',					'rename_success': '{0} 重命名成功',					'move_success': '{0} 移动成功到 {1}',					'command': {						'appendsiblingnode': '插入同级主题',                        'appendparentnode': '插入上级主题',						'appendchildnode': '插入下级主题',						'removenode': '删除',						'editnode': '编辑',						'arrangeup': '上移',						'arrangedown': '下移',						'resetlayout': '整理布局',						'expandtoleaf': '展开全部节点',						'expandtolevel1': '展开到一级节点',						'expandtolevel2': '展开到二级节点',						'expandtolevel3': '展开到三级节点',						'expandtolevel4': '展开到四级节点',						'expandtolevel5': '展开到五级节点',						'expandtolevel6': '展开到六级节点',						'fullscreen': '全屏',						'outline': '大纲'					},					'search':'搜索',					'expandtoleaf': '展开',					'back': '返回',					'undo': '撤销 (Ctrl + Z)',					'redo': '重做 (Ctrl + Y)',					'tabs': {						'idea': '思路',						'appearence': '外观',						'view': '视图'					},					'quickvisit': {						'new': '新建 (Ctrl + Alt + N)',						'save': '保存 (Ctrl + S)',						'share': '分享 (Ctrl + Alt + S)',						'feedback': '反馈问题(F1)',						'editshare': '编辑'					},					'menu': {						'mainmenutext': '百度脑图', // 主菜单按钮文本						'newtab': '新建',						'opentab': '打开',						'savetab': '保存',						'sharetab': '分享',						'preferencetab': '设置',						'helptab': '帮助',						'feedbacktab': '反馈',						'recenttab': '最近使用',						'netdisktab': '百度云存储',						'localtab': '本地文件',						'drafttab': '草稿箱',						'downloadtab': '导出到本地',						'createsharetab': '当前脑图',						'managesharetab': '已分享',						'newheader': '新建脑图',						'openheader': '打开',						'saveheader': '保存到',						'draftheader': '草稿箱',						'shareheader': '分享我的脑图',						'downloadheader': '导出到指定格式',						'preferenceheader': '偏好设置',						'helpheader': '帮助',						'feedbackheader': '反馈'					},					'mydocument': '我的文档',					'emptydir': '目录为空!',					'pickfile': '选择文件...',					'acceptfile': '支持的格式:{0}',					'dropfile': '或将文件拖至此处',					'unsupportedfile': '不支持的文件格式',					'untitleddoc': '未命名文档',					'overrideconfirm': '{0} 已存在,确认覆盖吗?',					'checklogin': '检查登录状态中...',					'loggingin': '正在登录...',					'recent': '最近打开',					'clearrecent': '清空',					'clearrecentconfirm': '确认清空最近文档列表?',					'cleardraft': '清空',					'cleardraftconfirm': '确认清空草稿箱?',					'none_share': '不分享',					'public_share': '公开分享',					'password_share': '私密分享',					'email_share': '邮件邀请',					'url_share': '脑图 URL 地址:',					'sns_share': '社交网络分享:',					'sns_share_text': '“{0}” - 我用百度脑图制作的思维导图,快看看吧!(地址:{1})',					'none_share_description': '不分享当前脑图',					'public_share_description': '创建任何人可见的分享',					'share_button_text': '创建',					'password_share_description': '创建需要密码才可见的分享',					'email_share_description': '创建指定人可见的分享,您还可以允许他们编辑',					'ondev': '敬请期待!',					'create_share_failed': '分享失败:{0}',					'remove_share_failed': '删除失败:{1}',					'copy': '复制',					'copied': '已复制',					'shared_tip': '当前脑图被 {0}  分享,你可以修改之后保存到自己的网盘上或再次分享',					'current_share': '当前脑图',					'manage_share': '我的分享',					'share_remove_action': '不分享该脑图',					'share_view_action': '打开分享地址',					'share_edit_action': '编辑分享的文件',					'login': '登录',					'logout': '注销',					'switchuser': '切换账户',					'userinfo': '个人信息',					'gotonetdisk': '我的网盘',					'requirelogin': '请 <a class="login-button">登录</a> 后使用',					'saveas': '保存为',					'filename': '文件名',					'fileformat': '保存格式',					'save': '保存',					'mkdir': '新建目录',					'recycle': '回收站',					'newdir': '未命名目录',					'bold': '加粗',					'italic': '斜体',					'forecolor': '字体颜色',					'fontfamily': '字体',					'fontsize': '字号',					'layoutstyle': '主题',					'node': '节点操作',					'saveto': '另存为',					'hand': '允许拖拽',					'camera': '定位根节点',					'zoom-in': '放大(Ctrl+)',					'zoom-out': '缩小(Ctrl-)',					'markers': '标签',					'resource': '资源',					'help': '帮助',					'preference': '偏好设置',					'expandnode': '展开到叶子',					'collapsenode': '收起到一级节点',					'template': '模板',					'theme': '皮肤',					'clearstyle': '清除样式',					'copystyle': '复制样式',					'pastestyle': '粘贴样式',					'appendsiblingnode': '同级主题',					'appendchildnode': '下级主题',					'arrangeup': '前调',					'arrangedown': '后调',					'editnode': '编辑',					'removenode': '移除',					'priority': '优先级',					'progress': {						'p1': '未开始',						'p2': '完成 1/8',						'p3': '完成 1/4',						'p4': '完成 3/8',						'p5': '完成一半',						'p6': '完成 5/8',						'p7': '完成 3/4',						'p8': '完成 7/8',						'p9': '已完成',						'p0': '清除进度'					},					'link': '链接',					'image': '图片',					'note': '备注',                    'insertlink': '插入链接',                    'insertimage': '插入图片',                    'insertnote': '插入备注',					'removelink': '移除已有链接',					'removeimage': '移除已有图片',					'removenote': '移除已有备注',					'resetlayout': '整理',					'justnow': '刚刚',					'minutesago': '{0} 分钟前',					'hoursago': '{0} 小时前',					'yesterday': '昨天',					'daysago': '{0} 天前',					'longago': '很久之前',					'redirect': '您正在打开连接 {0},百度脑图不能保证连接的安全性,是否要继续?',					'navigator': '导航器',					'unsavedcontent': '当前文件还没有保存到网盘:\n\n{0}\n\n虽然未保存的数据会缓存在草稿箱,但是清除浏览器缓存会导致草稿箱清除。',					'shortcuts': '快捷键',					'contact': '联系与反馈',					'email': '邮件组',					'qq_group': 'QQ 群',					'github_issue': 'Github',					'baidu_tieba': '贴吧',					'clipboardunsupported': '您的浏览器不支持剪贴板,请使用快捷键复制',					'load_success': '{0} 加载成功',					'save_success': '{0} 已保存于 {1}',					'autosave_success': '{0} 已自动保存于 {1}',					'selectall': '全选',					'selectrevert': '反选',					'selectsiblings': '选择兄弟节点',					'selectlevel': '选择同级节点',					'selectpath': '选择路径',					'selecttree': '选择子树'				},				'popupcolor': {					'clearColor': '清空颜色',					'standardColor': '标准颜色',					'themeColor': '主题颜色'				},				'dialogs': {					'markers': {						'static': {							'lang_input_text': '文本内容:',							'lang_input_url': '链接地址:',							'lang_input_title': '标题:',							'lang_input_target': '是否在新窗口:'						},						'priority': '优先级',						'none': '无',						'progress': {							'title': '进度',							'notdone': '未完成',							'done1': '完成 1/8',							'done2': '完成 1/4',							'done3': '完成 3/8',							'done4': '完成 1/2',							'done5': '完成 5/8',							'done6': '完成 3/4',							'done7': '完成 7/8',							'done': '已完成'						}					},					'help': {					},					'hyperlink': {},					'image': {},					'resource': {}				},				'hyperlink': {					'hyperlink': '链接...',					'unhyperlink': '移除链接'				},				'image': {					'image': '图片...',					'removeimage': '移除图片'				},				'marker': {					'marker': '进度/优先级...'				},				'resource': {					'resource': '资源...'				}			}		}	});/** * @fileOverview * * UI 状态的 LocalStorage 的存取文件,未来可能在离线编辑的时候升级 * * @author: zhangbobell * @email : zhangbobell@163.com * * @copyright: Baidu FEX, 2015 */angular.module('kityminderEditor')    .service('memory', function() {        function isQuotaExceeded(e) {            var quotaExceeded = false;            if (e) {                if (e.code) {                    switch (e.code) {                        case 22:                            quotaExceeded = true;                            break;                        case 1014:                            // Firefox                            if (e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {                                quotaExceeded = true;                            }                            break;                    }                } else if (e.number === -2147024882) {                    // Internet Explorer 8                    quotaExceeded = true;                }            }            return quotaExceeded;        }        return {            get: function(key) {                var value = window.localStorage.getItem(key);                return null || JSON.parse(value);            },            set: function(key, value) {                try {                    window.localStorage.setItem(key, JSON.stringify(value));                    return true;                } catch(e) {                    if (isQuotaExceeded(e)) {                        return false;                    }                }            },            remove: function(key) {                var value = window.localStorage.getItem(key);                window.localStorage.removeItem(key);                return value;            },            clear: function() {                window.localStorage.clear();            }    }});angular.module('kityminderEditor')    .service('minder.service',  function() {        var callbackQueue = [];        function registerEvent(callback) {            callbackQueue.push(callback);        }        function executeCallback() {            callbackQueue.forEach(function(ele) {                ele.apply(this, arguments);            })        }        return {            registerEvent: registerEvent,            executeCallback: executeCallback        }    });angular.module('kityminderEditor')    .service('resourceService', ['$document', function($document) {    var openScope = null;    this.open = function( dropdownScope ) {        if ( !openScope ) {            $document.bind('click', closeDropdown);            $document.bind('keydown', escapeKeyBind);        }        if ( openScope && openScope !== dropdownScope ) {            openScope.resourceListOpen = false;        }        openScope = dropdownScope;    };    this.close = function( dropdownScope ) {        if ( openScope === dropdownScope ) {            openScope = null;            $document.unbind('click', closeDropdown);            $document.unbind('keydown', escapeKeyBind);        }    };    var closeDropdown = function( evt ) {        // This method may still be called during the same mouse event that        // unbound this event handler. So check openScope before proceeding.        //console.log(evt, openScope);        if (!openScope) { return; }        var toggleElement = openScope.getToggleElement();        if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) {            return;        }        openScope.$apply(function() {            console.log('to close the resourcelist');            openScope.resourceListOpen = false;        });    };    var escapeKeyBind = function( evt ) {        if ( evt.which === 27 ) {            openScope.focusToggleElement();            closeDropdown();        }    };}])angular.module('kityminderEditor').service('revokeDialog', ['$modal', 'minder.service', function($modal, minderService) {    minderService.registerEvent(function() {        // 触发导入节点或导出节点对话框        var minder = window.minder;        var editor = window.editor;        var parentFSM = editor.hotbox.getParentFSM();        minder.on('importNodeData', function() {            parentFSM.jump('modal', 'import-text-modal');            var importModal = $modal.open({                animation: true,                templateUrl: 'ui/dialog/imExportNode/imExportNode.tpl.html',                controller: 'imExportNode.ctrl',                size: 'md',                resolve: {                    title: function() {                        return '导入节点';                    },                    defaultValue: function() {                        return '';                    },                    type: function() {                        return 'import';                    }                }            });            importModal.result.then(function(result) {                try{                    minder.Text2Children(minder.getSelectedNode(), result);                } catch(e) {                    alert(e);                }                parentFSM.jump('normal', 'import-text-finish');                editor.receiver.selectAll();            }, function() {                parentFSM.jump('normal', 'import-text-finish');                editor.receiver.selectAll();            });        });        minder.on('exportNodeData', function() {            parentFSM.jump('modal', 'export-text-modal');            var exportModal = $modal.open({                animation: true,                templateUrl: 'ui/dialog/imExportNode/imExportNode.tpl.html',                controller: 'imExportNode.ctrl',                size: 'md',                resolve: {                    title: function() {                        return '导出节点';                    },                    defaultValue: function() {                        var selectedNode = minder.getSelectedNode(),                            Node2Text = window.kityminder.data.getRegisterProtocol('text').Node2Text;                        return Node2Text(selectedNode);                    },                    type: function() {                        return 'export';                    }                }            });            exportModal.result.then(function(result) {                parentFSM.jump('normal', 'export-text-finish');                editor.receiver.selectAll();            }, function() {                parentFSM.jump('normal', 'export-text-finish');                editor.receiver.selectAll();            });        });    });    return {};}]);/** * @fileOverview * *  与后端交互的服务 * * @author: zhangbobell * @email : zhangbobell@163.com * * @copyright: Baidu FEX, 2015 */angular.module('kityminderEditor')    .service('server', ['config', '$http',  function(config, $http) {        return {            uploadImage: function(file) {                var url = config.get('imageUpload');                var fd = new FormData();                fd.append('upload_file', file);                return $http.post(url, fd, {                    transformRequest: angular.identity,                    headers: {'Content-Type': undefined}                });            }        }    }]);angular.module('kityminderEditor')    .service('valueTransfer', function() {        return {};    });angular.module('kityminderEditor')    .filter('commandState', function() {        return function(minder, command) {            return minder.queryCommandState(command);        }    })    .filter('commandValue', function() {        return function(minder, command) {            return minder.queryCommandValue(command);        }    });angular.module('kityminderEditor')	.filter('lang', ['config', 'lang.zh-cn', function(config, lang) {		return function(text, block) {			var defaultLang = config.get('defaultLang');			if (lang[defaultLang] == undefined) {				return '未发现对应语言包,请检查 lang.xxx.service.js!';			} else {				var dict = lang[defaultLang];				block.split('/').forEach(function(ele, idx) {					dict = dict[ele];				});				return dict[text] || null;			}		};	}]);angular.module('kityminderEditor')    .controller('hyperlink.ctrl', ["$scope", "$modalInstance", "link", function ($scope, $modalInstance, link) {        var urlRegex = '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$';        $scope.R_URL = new RegExp(urlRegex, 'i');        $scope.url = link.url || '';        $scope.title = link.title || '';        setTimeout(function() {            var $linkUrl = $('#link-url');            $linkUrl.focus();            $linkUrl[0].setSelectionRange(0, $scope.url.length);        }, 30);        $scope.shortCut = function(e) {            e.stopPropagation();            if (e.keyCode == 13) {                $scope.ok();            } else if (e.keyCode == 27) {                $scope.cancel();            }        };        $scope.ok = function () {            if($scope.R_URL.test($scope.url)) {                $modalInstance.close({                    url: $scope.url,                    title: $scope.title                });            } else {                $scope.urlPassed = false;                var $linkUrl = $('#link-url');                $linkUrl.focus();                $linkUrl[0].setSelectionRange(0, $scope.url.length);            }            editor.receiver.selectAll();        };        $scope.cancel = function () {            $modalInstance.dismiss('cancel');            editor.receiver.selectAll();        };    }]);angular.module('kityminderEditor')    .controller('imExportNode.ctrl', ["$scope", "$modalInstance", "title", "defaultValue", "type", function ($scope, $modalInstance, title, defaultValue, type) {        $scope.title = title;        $scope.value = defaultValue;        $scope.type = type;        $scope.ok = function () {            if ($scope.value == '') {                return;            }            $modalInstance.close($scope.value);            editor.receiver.selectAll();        };        $scope.cancel = function () {            $modalInstance.dismiss('cancel');            editor.receiver.selectAll();        };        setTimeout(function() {            $('.single-input').focus();            $('.single-input')[0].setSelectionRange(0, defaultValue.length);        }, 30);        $scope.shortCut = function(e) {            e.stopPropagation();            //if (e.keyCode == 13 && e.shiftKey == false) {            //    $scope.ok();            //}            if (e.keyCode == 27) {                $scope.cancel();            }            // tab 键屏蔽默认事件 和 backspace 键屏蔽默认事件            if (e.keyCode == 8 && type == 'export') {                e.preventDefault();            }            if (e.keyCode == 9) {                e.preventDefault();                var $textarea = e.target;                var pos = getCursortPosition($textarea);                var str = $textarea.value;                $textarea.value = str.substr(0, pos) + '\t' + str.substr(pos);                setCaretPosition($textarea, pos + 1);            }        };        /*        * 获取 textarea 的光标位置        * @Author: Naixor        * @date: 2015.09.23        * */        function getCursortPosition (ctrl) {            var CaretPos = 0;	// IE Support            if (document.selection) {                ctrl.focus ();                var Sel = document.selection.createRange ();                Sel.moveStart ('character', -ctrl.value.length);                CaretPos = Sel.text.length;            }            // Firefox support            else if (ctrl.selectionStart || ctrl.selectionStart == '0') {                CaretPos = ctrl.selectionStart;            }            return (CaretPos);        }        /*         * 设置 textarea 的光标位置         * @Author: Naixor         * @date: 2015.09.23         * */        function setCaretPosition(ctrl, pos){            if(ctrl.setSelectionRange) {                ctrl.focus();                ctrl.setSelectionRange(pos,pos);            } else if (ctrl.createTextRange) {                var range = ctrl.createTextRange();                range.collapse(true);                range.moveEnd('character', pos);                range.moveStart('character', pos);                range.select();            }        }    }]);angular.module('kityminderEditor')    .controller('image.ctrl', ['$http', '$scope', '$modalInstance', 'image', 'server', function($http, $scope, $modalInstance, image, server) {        $scope.data = {            list: [],            url: image.url || '',            title: image.title || '',            R_URL: /^https?\:\/\/\w+/        };        setTimeout(function() {            var $imageUrl = $('#image-url');            $imageUrl.focus();            $imageUrl[0].setSelectionRange(0, $scope.data.url.length);        }, 300);        // 搜索图片按钮点击事件        $scope.searchImage = function() {            $scope.list = [];            getImageData()                .success(function(json) {                    if(json && json.data) {                        for(var i = 0; i < json.data.length; i++) {                            if(json.data[i].objURL) {                                $scope.list.push({                                    title: json.data[i].fromPageTitleEnc,                                    src: json.data[i].middleURL,                                    url: json.data[i].middleURL                                });                            }                        }                    }                })                .error(function() {                });        };        // 选择图片的鼠标点击事件        $scope.selectImage = function($event) {            var targetItem = $('#img-item'+ (this.$index));            var targetImg = $('#img-'+ (this.$index));            targetItem.siblings('.selected').removeClass('selected');            targetItem.addClass('selected');            $scope.data.url = targetImg.attr('src');            $scope.data.title = targetImg.attr('alt');        };        // 自动上传图片,后端需要直接返回图片 URL        $scope.uploadImage = function() {            var fileInput = $('#upload-image');            if (!fileInput.val()) {                return;            }            if (/^.*\.(jpg|JPG|jpeg|JPEG|gif|GIF|png|PNG)$/.test(fileInput.val())) {                var file = fileInput[0].files[0];                return server.uploadImage(file).then(function (json) {                    var resp = json.data;                    if (resp.errno === 0) {                        $scope.data.url = resp.data.url;                    }                });            } else {                alert("后缀只能是 jpg、gif 及 png");            }        };        $scope.shortCut = function(e) {            e.stopPropagation();            if (e.keyCode == 13) {                $scope.ok();            } else if (e.keyCode == 27) {                $scope.cancel();            }        };        $scope.ok = function () {            if($scope.data.R_URL.test($scope.data.url)) {                $modalInstance.close({                    url: $scope.data.url,                    title: $scope.data.title                });            } else {                $scope.urlPassed = false;                var $imageUrl = $('#image-url');                if ($imageUrl) {                    $imageUrl.focus();                    $imageUrl[0].setSelectionRange(0, $scope.data.url.length);                }            }            editor.receiver.selectAll();        };        $scope.cancel = function () {            $modalInstance.dismiss('cancel');            editor.receiver.selectAll();        };        function getImageData() {            var key = $scope.data.searchKeyword2;            var currentTime = new Date();            var url = 'http://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&fp=result&queryWord='+ key +'&cl=2&lm=-1&ie=utf-8&oe=utf-8&st=-1&ic=0&word='+ key +'&face=0&istype=2&nc=1&pn=60&rn=60&gsm=3c&'+ currentTime.getTime() +'=&callback=JSON_CALLBACK';            return $http.jsonp(url);        }    }]);angular.module('kityminderEditor')    .directive('appendNode', ['commandBinder', function(commandBinder) {        return {            restrict: 'E',            templateUrl: 'ui/directive/appendNode/appendNode.html',            scope: {                minder: '='            },            replace: true,            link: function($scope) {                var minder = $scope.minder;                commandBinder.bind(minder, 'appendchildnode', $scope)                $scope.execCommand = function(command) {                    minder.execCommand(command, '分支主题');                    editText();                };                function editText() {                    var receiverElement = editor.receiver.element;                    var fsm = editor.fsm;                    var receiver = editor.receiver;                    receiverElement.innerText = minder.queryCommandValue('text');                    fsm.jump('input', 'input-request');                    receiver.selectAll();                }            }        }    }]);angular.module('kityminderEditor')    .directive('arrange', ['commandBinder', function(commandBinder) {        return {            restrict: 'E',            templateUrl: 'ui/directive/arrange/arrange.html',            scope: {                minder: '='            },            replace: true,            link: function($scope) {                var minder = $scope.minder;                //commandBinder.bind(minder, 'priority', $scope);            }        }    }]);angular.module('kityminderEditor')	.directive('colorPanel', function() {		return {			restrict: 'E',			templateUrl: 'ui/directive/colorPanel/colorPanel.html',			scope: {				minder: '='			},            replace: true,			link: function(scope) {				var minder = scope.minder;				var currentTheme = minder.getThemeItems();				scope.$on('colorPicked', function(event, color) {                    event.stopPropagation();					scope.bgColor = color;					minder.execCommand('background', color);				});				scope.setDefaultBg = function() {                    var currentNode = minder.getSelectedNode();                    var bgColor = minder.getNodeStyle(currentNode, 'background');                    // 有可能是 kity 的颜色类                    return typeof bgColor === 'object' ? bgColor.toHEX() : bgColor;                };                scope.bgColor = scope.setDefaultBg() || '#fff';			}		}	});angular.module('kityminderEditor')    .directive('expandLevel', function() {        return {            restrict: 'E',            templateUrl: 'ui/directive/expandLevel/expandLevel.html',            scope: {                minder: '='            },            replace: true,            link: function($scope) {                $scope.levels = [1, 2, 3, 4, 5, 6];            }        }    });angular.module('kityminderEditor')	.directive('fontOperator', function() {		return {			restrict: 'E',			templateUrl: 'ui/directive/fontOperator/fontOperator.html',			scope: {				minder: '='			},            replace: true,			link: function(scope) {				var minder = scope.minder;				var currentTheme = minder.getThemeItems();				scope.fontSizeList = [10, 12, 16, 18, 24, 32, 48];                scope.fontFamilyList = [{                    name: '宋体',                    val: '宋体,SimSun'                }, {                    name: '微软雅黑',                    val: '微软雅黑,Microsoft YaHei'                }, {                    name: '楷体',                    val: '楷体,楷体_GB2312,SimKai'                }, {                    name: '黑体',                    val: '黑体, SimHei'                }, {                    name: '隶书',                    val: '隶书, SimLi'                }, {                    name: 'Andale Mono',                    val: 'andale mono'                }, {                    name: 'Arial',                    val: 'arial,helvetica,sans-serif'                }, {                    name: 'arialBlack',                    val: 'arial black,avant garde'                }, {                    name: 'Comic Sans Ms',                    val: 'comic sans ms'                }, {                    name: 'Impact',                    val: 'impact,chicago'                }, {                    name: 'Times New Roman',                    val: 'times new roman'                }, {                    name: 'Sans-Serif',                    val: 'sans-serif'                }];                scope.$on('colorPicked', function(event, color) {                    event.stopPropagation();                    scope.foreColor = color;                    minder.execCommand('forecolor', color);                });                scope.setDefaultColor = function() {                    var currentNode = minder.getSelectedNode();                    var fontColor = minder.getNodeStyle(currentNode, 'color');                    // 有可能是 kity 的颜色类                    return typeof fontColor === 'object' ? fontColor.toHEX() : fontColor;                };                scope.foreColor = scope.setDefaultColor() || '#000';                scope.getFontfamilyName = function(val) {                    var fontName = '';                    scope.fontFamilyList.forEach(function(ele, idx, arr) {                        if (ele.val === val) {                            fontName = ele.name;                            return '';                        }                    });                    return fontName;                }			}		}	});angular.module('kityminderEditor')    .directive('hyperLink', ['$modal', function($modal) {        return {            restrict: 'E',            templateUrl: 'ui/directive/hyperLink/hyperLink.html',            scope: {                minder: '='            },            replace: true,            link: function($scope) {                var minder = $scope.minder;                $scope.addHyperlink = function() {                    var link = minder.queryCommandValue('HyperLink');                    var hyperlinkModal = $modal.open({                        animation: true,                        templateUrl: 'ui/dialog/hyperlink/hyperlink.tpl.html',                        controller: 'hyperlink.ctrl',                        size: 'md',                        resolve: {                            link: function() {                                return link;                            }                        }                    });                    hyperlinkModal.result.then(function(result) {                        minder.execCommand('HyperLink', result.url, result.title || '');                    });                }            }        }    }]);angular.module('kityminderEditor')    .directive('imageBtn', ['$modal', function($modal) {        return {            restrict: 'E',            templateUrl: 'ui/directive/imageBtn/imageBtn.html',            scope: {                minder: '='            },            replace: true,            link: function($scope) {                var minder = $scope.minder;                $scope.addImage = function() {                    var image = minder.queryCommandValue('image');                    var imageModal = $modal.open({                        animation: true,                        templateUrl: 'ui/dialog/image/image.tpl.html',                        controller: 'image.ctrl',                        size: 'md',                        resolve: {                            image: function() {                                return image;                            }                        }                    });                    imageModal.result.then(function(result) {                        minder.execCommand('image', result.url, result.title || '');                    });                }            }        }    }]);angular.module('kityminderEditor')	.directive('kityminderEditor', ['config', 'minder.service', 'revokeDialog', function(config, minderService, revokeDialog) {		return {			restrict: 'EA',			templateUrl: 'ui/directive/kityminderEditor/kityminderEditor.html',			replace: true,			scope: {				onInit: '&'			},			link: function(scope, element, attributes) {				var $minderEditor = element.children('.minder-editor')[0];				function onInit(editor, minder) {					scope.onInit({						editor: editor,						minder: minder					});					minderService.executeCallback();				}				if (typeof(seajs) != 'undefined') {					/* global seajs */					seajs.config({						base: './src'					});					define('demo', function(require) {						var Editor = require('editor');						var editor = window.editor = new Editor($minderEditor);						if (window.localStorage.__dev_minder_content) {							editor.minder.importJson(JSON.parse(window.localStorage.__dev_minder_content));						}						editor.minder.on('contentchange', function() {							window.localStorage.__dev_minder_content = JSON.stringify(editor.minder.exportJson());						});						window.minder = window.km = editor.minder;						scope.editor = editor;						scope.minder = minder;                        scope.config = config.get();                        //scope.minder.setDefaultOptions(scope.config);						scope.$apply();						onInit(editor, minder);					});					seajs.use('demo');				} else if (window.kityminder && window.kityminder.Editor) {					var editor = new kityminder.Editor($minderEditor);					window.editor = scope.editor = editor;					window.minder = scope.minder = editor.minder;                    scope.config = config.get();                    //scope.minder.setDefaultOptions(config.getConfig());                    onInit(editor, editor.minder);                }			}		}	}]);angular.module('kityminderEditor')    .directive('kityminderViewer', ['config', 'minder.service', function(config, minderService) {        return {            restrict: 'EA',            templateUrl: 'ui/directive/kityminderViewer/kityminderViewer.html',            replace: true,            scope: {                onInit: '&'            },            link: function(scope, element, attributes) {                var $minderEditor = element.children('.minder-viewer')[0];                function onInit(editor, minder) {                    scope.onInit({                        editor: editor,                        minder: minder                    });                    minderService.executeCallback();                }                if (window.kityminder && window.kityminder.Editor) {                    var editor = new kityminder.Editor($minderEditor);                    window.editor = scope.editor = editor;                    window.minder = scope.minder = editor.minder;                    onInit(editor, editor.minder);                }            }        }    }]);angular.module('kityminderEditor')	.directive('layout', function() {		return {			restrict: 'E',			templateUrl: 'ui/directive/layout/layout.html',			scope: {				minder: '='			},            replace: true,			link: function(scope) {			}		}	});/** * @fileOverview * * 左下角的导航器 * * @author: zhangbobell * @email : zhangbobell@163.com * * @copyright: Baidu FEX, 2015 */angular.module('kityminderEditor')    .directive('navigator', ['memory', 'config', function(memory, config) {        return {            restrict: 'A',            templateUrl: 'ui/directive/navigator/navigator.html',            scope: {                minder: '='            },            link: function(scope) {                minder.setDefaultOptions({zoom: config.get('zoom')});                scope.isNavOpen = !memory.get('navigator-hidden');                scope.getZoomRadio = function(value) {                    var zoomStack = minder.getOption('zoom');                    var minValue = zoomStack[0];                    var maxValue = zoomStack[zoomStack.length - 1];                    var valueRange = maxValue - minValue;                    return (1 - (value - minValue) / valueRange);                };                scope.getHeight = function(value) {                    var totalHeight = $('.zoom-pan').height();                    return scope.getZoomRadio(value) * totalHeight;                };                // 初始的缩放倍数                scope.zoom = 100;                // 发生缩放事件时                minder.on('zoom', function(e) {                    scope.zoom = e.zoom;                });                scope.toggleNavOpen = function() {                    scope.isNavOpen = !scope.isNavOpen;                    memory.set('navigator-hidden', !scope.isNavOpen);                    if (scope.isNavOpen) {                        bind();                        updateContentView();                        updateVisibleView();                    } else{                        unbind();                    }                };                setTimeout(function() {                    if (scope.isNavOpen) {                        bind();                        updateContentView();                        updateVisibleView();                    } else{                        unbind();                    }                }, 0);                function bind() {                    minder.on('layout layoutallfinish', updateContentView);                    minder.on('viewchange', updateVisibleView);                }                function unbind() {                    minder.off('layout layoutallfinish', updateContentView);                    minder.off('viewchange', updateVisibleView);                }                /**  以下部分是缩略图导航器 *                 * */                var $previewNavigator = $('.nav-previewer');                // 画布,渲染缩略图                var paper = new kity.Paper($previewNavigator[0]);                // 用两个路径来挥之节点和连线的缩略图                var nodeThumb = paper.put(new kity.Path());                var connectionThumb = paper.put(new kity.Path());                // 表示可视区域的矩形                var visibleRect = paper.put(new kity.Rect(100, 100).stroke('red', '1%'));                var contentView = new kity.Box(), visibleView = new kity.Box();                /**                 * 增加一个对天盘图情况缩略图的处理,                 * @Editor: Naixor line 104~129                 * @Date: 2015.11.3                 */                var pathHandler = getPathHandler(minder.getTheme());                // 主题切换事件                minder.on('themechange', function(e) {                    pathHandler = getPathHandler(e.theme);                });                function getPathHandler(theme) {                    switch (theme) {                        case "tianpan":                        case "tianpan-compact":                            return function(nodePathData, x, y, width, height) {                                var r = width >> 1;                                nodePathData.push('M', x, y + r,                                    'a', r, r, 0, 1, 1, 0, 0.01,                                    'z');                            }                        default: {                            return function(nodePathData, x, y, width, height) {                                nodePathData.push('M', x, y,                                    'h', width, 'v', height,                                    'h', -width, 'z');                            }                        }                    }                }                navigate();                function navigate() {                    function moveView(center, duration) {                        var box = visibleView;                        center.x = -center.x;                        center.y = -center.y;                        var viewMatrix = minder.getPaper().getViewPortMatrix();                        box = viewMatrix.transformBox(box);                        var targetPosition = center.offset(box.width / 2, box.height / 2);                        minder.getViewDragger().moveTo(targetPosition, duration);                    }                    var dragging = false;                    paper.on('mousedown', function(e) {                        dragging = true;                        moveView(e.getPosition('top'), 200);                        $previewNavigator.addClass('grab');                    });                    paper.on('mousemove', function(e) {                        if (dragging) {                            moveView(e.getPosition('top'));                        }                    });                    $(window).on('mouseup', function() {                        dragging = false;                        $previewNavigator.removeClass('grab');                    });                }                function updateContentView() {                    var view = minder.getRenderContainer().getBoundaryBox();                    contentView = view;                    var padding = 30;                    paper.setViewBox(                        view.x - padding - 0.5,                        view.y - padding - 0.5,                        view.width + padding * 2 + 1,                        view.height + padding * 2 + 1);                    var nodePathData = [];                    var connectionThumbData = [];                    minder.getRoot().traverse(function(node) {                        var box = node.getLayoutBox();                        pathHandler(nodePathData, box.x, box.y, box.width, box.height);                        if (node.getConnection() && node.parent && node.parent.isExpanded()) {                            connectionThumbData.push(node.getConnection().getPathData());                        }                    });                    paper.setStyle('background', minder.getStyle('background'));                    if (nodePathData.length) {                        nodeThumb                            .fill(minder.getStyle('root-background'))                            .setPathData(nodePathData);                    } else {                        nodeThumb.setPathData(null);                    }                    if (connectionThumbData.length) {                        connectionThumb                            .stroke(minder.getStyle('connect-color'), '0.5%')                            .setPathData(connectionThumbData);                    } else {                        connectionThumb.setPathData(null);                    }                    updateVisibleView();                }                function updateVisibleView() {                    visibleView = minder.getViewDragger().getView();                    visibleRect.setBox(visibleView.intersect(contentView));                }            }        }    }]);angular.module('kityminderEditor')    .directive('noteBtn', ['valueTransfer', function(valueTransfer) {        return {            restrict: 'E',            templateUrl: 'ui/directive/noteBtn/noteBtn.html',            scope: {                minder: '='            },            replace: true,            link: function($scope) {                var minder = $scope.minder;                $scope.addNote =function() {                    valueTransfer.noteEditorOpen = true;                };            }        }    }]);angular.module('kityminderEditor')	.directive('noteEditor', ['valueTransfer', function(valueTransfer) {		return {			restrict: 'A',			templateUrl: 'ui/directive/noteEditor/noteEditor.html',			scope: {				minder: '='			},            replace: true,			controller: ["$scope", function($scope) {				var minder = $scope.minder;				var isInteracting = false;				var cmEditor;				$scope.codemirrorLoaded =  function(_editor) {					cmEditor = $scope.cmEditor = _editor;					_editor.setSize('100%', '100%');				};				function updateNote() {					var enabled = $scope.noteEnabled = minder.queryCommandState('note') != -1;					var noteValue = minder.queryCommandValue('note') || '';					if (enabled) {						$scope.noteContent = noteValue;					}					isInteracting = true;					$scope.$apply();					isInteracting = false;				}				$scope.$watch('noteContent', function(content) {					var enabled = minder.queryCommandState('note') != -1;					if (content && enabled && !isInteracting) {						minder.execCommand('note', content);					}					setTimeout(function() {						cmEditor.refresh();					});				});                var noteEditorOpen = function() {                    return valueTransfer.noteEditorOpen;                };                // 监听面板状态变量的改变                $scope.$watch(noteEditorOpen, function(newVal, oldVal) {                    if (newVal) {                        setTimeout(function() {                            cmEditor.refresh();                            cmEditor.focus();                        });                    }                    $scope.noteEditorOpen = valueTransfer.noteEditorOpen;                }, true);                $scope.closeNoteEditor = function() {                    valueTransfer.noteEditorOpen = false;					editor.receiver.selectAll();                };				minder.on('interactchange', updateNote);			}]		}	}]);// TODO: 使用一个 div 容器作为 previewer,而不是两个angular.module('kityminderEditor')	.directive('notePreviewer', ['$sce', 'valueTransfer', function($sce, valueTransfer) {		return {			restrict: 'A',			templateUrl: 'ui/directive/notePreviewer/notePreviewer.html',			link: function(scope, element) {				var minder = scope.minder;				var $container = element.parent();				var $previewer = element.children();				scope.showNotePreviewer = false;				marked.setOptions({                    gfm: true,                    tables: true,                    breaks: true,                    pedantic: false,                    sanitize: true,                    smartLists: true,                    smartypants: false                });				var previewTimer;				minder.on('shownoterequest', function(e) {					previewTimer = setTimeout(function() {						preview(e.node, e.keyword);					}, 300);				});				minder.on('hidenoterequest', function() {					clearTimeout(previewTimer);                    scope.showNotePreviewer = false;                    //scope.$apply();				});				var previewLive = false;				$(document).on('mousedown mousewheel DOMMouseScroll', function() {					if (!previewLive) return;					scope.showNotePreviewer = false;					scope.$apply();				});				element.on('mousedown mousewheel DOMMouseScroll', function(e) {					e.stopPropagation();				});				function preview(node, keyword) {					var icon = node.getRenderer('NoteIconRenderer').getRenderShape();					var b = icon.getRenderBox('screen');					var note = node.getData('note');					$previewer[0].scrollTop = 0;					var html = marked(note);					if (keyword) {						html = html.replace(new RegExp('(' + keyword + ')', 'ig'), '<span class="highlight">$1</span>');					}					scope.noteContent = $sce.trustAsHtml(html);					scope.$apply(); // 让浏览器重新渲染以获取 previewer 提示框的尺寸					var cw = $($container[0]).width();					var ch = $($container[0]).height();					var pw = $($previewer).outerWidth();					var ph = $($previewer).outerHeight();					var x = b.cx - pw / 2 - $container[0].offsetLeft;					var y = b.bottom + 10 - $container[0].offsetTop;					if (x < 0) x = 10;					if (x + pw > cw) x = b.left - pw - 10 - $container[0].offsetLeft;					if (y + ph > ch) y = b.top - ph - 10 - $container[0].offsetTop;					scope.previewerStyle = {						'left': Math.round(x) + 'px',						'top': Math.round(y) + 'px'					};					scope.showNotePreviewer = true;					var view = $previewer[0].querySelector('.highlight');					if (view) {						view.scrollIntoView();					}					previewLive = true;					scope.$apply();				}			}		}}]);angular.module('kityminderEditor')    .directive('operation', function() {        return {            restrict: 'E',            templateUrl: 'ui/directive/operation/operation.html',            scope: {                minder: '='            },            replace: true,            link: function($scope) {                $scope.editNode = function() {                    var receiverElement = editor.receiver.element;                    var fsm = editor.fsm;                    var receiver = editor.receiver;                    receiverElement.innerText = minder.queryCommandValue('text');                    fsm.jump('input', 'input-request');                    receiver.selectAll();                }            }        }    });angular.module('kityminderEditor')    .directive('priorityEditor', ['commandBinder', function(commandBinder) {        return {            restrict: 'E',            templateUrl: 'ui/directive/priorityEditor/priorityEditor.html',            scope: {                minder: '='            },            replace: true,            link: function($scope) {                var minder = $scope.minder;                var priorities = [];                for (var i = 0; i < 10; i++) {                    priorities.push(i);                }	            commandBinder.bind(minder, 'priority', $scope);	            $scope.priorities = priorities;	            $scope.getPriorityTitle = function(p) {		            switch(p) {			            case 0: return '移除优先级';			            default: return '优先级' + p;		            }	            }            }        }    }]);angular.module('kityminderEditor')	.directive('progressEditor', ['commandBinder', function(commandBinder) {		return {			restrict: 'E',			templateUrl: 'ui/directive/progressEditor/progressEditor.html',			scope: {				minder: '='			},            replace: true,			link: function($scope) {				var minder = $scope.minder;				var progresses = [];				for (var i = 0; i < 10; i++) {					progresses.push(i);				}				commandBinder.bind(minder, 'progress', $scope);				$scope.progresses = progresses;				$scope.getProgressTitle = function(p) {					switch(p) {						case 0: return '移除进度';						case 1: return '未开始';						case 9: return '全部完成';						default: return '完成' + (p - 1) + '/8';					}				}			}		}	}])angular.module('kityminderEditor')    .directive('resourceEditor', function () {        return {            restrict: 'E',            templateUrl: 'ui/directive/resourceEditor/resourceEditor.html',            scope: {                minder: '='            },            replace: true,            controller: ["$scope", function ($scope) {                var minder = $scope.minder;	            var isInteracting = false;                minder.on('interactchange', function () {                    var enabled = $scope.enabled = minder.queryCommandState('resource') != -1;                    var selected = enabled ? minder.queryCommandValue('resource') : [];                    var used = minder.getUsedResource().map(function (resourceName) {                        return {                            name: resourceName,                            selected: selected.indexOf(resourceName) > -1                        }                    });                    $scope.used = used;	                isInteracting = true;                    $scope.$apply();	                isInteracting = false;                });                $scope.$watch('used', function (used) {                    if (minder.queryCommandState('resource') != -1 && used) {                        var resource = used.filter(function (resource) {                            return resource.selected;                        }).map(function (resource) {                            return resource.name;                        });	                    // 由于 interactchange 带来的改变则不用执行 resource 命令	                    if (isInteracting) {		                    return;	                    }                        minder.execCommand('resource', resource);                    }                }, true);                $scope.resourceColor = function (resource) {                    return minder.getResourceColor(resource).toHEX();                };                $scope.addResource = function (resourceName) {	                var origin = minder.queryCommandValue('resource');                    if (!resourceName || !/\S/.test(resourceName)) return;	                if (origin.indexOf(resourceName) == -1) {		                $scope.used.push({			                name: resourceName,			                selected: true		                });	                }                    $scope.newResourceName = null;                };            }]        };    })    .directive('clickAnywhereButHere', ['$document', function ($document) {        return {            link: function(scope, element, attrs) {                var onClick = function (event) {                    var isChild = $('#resource-dropdown').has(event.target).length > 0;                    var isSelf = $('#resource-dropdown') == event.target;                    var isInside = isChild || isSelf;                    if (!isInside) {                        scope.$apply(attrs.clickAnywhereButHere)                    }                };                scope.$watch(attrs.isActive, function(newValue, oldValue) {                    if (newValue !== oldValue && newValue == true) {                        $document.bind('click', onClick);                    }                    else if (newValue !== oldValue && newValue == false) {                        $document.unbind('click', onClick);                    }                });            }        };    }]);angular.module('kityminderEditor')    .directive('searchBox', function() {        return {            restrict: 'A',            templateUrl: 'ui/directive/searchBox/searchBox.html',            scope: {                minder: '='            },            replace: true,            controller: ["$scope", function ($scope) {                var minder = $scope.minder;                var editor = window.editor;                $scope.handleKeyDown = handleKeyDown;                $scope.doSearch = doSearch;                $scope.exitSearch = exitSearch;                $scope.showTip = false;                $scope.showSearch = false;                // 处理输入框按键事件                function handleKeyDown(e) {                    if (e.keyCode == 13) {                        var direction = e.shiftKey ? 'prev' : 'next';                        doSearch($scope.keyword, direction);                    }                    if (e.keyCode == 27) {                        exitSearch();                    }                }                function exitSearch() {                    $('#search-input').blur();                    $scope.showSearch = false;                    minder.fire('hidenoterequest');                    editor.receiver.selectAll();                }                function enterSearch() {                    $scope.showSearch = true;                    setTimeout(function() {                        $('#search-input').focus();                    }, 10);                    if ($scope.keyword) {                        $('#search-input')[0].setSelectionRange(0, $scope.keyword.length);                    }                }                $('body').on('keydown', function(e) {                    if (e.keyCode == 70 && (e.ctrlKey || e.metaKey) && !e.shiftKey) {                        enterSearch();                        $scope.$apply();                        e.preventDefault();                    }                });                minder.on('searchNode', function() {                    enterSearch();                });                var nodeSequence = [];                var searchSequence = [];                minder.on('contentchange', makeNodeSequence);                makeNodeSequence();                function makeNodeSequence() {                    nodeSequence = [];                    minder.getRoot().traverse(function(node) {                        nodeSequence.push(node);                    });                }                function makeSearchSequence(keyword) {                    searchSequence = [];                    for (var i = 0; i < nodeSequence.length; i++) {                        var node = nodeSequence[i];                        var text = node.getText().toLowerCase();                        if (text.indexOf(keyword) != -1) {                            searchSequence.push({node:node});                        }                        var note = node.getData('note');                        if (note && note.toLowerCase().indexOf(keyword) != -1) {                            searchSequence.push({node: node, keyword: keyword});                        }                    }                }                function doSearch(keyword, direction) {                    $scope.showTip = false;                    minder.fire('hidenoterequest');                    if (!keyword || !/\S/.exec(keyword)) {                        $('#search-input').focus();                        return;                    }                    // 当搜索不到节点时候默认的选项                    $scope.showTip = true;                    $scope.curIndex = 0;                    $scope.resultNum = 0;                    keyword = keyword.toLowerCase();                    var newSearch = doSearch.lastKeyword != keyword;                    doSearch.lastKeyword = keyword;                    if (newSearch) {                        makeSearchSequence(keyword);                    }                    $scope.resultNum = searchSequence.length;                    if (searchSequence.length) {                        var curIndex = newSearch ? 0 : (direction === 'next' ? doSearch.lastIndex + 1 : doSearch.lastIndex - 1) || 0;                        curIndex = (searchSequence.length + curIndex) % searchSequence.length;                        setSearchResult(searchSequence[curIndex].node, searchSequence[curIndex].keyword);                        doSearch.lastIndex = curIndex;                        $scope.curIndex = curIndex + 1;                        function setSearchResult(node, previewKeyword) {                            minder.execCommand('camera', node, 50);                            setTimeout(function () {                                minder.select(node, true);                                if (!node.isExpanded()) minder.execCommand('expand', true);                                if (previewKeyword) {                                    minder.fire('shownoterequest', {node: node, keyword: previewKeyword});                                }                            }, 60);                        }                    }                }            }]        }    });angular.module('kityminderEditor')    .directive('searchBtn', function() {        return {            restrict: 'E',            templateUrl: 'ui/directive/searchBtn/searchBtn.html',            scope: {                minder: '='            },            replace: true,            link: function (scope) {                scope.enterSearch = enterSearch;                function enterSearch() {                    minder.fire('searchNode');                }            }        }    });angular.module('kityminderEditor')    .directive('selectAll', function() {        return {            restrict: 'E',            templateUrl: 'ui/directive/selectAll/selectAll.html',            scope: {                minder: '='            },            replace: true,            link: function($scope) {                var minder = $scope.minder;                $scope.items = ['revert', 'siblings', 'level', 'path', 'tree'];                $scope.select = {                    all: function() {                        var selection = [];                        minder.getRoot().traverse(function(node) {                            selection.push(node);                        });                        minder.select(selection, true);                        minder.fire('receiverfocus');                    },                    revert: function() {                        var selected = minder.getSelectedNodes();                        var selection = [];                        minder.getRoot().traverse(function(node) {                            if (selected.indexOf(node) == -1) {                                selection.push(node);                            }                        });                        minder.select(selection, true);                        minder.fire('receiverfocus');                    },                    siblings: function() {                        var selected = minder.getSelectedNodes();                        var selection = [];                        selected.forEach(function(node) {                            if (!node.parent) return;                            node.parent.children.forEach(function(sibling) {                                if (selection.indexOf(sibling) == -1) selection.push(sibling);                            });                        });                        minder.select(selection, true);                        minder.fire('receiverfocus');                    },                    level: function() {                        var selectedLevel = minder.getSelectedNodes().map(function(node) {                            return node.getLevel();                        });                        var selection = [];                        minder.getRoot().traverse(function(node) {                            if (selectedLevel.indexOf(node.getLevel()) != -1) {                                selection.push(node);                            }                        });                        minder.select(selection, true);                        minder.fire('receiverfocus');                    },                    path: function() {                        var selected = minder.getSelectedNodes();                        var selection = [];                        selected.forEach(function(node) {                            while(node && selection.indexOf(node) == -1) {                                selection.push(node);                                node = node.parent;                            }                        });                        minder.select(selection, true);                        minder.fire('receiverfocus');                    },                    tree: function() {                        var selected = minder.getSelectedNodes();                        var selection = [];                        selected.forEach(function(parent) {                            parent.traverse(function(node) {                                if (selection.indexOf(node) == -1) selection.push(node);                            });                        });                        minder.select(selection, true);                        minder.fire('receiverfocus');                    }                };            }        }    });angular.module('kityminderEditor')	.directive('styleOperator', function() {		return {			restrict: 'E',			templateUrl: 'ui/directive/styleOperator/styleOperator.html',			scope: {				minder: '='			},            replace: true		}	});angular.module('kityminderEditor')	.directive('templateList', function() {		return {			restrict: 'E',			templateUrl: 'ui/directive/templateList/templateList.html',			scope: {				minder: '='			},            replace: true,			link: function($scope) {				$scope.templateList = kityminder.Minder.getTemplateList();			}		}	});angular.module('kityminderEditor')	.directive('themeList', function() {		return {			restrict: 'E',			templateUrl: 'ui/directive/themeList/themeList.html',            replace: true,			link: function($scope) {				var themeList = kityminder.Minder.getThemeList();				//$scope.themeList = themeList;				$scope.getThemeThumbStyle = function (theme) {					var themeObj = themeList[theme];                    if (!themeObj) {                        return;                    }					var style = {						'color': themeObj['root-color'],						'border-radius': themeObj['root-radius'] / 2					};					if (themeObj['root-background']) {						style['background'] = themeObj['root-background'].toString();					}					return style;				};				// 维护 theme key 列表以保证列表美观(不按字母顺序排序)				$scope.themeKeyList = [					'classic',					'classic-compact',					'fresh-blue',					'fresh-blue-compat',					'fresh-green',					'fresh-green-compat',					'fresh-pink',					'fresh-pink-compat',					'fresh-purple',					'fresh-purple-compat',					'fresh-red',					'fresh-red-compat',					'fresh-soil',					'fresh-soil-compat',					'snow',					'snow-compact',					'tianpan',					'tianpan-compact',					'fish',					'wire'				];			}		}	});angular.module('kityminderEditor')    .directive('topTab', function() {       return {           restrict: 'A',           templateUrl: 'ui/directive/topTab/topTab.html',           scope: {               minder: '=topTab',               editor: '='           },           link: function(scope) {               /*               *               * 用户选择一个新的选项卡会执行 setCurTab 和 foldTopTab 两个函数               * 用户点击原来的选项卡会执行 foldTopTop 一个函数               *               * 也就是每次选择新的选项卡都会执行 setCurTab,初始化的时候也会执行 setCurTab 函数               * 因此用 executedCurTab 记录是否已经执行了 setCurTab 函数               * 用 isInit 记录是否是初始化的状态,在任意一个函数时候 isInit 设置为 false               * 用 isOpen 记录是否打开了 topTab               *               * 因此用到了三个 mutex               * */               var executedCurTab = false;               var isInit = true;               var isOpen = true;               scope.setCurTab = function(tabName) {                   setTimeout(function() {                       //console.log('set cur tab to : ' + tabName);                       executedCurTab = true;                       //isOpen = false;                       if (tabName != 'idea') {                           isInit = false;                       }                   });                };               scope.toggleTopTab = function() {                   setTimeout(function() {                       if(!executedCurTab || isInit) {                           isInit = false;                           isOpen ? closeTopTab(): openTopTab();                           isOpen = !isOpen;                       }                       executedCurTab = false;                   });               };               function closeTopTab() {                   var $tabContent = $('.tab-content');                   var $minderEditor = $('.minder-editor');                   $tabContent.animate({                       height: 0,                       display: 'none'                   });                   $minderEditor.animate({                      top: '32px'                   });               }               function openTopTab() {                   var $tabContent = $('.tab-content');                   var $minderEditor = $('.minder-editor');                   $tabContent.animate({                       height: '60px',                       display: 'block'                   });                   $minderEditor.animate({                       top: '92px'                   });               }           }       }    });angular.module('kityminderEditor')    .directive('undoRedo', function() {        return {            restrict: 'E',            templateUrl: 'ui/directive/undoRedo/undoRedo.html',            scope: {                editor: '='            },            replace: true,            link: function($scope) {            }        }    });use('expose-editor');})();
 |