User:Subh83/JavaScriptTools/utilsDOMdynamics.js

/****************************************************
* Created by Subhrajit Bhattacharya [[User:Subh83]] *
* Licensed under GNU-GPL v3.0                       *
*****************************************************/
var UserSubh83_utilsDOMdynamics = true;

// ================================================================
/*** DOM traversal/search utils ***/

function FindNodeUpLeftTree(elemin, tagnames) {
    // Given an element 'elemin', the function finds the first node with 
    //    tag name in array 'tagnames' that is either a previous sibling, 
    //    or a previous sibling of of any ancestor.
    var elem = elemin;
    for (var j=0; j<tagnames.length; j++) tagnames[j] = tagnames[j].toLowerCase();
 
    var prevelem;
    for (var i=0;i<=10000;i++) {
        if (elem.previousSibling)
            prevelem = elem.previousSibling;
        else if (elem.parentNode)
            prevelem = elem.parentNode;
 
        if (!prevelem.tagName) {
            elem = prevelem;
            continue;
        }
 
        if (prevelem) {
            var tn = prevelem.tagName.toLowerCase();
            for (var j=0; j<tagnames.length; j++)
                if (tn==tagnames[j])
                    return prevelem;
            elem = prevelem;
        } else
            return false;
    }
}

function FindNodeUpTree(elemin, tagnames) {
    // Given an element 'elemin', the function finds an ancestor with tag from 'tagnames'
    var elem = elemin;
    for (var j=0; j<tagnames.length; j++) tagnames[j] = tagnames[j].toLowerCase();
 
    var prevelem;
    for (var i=0;i<=10000;i++) {
        if (elem.parentNode)
            prevelem = elem.parentNode;
 
        if (!prevelem.tagName) {
            elem = prevelem;
            continue;
        }
 
        if (prevelem) {
            var tn = prevelem.tagName.toLowerCase();
            for (var j=0; j<tagnames.length; j++)
                if (tn==tagnames[j])
                    return prevelem;
            elem = prevelem;
        } else
            return false;
    }
}

// Wikipedia specific: For finding the edit section corresponding to a paragraph
function GetPrevEditsectionLinkElement(elem) {
    // Traverse the DOM tree upwards until a 'h' element is encountered
    var hElem = FindNodeUpLeftTree(elem, ['h1','h2','h3','h4','h5','h6']);
    // Return the 'a' in it
    if (hElem) {
        var hElemAs = hElem.getElementsByTagName("a");
        if (hElemAs && hElemAs.length>0)
            return hElemAs[0];
    }
    return false;
}


// ================================================================
/*** Poistioning/display utils ***/

function setMenuPosition (e, menudiv) {
    // Position 'menudiv' at mouse pointer position.
    var posx = e.clientX; 
    var posy = e.clientY;

    var w, h;
    if (document.body && document.body.offsetWidth) {
        w = document.body.offsetWidth;
        h = document.body.offsetHeight;
    }
    if (document.compatMode=='CSS1Compat' &&
               document.documentElement &&
                  document.documentElement.offsetWidth ) {
        w = document.documentElement.offsetWidth;
        h = document.documentElement.offsetHeight;
    }
    if (window.innerWidth && window.innerHeight) {
        w = window.innerWidth;
        h = window.innerHeight;
    }

    menudiv.style.position = "fixed";
    if (posx < w/2) {
        menudiv.style.left = posx+"px";
        menudiv.style.pixelLeft = posx+"px";
        menudiv.style.right = "auto";
        menudiv.style.pixelRight = "auto";
    } else {
        menudiv.style.right = (w-posx)+"px";
        menudiv.style.pixelRight = (w-posx)+"px";
        menudiv.style.left = "auto";
        menudiv.style.pixelLeft = "auto";
    }

    if (posy < h/2) {
        menudiv.style.top = posy+"px";
        menudiv.style.pixelTop = posy+"px";
        menudiv.style.bottom = "auto";
        menudiv.style.pixelBottom = "auto";
    } else {
        menudiv.style.bottom = (h-posy)+"px";
        menudiv.style.pixelBottom = (h-posy)+"px";
        menudiv.style.top = "auto";
        menudiv.style.pixelTop = "auto";
    }
}

function ToggleElementDisplay(divID) {
    var theElem = document.getElementById(divID);
    if (theElem) {
        if (theElem.style.display=='none') { theElem.style.display='block'; return 1; }
        else { theElem.style.display='none'; return 0; }
    }
}

// ================================================================
/*** Textarea, textbox selection & editing utils ***/

function selectRangeInTextarea(ctrl, start, end, autoscroll) {
    if(ctrl.setSelectionRange) {
        ctrl.focus();
        ctrl.setSelectionRange(start, end);
    }
    else if (ctrl.createTextRange) {
        var range = ctrl.createTextRange();
        range.collapse(true);
        range.moveStart('character', start);
        range.moveEnd('character', end);
        range.select();
    }
    if (typeof(autoscroll)=='undefined') autoscroll = true;
    if(autoscroll)
        ctrl.scrollTop = findScrollTopFromPos(ctrl, start, 2);
    ctrl.focus();
}

