JS code assist in JS

Gribēju tev manu dārgo lasītāj izstāstīt par savu šīsnedēļas naktsprojektu. Nē, nē, nejau to, kur līdz turpat trijiem naktī tiek nostāvēts Ļeņingradā, jo sarunas ar Uldi, Andri un Aneti ir foršas – par to lai Andris uzraksta Luckānismā.

Es te par citu savu izklaidi – Math.js un tā testēšanas un izmantošanas konsoli.

Viss sākās ar to, ka pirmdien (laikam, kaut gan iespējams arī otrdien) izdomāju, ka jāpieliek konsolei megafīča – grafiku zīmēšana – domāts darīts – samedīju internetos vienu koda gabalu, kur ar canvas tiek zīmēti funkciju grafiki. Godīgi nospēru šo kodu, pielāgoju to savām vajadzībām un sāku gūgletõlkā zīmēties.

A tur man pretī – a tu, bļe scuko, helpu uztaisi – a to fig var saprast, ko vispār iekš tās tavas konsoles var un ko nevar. Es, protams, kā jau parasti normāli koderi atbild uz jūzeru rekvestiem – šāvu pretī – da nah – un vispār visa šitā figņa ir tīri manām vajadzībām un es tjipa atceros visu, ko var un ko nevar.

Bet, tomēr savā būtībā jusdamies koderis sajutu sevī čallendžu – a moš tomēr kaut kādu code assist rīku var uzmeistarot, nu tur tjipa no sērijas funkcijām autocomplete. Un tad atcerējos par vienu lielisku JS īpašību – for property in object ciklus – takš var uztaisīt, ka atpazīstam kaut kādu sarakstīto teksta gabaliņu un tad nočekojam vai rakstītais teksts ir kaut kāda propertija sākums. Domāts darīts.

Eku interesantais kods:


//tekstārejai ar idu #js_execute, pieliekam eventu pie pogu nospiešanas
//saprotams, ka izmantojam jQuery
$('#js_execute').keydown(function(e){
    if ( e.shiftKey && e.keyCode == 32) {
        e.preventDefault();
        window.getJsExecSelection(this.selectionStart);
        return false;
    }            
});

window.getJsExecSelection = function(ro){
    var el =$('#js_execute')[0];
    var text = $('#js_execute').val().substr(0,ro);
    var GlobalObjs = ['Math','window','document','navigator','isFinite',
    'isNaN','Number','parseFloat','parseInt','Infinity','NaN','undefined'];
    
    function getSuggestion(objs,i,parentObj) {
        if ( objs.length - 1 == i ) {
            //suggestion here
            if ( i == 0 ) {
                for ( var k = 0; k<GlobalObjs.length; k++ ) {
                    if ( GlobalObjs[k].match('^'+objs[i]) ) {
                        var htext = GlobalObjs[k].substr(objs[i].length);
                        $('#js_execute').val(text+htext+textAfter);
                        el.selectionStart = ro;
                        el.selectionEnd = ro+htext.length;
                        return;
                    }
                }
            } else {
                for ( var item in parentObj ) {
                    if ( item.match('^'+objs[i]) ) {
                        var htext = item.substr(objs[i].length);
                        $('#js_execute').val(text+htext+textAfter);
                        el.selectionStart = ro;
                        el.selectionEnd = ro+htext.length;
                        return;
                    }
                }
            }
            if ( i == 1 && parentObj == Math ) {
                var MathProps = ['E','LN2','LN10','LOG2E','LOG10E','PI','SQRT1_2','SQRT2',
                                'abs','acos','asin','atan','atan2','ceil','cos','exp','floor',
                                'log','max','min','pow','random','round','sin','sqrt','tan'];
                for ( var k = 0; k< MathProps.length; k++ ) {
                    if ( MathProps[k].match('^'+objs[i]) ) {
                        var htext = MathProps[k].substr(objs[i].length);
                        $('#js_execute').val(text+htext+textAfter);
                        el.selectionStart = ro;
                        el.selectionEnd = ro+htext.length;
                        return;
                    }
                }
            }
        } else {
            //get the current obj
            if ( i == 0 ) {
                for ( var k = 0; k<GlobalObjs.length; k++ ) {
                    if ( objs[i] == GlobalObjs[k] ) {
                        return getSuggestion(objs,i+1,eval(GlobalObjs[k]));
                    }
                }
            } else {
                for ( var k in parentObj ) {
                    if ( k == objs[i] ) {
                        return getSuggestion(objs,i+1,parentObj[k]);
                    }
                }
            }
        }
    }
    var textAfter = $('#js_execute').val().substr(ro);
    var lastToken = text.match(/[a-zA-Z][a-zA-Z0-9\.]*$/);
    if ( lastToken != null ) {
        var objs = lastToken.toString().split('.');
        
        getSuggestion(objs,0,null);
        
    }
    
}

Dažas piezīmes šī te koda sakarā:

  • Kā redzams, tad autocomplete tiek izsaukts nospiežot Shift + space (pirmajā variantā bija, ka tas notiek automātiski ar taimerīti, bet praksē lietojot šādu variantu nākas saskarties ar dažādām problēmām.)
  • Šis kods, ne sūda nestrādās uz IE (kas gan ir kinda pohuj – kanvasi arī nestrādā, turklāt vispār ir takš arī normāli pārlūki mūsdienās atrodami)
  • Nav nekādas iespējas normāli tikt klāt pie globālajiem objektiem/funkcijām, līdz ar to tie ir jādefinē, kā arī jāapstrādā atsevišķi.
  • Tāpat, kā izrādās, tad oriģinālās metodes/propertijus nevar dabūt arī valodas objektiem – (aļa tur Math/Array/String, etc.) līdz ar to, ja tādus gribās – tad tie arī ir jādefinē atsevišķi. Savukārt DOM objektu propertijus šis autocomplete māk atrast pavisam lieliski.
  • Vēl, kas ir kruta – ja tiek piedefinēts jauns propertijs, kādam no esošajiem objektiem, nu tur teiksim window objektam uztaisam propertiju blahblahblah (window.blahblahblah = 5), tad arī šo propertiju varēs dabūt iekš autocomplete.
  • Protams, ir visādas, lietas, kā šo pasākumu varētu sarežģīt un uztaisīt vēl lietojamāku – nu tur parādās kautkāds popups ar visiem objekta propertijiem, kuri atbilst dotā stringa sākumam, kurus tad attiecīgi var izvēlēties ‘n shit.
Raksts publicēts kategorijā Kods. Iemet grāmatzīmēs tiešsaiti.

1 Thought.

Atbildēt

Jūsu e-pasta adrese netiks publicēta. Obligātie lauki ir atzīmēti kā *