Creates Photoshop-like guides and rulers interface on a web page

Overview

RulersGuides.js

This Javascript package creates Photoshop-like guides and rulers interface on a web page.

DEMO

Main window:

Menu:

Guides are created by click-and-dragging corresponding horizontal or vertical ruler. Guide position is shown while dragging and on mouse over.

It is possible to open/save created guides as grids (Note: grids will be saved on a page location basis, so it's not possible to use the same grids in another browser window/tab).

 

Rulers can be unlocked, so that one of the rulers will scroll along the page and the other will be always visible.

Guides can be snapped to defined number of pixels.

Detailed info mode is available, which shows position and size of regions created by the guides. Works on guide position change too.

Guides can be snapped to DOM elements (experimental, use with caution, can be slow or unresponsive on complex pages with lots of elements).

Following hotkeys are available:

  • Toggle rulers - Ctrl + Alt + R
  • Toggle guides - Ctrl + Alt + G
  • Toggle rulers and guides - Ctrl + Alt + A
  • Clear all guides - Ctrl + Alt + D
  • Save grid dialog - Ctrl + Alt + S
  • Open grid dialog - Ctrl + Alt + O
  • Lock/unlock rulers - Ctrl + Alt + L
  • Open Snap to dialog - Ctrl + Alt + C
  • Toggle detailed info - Ctrl + Alt + I
  • Toggle snap to DOM - Ctrl + Alt + E

Look-and-feel can be adjusted using CSS.

RulersGuides.js is available as a bookmarklet, please see bookmarklet.js file provided with the package.

For IE users there is a bookmarklet_ie.js file, which loads necessary packages externally due to IE bookmark size restriction.

You can copy and include them locally by changing paths in the bookmarklet.

RulersGuides.js is available as an extension for Google Chrome browser, download it here, and drag and drop downloaded file to extensions tab (chrome://extensions).

RulersGuides.js requires Event.js and Dragdrop.js packages, which can be acquired at the following links:

Event.js

Dragdrop.js

Browser Compatibility

Currently tested in:

  • Chrome 24
  • Firefox 18
  • IE 7, 8 and 9 (without grid saving functionality)
  • Safari for Windows 5.1.7

Bug tracker

Have a bug? Please create an issue here on GitHub!

https://github.com/mark-rolich/RulersGuides.js/issues

Copyright and License

The MIT License (MIT)

Copyright (c) 2013 Mark Rolich

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Comments
  • Snap rules to DOM elements

    Snap rules to DOM elements

    Hey! Great stuff, love the bookmark functionality!

    One thing that would be even better would be a mode where the rules snap to DOM elements.

    Suggestion comes from here: https://news.ycombinator.com/item?id=6449883

    opened by victorb 5
  • How to create grid line for Particular div

    How to create grid line for Particular div

    Hi Mark., I working in your rulersguides.js. I create rulers for particular div refer FIDDLE.but i need to create grid line for that particular div not in body element.How to achieved it? Can you give proper guidelines to complete this issues?

    opened by 27viveks 3
  • Using the

    Using the "Show detailed info" feature

    Our site has been migrated to Wordpress. RulersGuides.js would be great for layout, except the horizontal ruler across the top of the page is almost covered by the WordPress admin toolbar. So, the little red menu icon for the rulers (top/ left) is covered and unusable.

    I could use the hot keys associated with the menu items but when I invoke "Cntrl Alt I" for the detailed information I get this Javascript error:

    "TypeError: 'null' is not an object (evaluating 'vRuler.style')"

    Here a screenshot of how the menu lays out in WordPress -- showing the errors (ignore the first two errors):

    snap_02

    If I could get the hot key combination to work the problem would be solved.

    Thanks,

    JH

    opened by harwooje 2
  • Make content zoomable, or add magnifier window

    Make content zoomable, or add magnifier window

    It's a great tool! But I want to put pixel ferfect guides. It's not easy to do now. Can you add some options to zoom the content? Or some little window magnifying the mouse area?

    If I want to make sure about positions or dimensions, nowdays I have to make a screenshot, paste it into PS, zoom in and use guides. With this I could forget that method.

    opened by davidzoli 2
  • Make ruler fixed to top/left on scroll

    Make ruler fixed to top/left on scroll

    When scrolling vertically up/down the page. The top x-axis ruler should always be visible. Similarly, when scrolling horizontally left/right the page. The left y-axis ruler should also be visible.

    Also, note that when scrolling, the ruler should still show the offset from the top left, (0,0). Using position: fixed will keep them on screen, but not display the correct offsets.

    opened by TheSharpieOne 2
  • How to add Grid line and rulers for particular div

    How to add Grid line and rulers for particular div

    Hi buddy, Here, I am struggle with to add rulers for particular inner div using this rulerguides.js.But i dont achieved it.Here i tried to add rulers for div like photoshop. My current changed script: var evt = new Event(),

    dragdrop    = new Dragdrop(evt),
    
    rg          = new RulersGuides(evt, dragdrop, document.getElementById('workarea'));
    
    I get this code for this issues :https://github.com/mark-rolich/RulersGuides.js/issues/11 How to changed ruler for div.
    opened by 27viveks 1
  • Fixing rulers to the window

    Fixing rulers to the window

    Changed the position->"absolute" for the class->".ruler" to->"fixed", for beetter usability on large pages, if you could scroll on the page vertical or horizontal. Otherwise you have to scroll to the top of a page and drag and drop each line for more than a page lenght.

    opened by AminZoubaa 1
  • Fix toggle

    Fix toggle

    When toggling the bookmarklet on and off, it basically changes the display of both .ruler elements from none to block and vice versa. Any chance you could change the display value of their parent (.rg-overlay) instead?

    Currently, it makes the site unsable as soon as you have enabled the bookmarklet once, even if you have used it again in order to turn it off. This because the full screen overlay remains and prevents the site below from being used.

    Using pointer-events: none could be a solution if you have some solid reasons not to move the show/hide to the parent.

    Thanks!

    opened by KittyGiraudel 1
  • Update ruler length on page re-size

    Update ruler length on page re-size

    With dynamic content, the page's height and/or width may change. The ruler may be too large or too small for the page based on the changing content. toggling the ruler does not seem to resolve this issue. It would be best if the ruler would update its size on the page's re-size event.

    Examples after re-sizing this page: image The ruler does not extend far enough

    image The ruler extends too far and makes the page wider.

    opened by TheSharpieOne 1
  • Clear/Remove grid

    Clear/Remove grid

    Allow for the grid to be cleared/removed without having to reload the page or drag each of the grid lines into the ruler.

    This would be useful in conjunction with #1

    opened by TheSharpieOne 0
  • can't create bookmarklets in safari mac os

    can't create bookmarklets in safari mac os

    added as address field javascript:(function(){var%20Event=function(){'use%20strict';this.attach=function(evtName,element,listener,capture){var%20evt='',useCapture=(capture===undefined)?true:capture,handler=null;if(window.addEventListener===undefined){evt='on'+evtName;handler=function(evt,listener){element.attachEvent(evt,listener);return%20listener;};}else{evt=evtName;handler=function(evt,listener,useCapture){element.addEventListener(evt,listener,useCapture);return%20listener;};}return%20handler.apply(element,[evt,function(ev){var%20e=ev||event,src=e.srcElement||e.target;listener(e,src);},useCapture]);};this.detach=function(evtName,element,listener,capture){var%20evt='',useCapture=(capture===undefined)?true:capture;if(window.removeEventListener===undefined){evt='on'+evtName;element.detachEvent(evt,listener);}else{evt=evtName;element.removeEventListener(evt,listener,useCapture);}};this.stop=function(evt){evt.cancelBubble=true;if(evt.stopPropagation){evt.stopPropagation();}};this.prevent=function(evt){if(evt.preventDefault){evt.preventDefault();}else{evt.returnValue=false;}};};var%20Dragdrop=function(evt){'use%20strict';var%20elem=null,started=0,self=this,moveHandler=null,doc=document.documentElement,body=document.body,gWidth=(document.body.scrollWidth%3Edocument.documentElement.clientWidth)?document.body.scrollWidth:document.documentElement.clientWidth,gHeight=Math.max(body.scrollHeight,body.offsetHeight,doc.clientHeight,doc.scrollHeight,doc.offsetHeight),move=function(e){var%20xDiff=e.clientX-elem.posX,yDiff=e.clientY-elem.posY,x=xDiff-(xDiff%elem.snap)+'px',y=yDiff-(yDiff%elem.snap)+'px';if(started===1){switch(elem.mode){case%200:elem.style.top=y;elem.style.left=x;break;case%201:elem.style.left=x;break;case%202:elem.style.top=y;break;}if(elem.mode!==2){if(xDiff%3C=elem.minX){elem.style.left=elem.minX+'px';}if(elem.offsetLeft+elem.offsetWidth%3E=elem.maxX){elem.style.left=(elem.maxX-elem.offsetWidth)+'px';}}if(elem.mode!==1){if(yDiff%3C=elem.minY){elem.style.top=elem.minY+'px';}if(elem.offsetTop+elem.offsetHeight%3E=elem.maxY){elem.style.top=(elem.maxY-elem.offsetHeight)+'px';}}elem.onMove(elem);}},start=function(e,src){if(src.className.indexOf('draggable')!==-1){evt.prevent(e);moveHandler=evt.attach('mousemove',document,move,true);started=1;elem=src;elem.posX=e.clientX-elem.offsetLeft;elem.posY=e.clientY-elem.offsetTop;if(elem.mode===undefined){self.set(elem);}elem.onStart(elem);if(elem.setCapture){elem.setCapture();}}},stop=function(){if(started===1){started=0;elem.onStop(elem);evt.detach('mousemove',document,moveHandler);if(elem.releaseCapture){elem.releaseCapture();}}};evt.attach('mousedown',document,start,false);evt.attach('mouseup',document,stop,false);this.start=start;this.set=function(element,elemOptions){var%20options=elemOptions||{};elem=(typeof%20element==='string')?document.getElementById(element):element;elem.mode=options.mode||0;elem.minX=options.minX||0;elem.maxX=options.maxX||gWidth;elem.minY=options.minY||0;elem.maxY=options.maxY||gHeight;elem.snap=options.snap||1;elem.onStart=options.onstart||function(){};elem.onMove=options.onmove||function(){};elem.onStop=options.onstop||function(){};elem.style.left=elem.offsetLeft+'px';elem.style.top=elem.offsetTop+'px';elem.unselectable='on';};};var%20RulersGuides=function(evt,dragdrop){'use%20strict';var%20doc=document.documentElement,body=document.body,wrapper=null,lockHandler=null,locked=1,hRuler=null,vRuler=null,menu=null,dialogs=[],snapDialog=null,openGridDialog=null,xSnap=0,ySnap=0,mode=2,guides={},guidesCnt=0,gUid='',rulerStatus=1,guideStatus=1,hBound=0,vBound=0,gridList=null,gridListLen=0,menuBtn=null,gInfoBlockWrapper=null,detailsStatus=0,domElements=[],domDimensions=[],resizeTimer=null,snapDom=0,cssText='html,body{margin:0;padding:0}.rg-overlay{position:absolute;top:0;left:0;overflow:hidden}.guide{position:absolute;top:0;left:0;z-index:9991;font-size:0}.guide.v{width:1px;height:7000px;border-right:solid%201px%20#00f;cursor:col-resize}.guide.h{width:3000px;height:1px;border-bottom:solid%201px%20#00f;cursor:row-resize}.info{width:50px;height:25px;line-height:25px;text-align:center;position:relative;font-size:13px;background-color:#eee;border:solid%201px%20#ccc;color:#000}.guide.v%20.info{left:2px}.guide.h%20.info{top:2px}.unselectable{-moz-user-select:-moz-none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.ruler{background-color:#ccc;position:absolute;top:0;left:0;z-index:9990}.ruler%20.label{font:12px%20Arial;color:#000}.ruler,.ruler%20span{font-size:0}.ruler.h{width:3000px;left:-1px;padding-top:14px;border-bottom:solid%201px%20#000}.ruler.v{height:7000px;top:-1px;padding-left:16px;width:25px;border-right:solid%201px%20#000}.ruler.h%20span{border-left:solid%201px%20#999;height:9px;width:1px;vertical-align:bottom;display:inline-block;*display:inline;zoom:1}.ruler.v%20span{display:block;margin-left:auto;margin-right:0;border-top:solid%201px%20#999;width:9px;height:1px}.ruler.v%20span.major{border-top:solid%201px%20#000;width:13px}.ruler.v%20span.milestone{position:relative;border-top:solid%201px%20#000;width:17px}.ruler.v%20span.label{border:0;font-size:9px;position:absolute;text-align:center;width:9px}.ruler.h%20span.major{border-left:solid%201px%20#000;height:13px}.ruler.h%20span.milestone{position:relative;border-left:solid%201px%20#000;height:17px}.ruler.h%20span.label{border:0;font-size:9px;position:absolute;text-align:center;top:-14px;width:9px}.ruler.h%20.l10{left:-5px}.ruler.h%20.l100{left:-7px}.ruler.h%20.l1000{left:-10px}.ruler.v%20.l10,.ruler.v%20.l100,.ruler.v%20.l1000{top:-7px}.ruler.v%20.l10{left:-12px}.ruler.v%20.l100{left:-17px}.ruler.v%20.l1000{left:-23px}.menu-btn{position:fixed;left:3px;top:2px;line-height:9px;z-index:9998;width:20px;height:20px;background-color:red;opacity:.5;font-size:20px;text-align:left;color:#fff;font-weight:700;cursor:pointer;border-radius:2px}.rg-menu{position:fixed;top:22px;left:3px;padding:0;margin:0;list-style:0;display:none;font:13px%20Arial;z-index:9999;box-shadow:2px%202px%2010px%20#ccc}.rg-menu%20li{border-bottom:solid%201px%20#999;padding:0}.rg-menu%20a{background-color:#777;display:block;padding:5px;text-decoration:none;color:#fff;line-height:18px}.rg-menu%20a:hover,.rg-menu%20a.selected{color:#fff;background-color:#3b94ec}.rg-menu%20a.disabled{color:#ccc}.rg-menu%20.desc{display:inline-block;width:170px}.dialog{position:fixed;background-color:#777;z-index:9999;color:#fff;font-size:13px;display:none;box-shadow:2px%202px%2010px%20#ccc}.dialog%20button{border:0;color:#333;cursor:pointer;background-color:#eaeaea;background-image:linear-gradient(#fafafa,#eaeaea);background-repeat:repeat-x;border-radius:3px;text-shadow:0%201px%200%20rgba(255,255,255,.9)}.dialog%20input,.dialog%20select,.dialog%20button{font-size:13px;margin:3px;padding:3px}.dialog%20.title-bar{padding:5px;background-color:#aaa;font-weight:700}.dialog%20.wrapper{padding:10px}.open-dialog%20select,.open-dialog%20button{float:left;display:block}.open-dialog%20.ok-btn,.open-dialog%20.cancel-btn{margin:10px%203px}.open-dialog%20.ok-btn{clear:both}.snap-dialog%20label{font-weight:700;padding:3px}.snap-dialog%20.ok-btn{margin-left:18px}.snap-dialog%20.ok-btn,.snap-dialog%20.cancel-btn{margin-top:10px}.snap-dialog%20.rg-y-label{margin-left:10px}#rg-x-snap,#rg-y-snap{width:50px}.info-block-wrapper{position:absolute;z-index:9989}.info-block{position:absolute;text-align:left}.info-block.even{background:0;background-color:rgba(0,0,255,.2);-ms-filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#330000FF,%20endColorstr=#330000FF);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#330000FF,%20endColorstr=#330000FF);zoom:1}.info-block.odd{background:0;background-color:rgba(255,0,0,.2);-ms-filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#33FF0000,%20endColorstr=#33FF0000);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#33FF0000,%20endColorstr=#33FF0000);zoom:1}.info-block-txt{padding:5px;display:inline-block;vertical-align:top;background-color:#777;color:#fff;font-size:13px;*display:inline;zoom:1}',Ruler=function(type,size){var%20ruler=document.createElement('div'),i=0,span=document.createElement('span'),label=null,labelTxt=null,spanFrag=document.createDocumentFragment(),cnt=Math.floor(size/2);ruler.className='ruler%20'+type+'%20unselectable';for(i;i<cnt;i=i+1){span=span.cloneNode(false);if(i%%2025===0){span.className='milestone';if(i>0){label=span.cloneNode(false);label.className='label';if(i<50){label.className+='%20l10';}else%20if(i>=50&&i<500){label.className+='%20l100';}else%20if(i>=500){label.className+='%20l1000';}labelTxt=document.createTextNode(i*2);label.appendChild(labelTxt);span.appendChild(label);}span.className='milestone';}else%20if(i%5===0){span.className='major';}else{span.className='';span.removeAttribute('class');}spanFrag.appendChild(span);}ruler.appendChild(spanFrag);return%20ruler;},getWindowSize=function(){var%20w=Math.max(body.scrollWidth,body.offsetWidth,doc.clientWidth,doc.scrollWidth,doc.offsetWidth),h=Math.max(body.scrollHeight,body.offsetHeight,doc.clientHeight,doc.scrollHeight,doc.offsetHeight);return[w,h];},getScrollPos=function(){var%20t=Math.max(doc.scrollTop,body.scrollTop),l=Math.max(doc.scrollLeft,body.scrollLeft);return[t,l];},getScrollSize=function(){var%20w=Math.max(doc.scrollWidth,body.scrollWidth),h=Math.max(doc.scrollHeight,body.scrollHeight);return[w,h];},closeAllDialogs=function(){var%20i=0;for(i;i<dialogs.length;i=i+1){dialogs[i].close();}},removeInboundGuide=function(guide,gUid){var%20scrollPos=getScrollPos();if(rulerStatus===1&&guideStatus===1&&((guide.className==='guide%20h%20draggable'&&guide.offsetTop<hBound+scrollPos[0])||(guide.className==='guide%20v%20draggable'&&guide.offsetLeft<vBound+scrollPos[1]))){wrapper.removeChild(guide);delete%20guides[gUid];guidesCnt=guidesCnt-1;}},removeInboundGuides=function(){var%20i;for(i%20in%20guides){if(guides.hasOwnProperty(i)){removeInboundGuide(guides[i],i);}}},toggleGuides=function(){var%20i;guideStatus=1-guideStatus;for(i%20in%20guides){if(guides.hasOwnProperty(i)){guides[i].style.display=(guideStatus===1)?'block':'none';}}if(guideStatus===1){wrapper.style.display='block';}},toggleRulers=function(){rulerStatus=1-rulerStatus;if(rulerStatus===1){vRuler.style.display='block';hRuler.style.display='block';wrapper.style.display='block';removeInboundGuides();}else{vRuler.style.display='none';hRuler.style.display='none';}},removeGrid=function(gridName){if(gridList[gridName]!==undefined){delete%20gridList[gridName];window.localStorage.setItem('RulersGuides',JSON.stringify(gridList));gridListLen=gridListLen-1;}},deleteGuides=function(){var%20i;if(guidesCnt>0){for(i%20in%20guides){if(guides.hasOwnProperty(i)){wrapper.removeChild(guides[i]);delete%20guides[i];guidesCnt=guidesCnt-1;}}gInfoBlockWrapper.style.display='none';}},renderGrid=function(gridName){if(gridList[gridName]!==undefined){var%20grid=gridList[gridName],guideId=null,guideElem=null;deleteGuides();for(guideId%20in%20grid){if(grid.hasOwnProperty(guideId)){guideElem=document.createElement('div');guideElem.id=guideId;guideElem.className=grid[guideId].cssClass;guideElem.style.cssText=grid[guideId].style;wrapper.appendChild(guideElem);guides[guideId]=guideElem;guidesCnt=guidesCnt+1;}}}},OpenGridDialog=function(){var%20dialog=null,self=this,select=null,renderSelect=function(insertOrUpdate){var%20gridName,options='',i;gridListLen=0;if(window.localStorage){gridList=JSON.parse(window.localStorage.getItem('RulersGuides'));for(i%20in%20gridList){if(gridList.hasOwnProperty(i)){gridListLen=gridListLen+1;}}}if(insertOrUpdate===0){select=document.createElement('select');select.id='grid-list';}if(gridListLen>0){for(gridName%20in%20gridList){if(gridList.hasOwnProperty(gridName)){options+='<option>'+gridName+'</option>';}}select.innerHTML=options;}return%20select;};this.render=function(){if(dialog===null){dialog=document.createElement('div');select=renderSelect(0);var%20text=document.createTextNode(''),titleBar=dialog.cloneNode(false),dialogWrapper=dialog.cloneNode(false),okBtn=document.createElement('button'),cancelBtn=okBtn.cloneNode(false),delBtn=okBtn.cloneNode(false),titleBarTxt=text.cloneNode(false),okBtnTxt=text.cloneNode(false),cancelBtnTxt=text.cloneNode(false),delBtnTxt=text.cloneNode(false);titleBarTxt.nodeValue='Open%20grid';okBtnTxt.nodeValue='OK';cancelBtnTxt.nodeValue='Cancel';delBtnTxt.nodeValue='Delete';dialog.className='dialog%20open-dialog';titleBar.className='title-bar';dialogWrapper.className='wrapper';okBtn.className='ok-btn';cancelBtn.className='cancel-btn';delBtn.className='del-btn';titleBar.appendChild(titleBarTxt);okBtn.appendChild(okBtnTxt);cancelBtn.appendChild(cancelBtnTxt);delBtn.appendChild(delBtnTxt);dialogWrapper.appendChild(select);dialogWrapper.appendChild(delBtn);dialogWrapper.appendChild(okBtn);dialogWrapper.appendChild(cancelBtn);dialog.appendChild(titleBar);dialog.appendChild(dialogWrapper);body.appendChild(dialog);evt.attach('click',delBtn,function(){if(window.confirm('Are%20you%20sure%20?')){if(select.options.length>0){removeGrid(select.options[select.selectedIndex].value);select.removeChild(select.options[select.selectedIndex]);}if(select.options.length===0){self.close();}}});evt.attach('click',okBtn,function(){renderGrid(select.value);self.close();});evt.attach('click',cancelBtn,function(){self.close();});}};this.render();this.open=function(){closeAllDialogs();renderSelect(1);if(gridListLen>0){dialog.style.display='block';dialog.style.left=((doc.clientWidth-dialog.clientWidth)/2)+'px';dialog.style.top=((doc.clientHeight-dialog.clientHeight)/2)+'px';}};this.close=function(){dialog.style.display='none';};},toggleRulersLock=function(){if(locked===0){if(lockHandler!==null){evt.detach('scroll',window,lockHandler);}}else{lockHandler=evt.attach('scroll',window,function(){var%20pos=getScrollPos(),size=getScrollSize();hRuler.style.top=pos[0]+'px';wrapper.style.height=size[1]+'px';vRuler.style.left=pos[1]+'px';wrapper.style.width=size[0]+'px';});}locked=1-locked;},saveGrid=function(){var%20data={},gridData={},i,gridName='';while(gridName===''&&guidesCnt>0){gridName=window.prompt('Save%20grid%20as');if(gridName!==''&&gridName!==false&&gridName!==null&&window.localStorage){for(i%20in%20guides){if(guides.hasOwnProperty(i)){gridData[i]={'cssClass':guides[i].className,'style':guides[i].style.cssText};}}if(window.localStorage.getItem('RulersGuides')!==null){data=JSON.parse(window.localStorage.getItem('RulersGuides'));}data[gridName]=gridData;window.localStorage.setItem('RulersGuides',JSON.stringify(data));gridListLen=gridListLen+1;}}},showDetailedInfo=function(){var%20i,j=0,hGuides=[],vGuides=[],scrollSize=getScrollSize(),infoBlockWrapper=document.createElement('div'),infoFrag=document.createDocumentFragment(),infoBlock=infoBlockWrapper.cloneNode(false),infoBlockTxt=infoBlockWrapper.cloneNode(false),infoData1=document.createTextNode(''),infoData2=infoData1.cloneNode(false),text='',br=document.createElement('br');for(i%20in%20guides){if(guides.hasOwnProperty(i)){if(guides[i].type==='h'){hGuides.push(guides[i].y);}else{vGuides.push(guides[i].x);}}}vGuides.unshift(0);vGuides.push(scrollSize[0]);hGuides.unshift(0);hGuides.push(scrollSize[1]);vGuides=vGuides.sort(function(a,b){return%20a-b;});hGuides=hGuides.sort(function(a,b){return%20a-b;});for(i=0;i<hGuides.length-1;i=i+1){j=0;for(j;j<vGuides.length-1;j=j+1){infoBlock=infoBlock.cloneNode(false);infoBlockTxt=infoBlockTxt.cloneNode(false);infoData1=infoData1.cloneNode(false);infoData2=infoData2.cloneNode(false);br=br.cloneNode();infoBlockWrapper.className='info-block-wrapper';infoBlock.className='info-block';infoBlockTxt.className='info-block-txt';infoBlock.className+=((i%2!==0&&j%2!==0)||(i%2===0&&j%2===0))?'%20even':'%20odd';infoBlock.style.top=hGuides[i]+'px';infoBlock.style.left=vGuides[j]+'px';infoBlock.style.width=(vGuides[j+1]-vGuides[j])+'px';infoBlock.style.height=(hGuides[i+1]-hGuides[i])+'px';text=(vGuides[j+1]-vGuides[j])+'%20x%20'+(hGuides[i+1]-hGuides[i]);infoData1.nodeValue=text;text=hGuides[i]+'%20:%20'+vGuides[j];infoData2.nodeValue=text;infoBlockTxt.appendChild(infoData1);infoBlockTxt.appendChild(br);infoBlockTxt.appendChild(infoData2);infoBlock.appendChild(infoBlockTxt);infoBlockTxt.style.marginTop=(i===0)?'31px':'0';infoBlockTxt.style.marginLeft=(j===0)?'42px':'0';infoFrag.appendChild(infoBlock);}}infoBlockWrapper.appendChild(infoFrag);if(detailsStatus===1){wrapper.replaceChild(infoBlockWrapper,gInfoBlockWrapper);gInfoBlockWrapper=infoBlockWrapper;}else{gInfoBlockWrapper.style.display='none';}},calculateDomDimensions=function(){var%20x=[],y=[],dm=[],i=0,len=domElements.length,findDimensions=function(elem){var%20t=0,l=0,w=elem.offsetWidth,h=elem.offsetHeight;while(elem){l+=(elem.offsetLeft-elem.scrollLeft+elem.clientLeft);t+=(elem.offsetTop-elem.scrollTop+elem.clientTop);elem=elem.offsetParent;}return[l,t,l+w,t+h];},getUnique=function(arr){var%20u={},a=[],idx=0,arrLen=arr.length;for(idx;idx<arrLen;idx=idx+1){if(u.hasOwnProperty(arr[idx])===false){a.push(arr[idx]);u[arr[idx]]=1;}}return%20a;};for(i;i<len;i=i+1){dm=findDimensions(domElements[i]);x.push(dm[0]);x.push(dm[2]);y.push(dm[1]);y.push(dm[3]);}x=getUnique(x).sort(function(a,b){return%20a-b;});y=getUnique(y).sort(function(a,b){return%20a-b;});return[x,y];},Menu=function(){var%20menuList=null,status=0,toggles={},menuItemsList=[{'text':'Hide%20rulers','hotkey':'Ctrl%20+%20Alt%20+%20R','alias':'rulers'},{'text':'Hide%20guides','hotkey':'Ctrl%20+%20Alt%20+%20G','alias':'guides'},{'text':'Hide%20all','hotkey':'Ctrl%20+%20Alt%20+%20A','alias':'all'},{'text':'Unlock%20rulers','hotkey':'Ctrl%20+%20Alt%20+%20L','alias':'lock'},{'text':'Clear%20all%20guides','hotkey':'Ctrl%20+%20Alt%20+%20D','alias':'clear'},{'text':'Open%20grid','hotkey':'Ctrl%20+%20Alt%20+%20O','alias':'open'},{'text':'Save%20grid','hotkey':'Ctrl%20+%20Alt%20+%20G','alias':'save'},{'text':'Snap%20to','hotkey':'Ctrl%20+%20Alt%20+%20C','alias':'snap'},{'text':'Show%20detailed%20info','hotkey':'Ctrl%20+%20Alt%20+%20I','alias':'details'},{'text':'Snap%20to%20DOM','hotkey':'Ctrl%20+%20Alt%20+%20E','alias':'snapdom'}],i=0;this.render=function(){menuBtn=document.createElement('div');menuBtn.className='menu-btn%20unselectable';menuBtn.appendChild(document.createTextNode('\u250C'));menuList=document.createElement('ul');menuList.className='rg-menu';var%20menuItems=document.createDocumentFragment(),li=document.createElement('li'),liLink=document.createElement('a'),liDesc=document.createElement('span'),liHotKey=liDesc.cloneNode(false),liDescTxt=document.createTextNode(''),liHotKeyTxt=liDescTxt.cloneNode(false);liLink.href='javascript:';liDesc.className='desc';liHotKey.className='hotkey';for(i;i<menuItemsList.length;i=i+1){li=li.cloneNode(false);liLink=liLink.cloneNode(false);liDesc=liDesc.cloneNode(false);liHotKey=liHotKey.cloneNode(false);liDescTxt=liDescTxt.cloneNode(false);liHotKeyTxt=liHotKeyTxt.cloneNode(false);liDescTxt.nodeValue=menuItemsList[i].text;liHotKeyTxt.nodeValue=menuItemsList[i].hotkey;liDesc.appendChild(liDescTxt);liHotKey.appendChild(liHotKeyTxt);liLink.appendChild(liDesc);liLink.appendChild(liHotKey);li.appendChild(liLink);menuItems.appendChild(li);toggles[menuItemsList[i].alias]={obj:liLink,txt:liDescTxt};}evt.attach('mousedown',toggles.rulers.obj,function(){toggleRulers();});evt.attach('mousedown',toggles.guides.obj,function(){toggleGuides();});evt.attach('mousedown',toggles.all.obj,function(){if(rulerStatus===1||guideStatus===1){rulerStatus=guideStatus=1;wrapper.style.display='none';}else{rulerStatus=guideStatus=0;wrapper.style.display='block';}toggleRulers();toggleGuides();});evt.attach('mousedown',toggles.lock.obj,function(){toggleRulersLock();});evt.attach('mousedown',toggles.clear.obj,function(){deleteGuides();});evt.attach('mousedown',toggles.open.obj,function(){openGridDialog.open();});evt.attach('mousedown',toggles.save.obj,function(){saveGrid();});evt.attach('mousedown',toggles.snap.obj,function(){snapDialog.open();});evt.attach('mousedown',toggles.details.obj,function(){detailsStatus=1-detailsStatus;showDetailedInfo();});evt.attach('mousedown',toggles.snapdom.obj,function(){snapDom=1-snapDom;if(snapDom===1){domDimensions=calculateDomDimensions();}});menuList.appendChild(menuItems);body.appendChild(menuBtn);body.appendChild(menuList);evt.attach('mousedown',menuBtn,function(){toggles.rulers.txt.nodeValue=(rulerStatus===1)?'Hide%20rulers':'Show%20rulers';if(guidesCnt>0){toggles.guides.obj.className='';toggles.clear.obj.className='';toggles.save.obj.className='';toggles.guides.txt.nodeValue=(guideStatus===1)?'Hide%20guides':'Show%20guides';}else{toggles.guides.obj.className='disabled';toggles.clear.obj.className='disabled';toggles.save.obj.className='disabled';}toggles.all.txt.nodeValue=(rulerStatus===1||guideStatus===1)?'Hide%20all':'Show%20all';toggles.lock.txt.nodeValue=(locked===0)?'Lock%20rulers':'Unlock%20rulers';toggles.details.txt.nodeValue=(detailsStatus===0)?'Show%20detailed%20info':'Hide%20detailed%20info';toggles.snapdom.txt.nodeValue=(snapDom===0)?'Snap%20to%20DOM':'Turn%20off%20snap%20to%20DOM';toggles.open.obj.className=(gridListLen>0)?'':'disabled';menuList.style.display=(status===0)?'inline-block':'none';status=1-status;});};this.render();this.close=function(){if(menuList!==null){menuList.style.display='none';status=0;}};},SnapDialog=function(){var%20dialog=null,xInput=null,yInput=null,self=this;this.render=function(){if(dialog===null){dialog=document.createElement('div');xInput=document.createElement('input');yInput=xInput.cloneNode(false);var%20text=document.createTextNode(''),okBtn=document.createElement('button'),xLabel=document.createElement('label'),titleBar=dialog.cloneNode(false),dialogWrapper=dialog.cloneNode(false),inputWrapper=dialog.cloneNode(false),btnWrapper=dialog.cloneNode(false),resetBtn=okBtn.cloneNode(false),cancelBtn=okBtn.cloneNode(false),yLabel=xLabel.cloneNode(false),titleBarTxt=text.cloneNode(false),xLabelTxt=text.cloneNode(false),yLabelTxt=text.cloneNode(false),okBtnTxt=text.cloneNode(false),resetBtnTxt=text.cloneNode(false),cancelBtnTxt=text.cloneNode(false);titleBarTxt.nodeValue='Snap%20guides%20to';xLabelTxt.nodeValue='X';yLabelTxt.nodeValue='Y';okBtnTxt.nodeValue='OK';resetBtnTxt.nodeValue='Reset';cancelBtnTxt.nodeValue='Cancel';dialog.className='dialog%20snap-dialog';titleBar.className='title-bar';dialogWrapper.className='wrapper';xLabel.className='rg-x-label';xLabel.setAttribute('for','rg-x-snap');yLabel.className='rg-y-label';yLabel.setAttribute('for','rg-y-snap');xInput.setAttribute('type','number');xInput.value='100';xInput.id='rg-x-snap';xInput.setAttribute('type','number');yInput.value='100';yInput.id='rg-y-snap';okBtn.className='ok-btn';resetBtn.className='reset-btn';cancelBtn.className='cancel-btn';titleBar.appendChild(titleBarTxt);xLabel.appendChild(xLabelTxt);yLabel.appendChild(yLabelTxt);okBtn.appendChild(okBtnTxt);resetBtn.appendChild(resetBtnTxt);cancelBtn.appendChild(cancelBtnTxt);inputWrapper.appendChild(xLabel);inputWrapper.appendChild(xInput);inputWrapper.appendChild(yLabel);inputWrapper.appendChild(yInput);inputWrapper.appendChild(resetBtn);btnWrapper.appendChild(okBtn);btnWrapper.appendChild(cancelBtn);dialogWrapper.appendChild(inputWrapper);dialogWrapper.appendChild(btnWrapper);dialog.appendChild(titleBar);dialog.appendChild(dialogWrapper);body.appendChild(dialog);evt.attach('mousedown',okBtn,function(){xSnap=parseInt(xInput.value,10);ySnap=parseInt(yInput.value,10);self.close();});evt.attach('mousedown',resetBtn,function(){xSnap=0;ySnap=0;self.close();});evt.attach('mousedown',cancelBtn,function(){self.close();});}};this.render();this.open=function(){closeAllDialogs();dialog.style.display='block';dialog.style.left=((doc.clientWidth-dialog.clientWidth)/2)+'px';dialog.style.top=((doc.clientHeight-dialog.clientHeight)/2)+'px';};this.close=function(){dialog.style.display='none';};},prepare=function(){var%20style=document.createElement('style'),size=getWindowSize(),elements=document.getElementsByTagName('*'),len=elements.length,i=0;for(i;i<len;i=i+1){domElements.push(elements[i]);}style.setAttribute('type','text/css');if(style.styleSheet){style.styleSheet.cssText=cssText;}else{style.appendChild(document.createTextNode(cssText));}body.appendChild(style);setTimeout(function(){hRuler=new%20Ruler('h',3000);vRuler=new%20Ruler('v',7000);wrapper=document.createElement('div');gInfoBlockWrapper=wrapper.cloneNode(false);wrapper.className='rg-overlay';gInfoBlockWrapper.className='info-block-wrapper';wrapper.style.width=(size[0])+'px';wrapper.style.height=(size[1])+'px';wrapper.appendChild(hRuler);wrapper.appendChild(vRuler);wrapper.appendChild(gInfoBlockWrapper);body.appendChild(wrapper);domDimensions=calculateDomDimensions();menu=new%20Menu();snapDialog=new%20SnapDialog();openGridDialog=new%20OpenGridDialog();dialogs=[snapDialog,openGridDialog];},10);};prepare();this.status=1;this.disable=function(){if(vRuler!==null){deleteGuides();vRuler.style.display='none';hRuler.style.display='none';wrapper.style.display='none';menuBtn.style.display='none';}rulerStatus=0;this.status=0;};this.enable=function(){if(vRuler!==null){vRuler.style.display='block';hRuler.style.display='block';wrapper.style.display='block';menuBtn.style.display='block';}rulerStatus=1;this.status=1;};evt.attach('mousedown',document,function(e,src){var%20x=e.clientX,y=e.clientY,guide=null,guideInfo=null,guideInfoText=null,scrollPos=getScrollPos(),snap=0;if(src.className.indexOf('menu-btn')===-1){menu.close();}if(vBound===0){vBound=vRuler.offsetWidth;hBound=hRuler.offsetHeight;}if(((x>vBound&&y<hBound)||(y>hBound&&x<vBound))&&rulerStatus===1){guide=document.createElement('div');guideInfo=guide.cloneNode(false);guideInfoText=document.createTextNode('');gUid='guide-'+guidesCnt;guideInfo.className='info';guideInfo.appendChild(guideInfoText);guide.appendChild(guideInfo);if(x>vBound&&y<hBound){guide.className='guide%20h%20draggable';guide.style.top=(e.clientY+scrollPos[0])+'px';guideInfo.style.left=(x+scrollPos[1]+10)+'px';guide.type='h';snap=ySnap;mode=2;}else%20if(y>hBound&&x<vBound){guide.className='guide%20v%20draggable';guide.style.left=(x+scrollPos[1])+'px';guideInfo.style.top=((y+scrollPos[0])-35)+'px';guide.type='v';snap=xSnap;mode=1;}guide.id=gUid;guide.info=guideInfo;guide.text=guideInfoText;guide.x=0;guide.y=0;guides[gUid]=guide;wrapper.appendChild(guide);dragdrop.set(guide,{mode:mode,onstart:function(elem){var%20text=(elem.mode===1)?parseInt(elem.style.left,10)+2:parseInt(elem.style.top,10)+2;elem.text.nodeValue=text+'px';if(elem.over!==undefined){evt.detach('mouseover',elem,elem.over);evt.detach('mouseout',elem,elem.out);}},onmove:function(elem){var%20text='',pos=0,dims=[],len=0,i=0;pos=(elem.mode===1)?elem.style.left:elem.style.top;pos=parseInt(pos,10);if(snapDom===1){dims=domDimensions[elem.mode-1];for(i,len=dims.length;i<len;i=i+1){if(pos<=dims[i]){pos=dims[i];break;}}}text=pos+'px';if(elem.mode===1){elem.style.left=(pos-2)+'px';elem.x=pos;}else{elem.style.top=(pos-2)+'px';elem.y=pos;}elem.text.nodeValue=text;},onstop:function(elem){elem.over=evt.attach('mouseover',elem,function(e,src){if(src.className==='guide%20v%20draggable'){elem.info.style.top=((e.clientY+scrollPos[0])-35)+'px';}else%20if(src.className==='guide%20h%20draggable'){elem.info.style.left=(e.clientX+scrollPos[1]+10)+'px';}elem.info.style.display='block';});elem.out=evt.attach('mouseout',elem,function(){elem.info.style.display='none';});},snap:snap});dragdrop.start(e,guide);guidesCnt=guidesCnt+1;}});evt.attach('mouseup',document,function(e,src){removeInboundGuide(src,src.id);if(detailsStatus===1){showDetailedInfo();}});evt.attach('keyup',document,function(e){if(e.ctrlKey===true&&e.altKey===true){switch(e.keyCode){case%2083:saveGrid();break;case%2082:toggleRulers();break;case%2079:openGridDialog.open();break;case%2076:toggleRulersLock();break;case%2073:detailsStatus=1-detailsStatus;showDetailedInfo();break;case%2071:toggleGuides();break;case%2069:snapDom=1-snapDom;if(snapDom===1){domDimensions=calculateDomDimensions();}break;case%2068:deleteGuides();break;case%2067:snapDialog.open();break;case%2065:if(rulerStatus===1||guideStatus===1){rulerStatus=guideStatus=1;wrapper.style.display='none';}else{rulerStatus=guideStatus=0;wrapper.style.display='block';}toggleRulers();toggleGuides();break;}}});evt.attach('resize',window,function(){var%20size=getWindowSize();wrapper.style.width=size[0]+'px';wrapper.style.height=size[1]+'px';if(resizeTimer!==null){window.clearTimeout(resizeTimer);}if(snapDom===1){resizeTimer=window.setTimeout(function(){domDimensions=calculateDomDimensions();},100);}});};var%20evt=new%20Event(),dragdrop=new%20Dragdrop(evt);if(window.rg===undefined){window.rg=new%20RulersGuides(evt,dragdrop);window.rg.status=0;}if(window.rg.status===1){window.rg.disable();}else{window.rg.enable();}})()

    but nothing happened when i click it?

    opened by v3nt 0
  • Top guide position issue

    Top guide position issue

    Hi, thank you for making such a wonderful ruler script. But there is a small issue that i am facing in the script. In my application, the ruler comes in a portion of page. The div that contains the ruler, have left and top properties. When getting guide from top, the click position always remains page top. but left side is working fine.

    opened by abhilashasokan 1
  • Can't delete individual guide line

    Can't delete individual guide line

    Hi, thank you for making such a wonderful ruler script. It works fine all leading browsers. Can you please add a function to delete individual guide line. Thank you

    opened by shamseerazeez 1
  • Ruler guide in svg editor

    Ruler guide in svg editor

    HI, This was amazing js to help me lot. How to use ruler guide in svg editor.But in svg editor already having rules with zoom functionality. I want to integrate in draggable guides of verticle and horizontal to svg rulers.Can you please help me.

    opened by thirupathia 0
Owner
Mark Rolich
Mark Rolich
A lightweight Adobe Photoshop .psd/.psb file parser in typescript with zero-dependency for WebBrowser and NodeJS

@webtoon/psd A lightweight Adobe Photoshop .psd/.psb file parser in typescript with zero-dependency for WebBrowser and NodeJS Browser Support Chrome F

null 830 Jan 1, 2023
A simple interface module that creates password-policy for your application.

This module is a simple alternate to creating complex native Regex, or tidious multidimensional checks on password-string to check required elements.

Snigdh Shourya 3 Oct 27, 2022
Chappe - 🧑‍💻 Developer Docs builder. Write guides in Markdown and references in API Blueprint. Comes with a built-in search engine.

Chappe Developer Docs builder. Write guides in Markdown and references in API Blueprint. Comes with a built-in search engine. Chappe is a Developer Do

Valerian Saliou 146 Jan 1, 2023
🧑‍💻 Developer Docs builder. Write guides in Markdown and references in API Blueprint. Comes with a built-in search engine.

Developer Docs builder. Write guides in Markdown and references in API Blueprint. Comes with a built-in search engine. Chappe is a Developer Docs buil

Crisp (OSS) 146 Jan 1, 2023
The awesomebooks project is a simple list, but separated into 3 parts and given a retro feel. The main page is where we can add books, and on another page we can see the list, and remove items. There is also a "contact-us" page.

Awesome Books This is the restructured version of the famous awesome-books project! Here you can find JavaScript broken into modules, using import-exp

Matt Gombos 12 Nov 15, 2022
A work-in-progress HTML sanitizer that strives for: performance like window.Sanitizer, readiness like DOMPurify, and ability to run in a WebWorker like neither of those.

Amuchina A work-in-progress HTML sanitizer that strives for: performance like window.Sanitizer, readiness like DOMPurify, and ability to run in a WebW

Fabio Spampinato 9 Sep 17, 2022
This package creates embeds and buttons in a very simple way using the whatsapp-web.js module for whatsapp

This package creates embeds and buttons in a very simple way using the whatsapp-web.js module for whatsapp

DeathAbyss 17 Jan 3, 2023
example app that creates a new player in Spotify Connect to play music from in the browse using Spotify Web Playback SDK.

Spotify Web Playback SDK Demo Requirements User must have Spotify Premium, DRM & EME supported and JavaScript enabled Web Browser. License Copyright 2

Sijey 8 Jul 20, 2022
A pure JavaScript Web Page to retrieve real-time OTP through a web page and generate/scan QR codes.

2FA-Solver A pure JavaScript Web Page to retrieve real-time OTP through a web page and generate/scan QR codes. It can be used as an offline web page b

Yuthan K 8 Dec 7, 2022
This single-page application displays a site where users can add/remove books from an interface and navigate between sections using ES6 Js.

Awesome Books - ES6 Web app that allows to add and remove book's data using Javascript and ES6 conventions. Built With HTML CSS Javascript ES6 Prerequ

Romina Patiño 5 Aug 19, 2022
The ManageYourCompany 📈 project is a project that creates, deletes, updates companies, units and assets.

The ManageYourCompany ?? project is a project that creates, deletes, updates companies, units and assets. The rule is that every company has several units and the units have several assets, these assets are machines with several fields: Name, status, person in charge, image, among others... This is a project in order to exercise my Backend skills with NodeJs and front with react.

Bruno da Silva Leite 2 Feb 9, 2022
🤖 An action that fetches the list of malicious domains on Discord in different providers and creates/updates a JSON file with them from time to time.

Discord Guardian Action ??  This action fetches the list of malicious domains on Discord in different providers and creates/updates a JSON file with t

Dalton Menezes 7 Nov 30, 2022
Visualize the Directed Acyclic Graph that Git creates to connect Commit, Tree and Blob objects internally.

Git Graph Visualize the Directed Acyclic Graph that Git creates to connect Commit, Tree and Blob objects. Hosted at HarshKapadia2.github.io/git-graph.

Harsh Kapadia 15 Aug 21, 2022
A self-hosted Thumbnail generator/finder which creates thumbnails based on folder names and google search results.

Thumba A self hosted Thumbnail generator/finder which creates thumbnails based on folder names and google search results. Description This project use

Norbert Takács 20 Dec 15, 2022
3D Infinite Art Gallery! This pulls from Reddit's r/Art and creates a procedural infinite art gallery from random (sfw-only) posts.

Infinite-Art-Gallery Click for Demo! 3D Infinite Procedurally-Generated Art Gallery! This pulls from Reddit's r/Art and creates a procedural infinite

Austin 33 Dec 15, 2022
A jQuery plugin that creates a countdown timer in years, months, days, hours and seconds in the form a bunch of rotating 3d cubes

CountdownCube is a jQuery plugin that is in the form of a bunch of rotating 3D cubes. It uses CSS transitions to create the 3D rotating cube effects.

null 16 Mar 6, 2022
VSCode extension that creates overlay for your Broadcasting Software of choice.

BSOverlay VSCode extension that creates an overlay for your Broadcasting Software of choice. Documentation Please refer to the Wiki Section. Installin

chocoearly44 4 Sep 30, 2022
Select creates a dropdown list of items with the selected item in closed view.

Native Base Select ?? This module includes a customizable multi-select and a single select component for Native Base. The package is both Android and

Blump Tech 3 Dec 25, 2022
An obsidian plugin that creates tomorrows daily note for preemtive planning.

Tomorrow's Daily Note An Obsidian plugin that creates tomorrows daily note for preemtive planning. Requirements Obsidian v0.12.0+. Daily notes plugin

Will Olson 12 Sep 24, 2022