function findScrollTopFromPos(ctrl, pos, topOffset) {
    if(typeof(topOffset)=='undefined') topOffset = 0;
    var reducingtext = ctrl.value;
    reducingtext.replace(/\t/g, "    ").replace(/\r\n|\n\r/g, "\n").replace(/\r/g, "\n");
    var ColsNo = getTextareaNumberOfColumns(ctrl);
    var LineRegexS = "^.{0,"+ColsNo+"}?\\n|^.{0,"+ColsNo+"}\\s|.{0,"+ColsNo+"}";
    var LineRegex = new RegExp(LineRegexS);
    var LineCount=0, CharCount=0, LinePos=0;
    while (CharCount<(ctrl.value.length-ColsNo-1)) {
        line = reducingtext.match(LineRegex);
        CharCount += line[0].length;
        if (CharCount<=pos) LinePos = LineCount;
        LineCount++;
        reducingtext = reducingtext.substring(line[0].length);
    }
    return parseInt( ctrl.scrollHeight * Math.min(1,Math.max(0, ((LinePos-topOffset)/LineCount) )) );
}

function getTextareaNumberOfColumns(ctrl) {
    var fullWidth = ctrl.clientWidth;
    ctrl.style.width = 'auto';
    while(ctrl.clientWidth < fullWidth) {
        ctrl.cols = ctrl.cols + 1;
    }
    while (ctrl.clientWidth > fullWidth) {
        ctrl.cols = ctrl.cols - 1;
    }
    return(ctrl.cols);
}

function getSelectionInTextarea(ctrl) {
    var sel = new Object();
    if(ctrl.selectionStart) {
        sel.start = ctrl.selectionStart;
        sel.end = ctrl.selectionEnd;
    }
    else if (document.selection) {
        var textRange = document.selection.createRange();
        sel.start = textRange.startOffset;
        sel.end = textRange.endOffset;
    }
    if (typeof(sel.start)!='undefined') {
        sel.text = ctrl.value.substring(sel.start, sel.end);
        return sel;
    }
    else {
        sel.start = 0;
        sel.end = 0;
        sel.text = 0;
    }
    return sel;
}

function updateSelectionInTextarea(ctrl, newtext, sel, newSelectionStartOffset, newSelectionLength) {
    if (typeof(sel)=='undefined') sel = getSelectionInTextarea(ctrl);
    var newcontent = ctrl.value.substring(0, sel.start) + newtext + ctrl.value.substring(sel.end);
    ctrl.value = newcontent;

    var retsel = new Object();
    if(typeof(newSelectionStartOffset)=='undefined') newSelectionStartOffset = 0;
    if(typeof(newSelectionLength)=='undefined') newSelectionLength = newtext.length;
    retsel.start = sel.start + newSelectionStartOffset;
    retsel.end = sel.start + newSelectionStartOffset + newSelectionLength;
    retsel.text = newtext.substr(newSelectionStartOffset, newSelectionLength);
    return retsel;
}

// ================================================================
/*** Event handling utils ***/

function AppendHandlerToEvent(theevent, newhandler, position, condition, finalEvalS) {
    // 'theevent' is a string. 'newhandler' is a function name or a string.
    // position is 'post' (default) or 'pre'
    // If 'condition' is provided, the function that is evaluated first must 
    //       return the value of the 'condition' for the next function to be evaluated.
    // 'finalEvalS' is a string to be evaluated at the end of the combined handler execution.
    //       This is required for passing signals to browser's native handlers. It can contain 
    //       variables 'retOld' and 'retNew'.

    if (typeof(position)=='undefined') position='post';
    if (typeof(finalEvalS)=='undefined') finalEvalS="";
    eval("var oldhandler = " + theevent);

    var evalStartS = theevent + " = function(e) {                                                       ";
    var oldEvalS =              "       if (oldhandler) {                                               " +
                                "           if (typeof(oldhandler)=='string') eval('r='+oldhandler);    " +
                                "           else r = oldhandler(e);                                     " +
                                "           retOld = r;                                                 " +
                                "       }                                                               ";

    var condStartS = ""; condEndS = "";
    if (typeof(condition)!='undefined') { condStartS = " if (r===condition) {"; condEndS = "}"; }

    var newEvalS =              "       if (typeof(newhandler)=='string') eval('r='+newhandler);        " +
                                "       else r = newhandler(e);                                         " +
                                "       retNew = r;                                                     ";
    var evalEndS = finalEvalS + "   }                                                                   ";

    if (position == 'post') var evalS = evalStartS + oldEvalS + condStartS + newEvalS + condEndS + evalEndS;
    else if (position == 'pre') var evalS = evalStartS + newEvalS + condStartS + oldEvalS + condEndS + evalEndS;

    eval(evalS);
}

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.