Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf0891c0

Browse files
committed
Responsive Helper plugin v0.1 added
1 parent3bce2a8 commitf0891c0

File tree

2 files changed

+392
-0
lines changed

2 files changed

+392
-0
lines changed

‎responsive-helper/icon.png‎

996 Bytes
Loading
Lines changed: 392 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,392 @@
1+
// Responsive Helper plugin to assist with responsive design breakpoints in the previewWindow, with CSS output & overrides
2+
// Variation of the Brackets Response plugin idea at https://github.com/kidwm/brackets-response
3+
// by Matt Pass as an ICEcoder plugin
4+
5+
top.ICEcoder.doResponsive=function(){
6+
7+
// Set our initial values
8+
if("undefined"===typeofbreakPoints){
9+
// Array to contain breakpoint px values, this current breakpoint and the template for media queries
10+
breakPoints=[];
11+
thisBreakPoint=0;
12+
mediaQueryTemplate="@media only screen and (max-width: [[[WIDTH]]]) {";
13+
}
14+
15+
// Init the plugin if we have a target window
16+
if(top.ICEcoder.previewWindow.location){
17+
18+
// Init the DOM objects if we haven't yet got a pw var
19+
if("undefined"===typeofpw){
20+
21+
// Define the preview window target from the ICEcoder window perspective
22+
pw=top.ICEcoder.previewWindow.document;
23+
24+
// Define the 12 colors to be used in order for the breakpoints
25+
colors=["#e1c76e",/* yellow */
26+
"#6cb5d9",/* blue */
27+
"#bf255c",/* pink */
28+
"#f9602c",/* orange */
29+
"#b9ca4a",/* green */
30+
"#9179bb",/* purple */
31+
"#d00",/* red */
32+
"#214e7b",/* bright blue */
33+
"#cc7",/* grey-yellow */
34+
"#099",/* teal */
35+
"#6a0d6a",/* purple-pink */
36+
"#186718"];/* dark green */
37+
38+
// Define a bar at the top of the page to contain breakpoints and add button etc
39+
respBar=document.createElement('div');
40+
respBar.style.position="fixed";
41+
respBar.style.top="0";
42+
respBar.style.left="0";
43+
respBar.style.width="100%";
44+
respBar.style.height="20px";
45+
respBar.style.background="#141612";
46+
respBar.style.boxSizing="border-box";
47+
respBar.style.zIndex="1000001";
48+
respBar.id="ICEcoderRespBar";
49+
50+
// Now define an inner bar inside this, as wide as the body
51+
respInnerBar=document.createElement('div');
52+
respInnerBar.style.position="fixed";
53+
respInnerBar.style.top="0";
54+
respInnerBar.style.width=pw.body.getBoundingClientRect().width+"px";
55+
respInnerBar.style.height="20px";
56+
respInnerBar.style.background="#666";
57+
respInnerBar.style.boxSizing="border-box";
58+
respInnerBar.style.zIndex="1000002";
59+
respInnerBar.id="ICEcoderRespInnerBar";
60+
61+
// Define a dummy element that will contain our cloned nodes
62+
respInnerBarDummy=document.createElement('div');
63+
respInnerBarDummy.style.position="absolute";
64+
respInnerBarDummy.style.width="1px";
65+
respInnerBarDummy.style.left="-10000px";
66+
respInnerBarDummy.id="respInnerBarDummy";
67+
68+
// OK now define our add button to allow the adding of breakpoints
69+
add=document.createElement('div');
70+
add.style.position="fixed";
71+
add.style.display="inline-block";
72+
add.style.top="0";
73+
add.style.padding="3px 8px";
74+
add.style.fontFamily="arial, verdana, helvetica, sans-serif";
75+
add.style.fontSize="12px";
76+
add.style.background="#2187e7";
77+
add.style.color="#eee";
78+
add.style.cursor="pointer";
79+
add.style.zIndex="1000003";
80+
add.id="ICEcoderRespAdd";
81+
add.innerHTML="Add + ";
82+
add.addEventListener("click",function(){addBreakpoint();},false);
83+
84+
// Now a container for our 'focus box'
85+
focusContBox=document.createElement('div');
86+
focusContBox.style.position="absolute";
87+
focusContBox.style.top="0";
88+
focusContBox.style.left="0";
89+
focusContBox.style.zIndex="1000000";
90+
focusContBox.id="focusContBox";
91+
92+
// Plus the focus box within this, contains a massive outline to provide the focus 'scope'
93+
focusBox=document.createElement('div');
94+
focusBox.style.position="relative";
95+
focusBox.style.display="inline-block";
96+
focusBox.style.top="0";
97+
focusBox.style.height="0";
98+
focusBox.style.width="0";
99+
focusBox.style.outline="rgba(0,0,0,0.5) solid 10000px";
100+
focusBox.style.transition="all 0.1s ease-in-out";
101+
focusBox.style.cursor="pointer";
102+
focusBox.style.zIndex="1000000";
103+
focusBox.id="focusBox";
104+
// Set an event listener to handle what happens when we click on it
105+
focusBox.addEventListener("click",function(){
106+
107+
// If we've not got any breakpoints as yet, add one
108+
if(breakPoints.length===0){
109+
addBreakpoint();
110+
}
111+
112+
// Select the last, or open, a /[NEW] tab for this content as needed
113+
varopenFiles=top.ICEcoder.openFiles;
114+
varfoundNewFile=false;
115+
for(vari=openFiles.length-1;i>=0;i--){
116+
if(openFiles[i]=="/[NEW]"){
117+
top.ICEcoder.switchTab(i+1);
118+
foundNewFile=true;
119+
break;
120+
}
121+
}
122+
if(!foundNewFile){
123+
top.ICEcoder.newTab();
124+
}
125+
126+
// Get CM instance for this tab
127+
top.ICEcoder.targetcM=top.ICEcoder.getcMInstance();
128+
129+
// We now need to find our media query chunk to add content into,
130+
// start by getting all content lines into an array
131+
varthisContent=top.ICEcoder.targetcM.getValue();
132+
thisContent=thisContent.split("\n");
133+
134+
// Clear any selection
135+
top.ICEcoder.targetcM.setSelection({line:0,ch:0},{line:0,ch:0});
136+
137+
// Establish the media query line to use
138+
varmediaQueryLine=mediaQueryTemplate.replace("[[[WIDTH]]]",breakPoints[thisBreakPoint]+"px");
139+
140+
// Set init values meaning the start and end of chunk not yet established
141+
varchunkStartLine=-1;
142+
varchunkEndLine=top.ICEcoder.targetcM.lineCount()-1;
143+
varselectorStartLine=-1;
144+
varselectorEndLine=-1;
145+
varfoundSelector=false;
146+
147+
// Try and find the start and end of the chunk we need to work within
148+
for(vari=0;i<thisContent.length;i++){
149+
150+
// Found the existing chunk!
151+
if(thisContent[i]==mediaQueryLine){
152+
chunkStartLine=i;
153+
}
154+
// If we found our start, we continue to the next media query or end of doc, from 1 line after the start
155+
if(chunkStartLine>-1&&i>chunkStartLine){
156+
if(thisContent[i].indexOf("@media")!=-1){
157+
chunkEndLine=i-2;
158+
}
159+
// Have we found our selector within this media query?
160+
if(thisContent[i].indexOf("\t"+getCSSPath(top.ICEcoder.respElemSelected)+" {")!=-1){
161+
foundSelector=true;
162+
selectorStartLine=i;
163+
}
164+
// Finally, if we've found the line containing the end brace for the selector
165+
if(foundSelector&&thisContent[i]=="\t}"){
166+
selectorEndLine=i+1;
167+
break;
168+
}
169+
}
170+
}
171+
172+
// Set the media query line at the start of the file, with 2 line breaks if it's not the first one added
173+
cssOutputMQ=top.ICEcoder.targetcM.getValue()=="" ?mediaQueryLine+"\n" :"\n\n"+mediaQueryLine+"\n";
174+
175+
// Set the CSS rules within the selector (CSS path)
176+
// The first line here establishes the CSS selector path by classname and node depth
177+
cssOutputStart="\t"+getCSSPath(top.ICEcoder.respElemSelected)+" {\n";
178+
cssOutputRules="";
179+
for(varkeyindiff){
180+
cssOutputRules+="\t\t"+key+": "+diff[key]+";\n";
181+
}
182+
cssOutputEnd="\t}\n";
183+
// End of our media query
184+
cssOutputMQEnd="}";
185+
186+
// If we have a media query chunk
187+
if(chunkStartLine!==-1){
188+
// If we don't have a selector in the media query chunk yet, add one in at the end of it
189+
if(!foundSelector){
190+
top.ICEcoder.targetcM.replaceRange(cssOutputStart+cssOutputRules+cssOutputEnd,{line:chunkEndLine,ch:0},{line:chunkEndLine,ch:0});
191+
// We have our selector, so just select it
192+
}else{
193+
top.ICEcoder.targetcM.setSelection({line:selectorStartLine,ch:0},{line:selectorEndLine,ch:0});
194+
195+
}
196+
// Else insert media query chunk for first time (and our selector chunk)
197+
}else{
198+
top.ICEcoder.targetcM.setValue(top.ICEcoder.targetcM.getValue()+cssOutputMQ+cssOutputStart+cssOutputRules+cssOutputEnd+cssOutputMQEnd);
199+
}
200+
},false);
201+
202+
// Finally, define our CSS output DIV to show DOM elem styles
203+
outputBox=document.createElement('div');
204+
outputBox.style.position="fixed";
205+
outputBox.style.display="block";
206+
outputBox.style.bottom="0";
207+
outputBox.style.left="0";
208+
outputBox.style.width="100%";
209+
outputBox.style.height="150px";
210+
outputBox.style.fontFamily="arial, verdana, helvetica, sans-serif";
211+
outputBox.style.fontSize="12px";
212+
outputBox.style.background="rgba(255,255,255,0.5)";
213+
outputBox.style.color="#000";
214+
outputBox.style.overflow="auto";
215+
outputBox.style.zIndex="1000000";
216+
outputBox.id="outputBox"
217+
}
218+
219+
// Add DOM elems to previewWindow
220+
pw.body.appendChild(respBar);
221+
pw.body.appendChild(respInnerBar);
222+
pw.body.appendChild(respInnerBarDummy);
223+
pw.body.appendChild(add);
224+
pw.body.appendChild(focusContBox);
225+
pw.getElementById('focusContBox').appendChild(focusBox);
226+
pw.body.appendChild(outputBox);
227+
228+
// Get all DOM elems into an array
229+
elems=pw.body.getElementsByTagName('*');
230+
231+
// For each one of those, if it's got a z-index under 1000000, it should be a user set DOM elem
232+
for(vari=0;i<=elems.length;i++){
233+
if(elems[i].style.zIndex<1000000){
234+
// So add a mouseover event to it...
235+
elems[i].addEventListener("mouseover",function(){
236+
// ...that sets the left, width and high properties of the focus box to match the bounding rectangle of the DOM elem
237+
// ...top is a cumulative offset from the document top so we can scroll and it matches y pos of elem underneath
238+
pw.getElementById('focusBox').style.top=cumulativeOffset(this).top+"px";
239+
pw.getElementById('focusBox').style.left=this.getBoundingClientRect().left+"px";
240+
pw.getElementById('focusBox').style.width=this.getBoundingClientRect().width+"px";
241+
pw.getElementById('focusBox').style.height=this.getBoundingClientRect().height+"px";
242+
243+
// Set the width (to same value), which forces a DOM render and avoids us getting lots of extra unwanted styles picked up
244+
this.style.width=getComputedStyle(this).width;
245+
246+
// Create a dummy clone of the node...
247+
vardummy=this.cloneNode(true);
248+
// ...and insert that into our dummy container that's out of sight
249+
pw.getElementById('respInnerBarDummy').appendChild(dummy);
250+
251+
// Now to pick up the styles. First get inline styles set on the elem
252+
styleText=this.style.cssText.split(";");
253+
// Get rid of last empty array item if it's empty
254+
if(styleText[styleText.length-1]==""){
255+
styleText.pop();
256+
}
257+
258+
// Get styles from the elem and dummy clone of it
259+
vardefaultStyles=getComputedStyle(dummy);
260+
varelementStyles=getComputedStyle(this);
261+
262+
// Work out diffs between elem and dummy clone and but into a diff object
263+
diff={};
264+
for(varkeyinelementStyles){
265+
// If the value of matching keys isn't the same, we have a value set as it's different
266+
if(defaultStyles[key]!==elementStyles[key]){
267+
// We'll ignore cssText as we've got inline styles already
268+
if(key!=="cssText"){
269+
// Set the CSS syntax key by turning camel case into hyphenated lowercase
270+
diff[key.replace(/([a-z\d])([A-Z])/g,'$1-$2').toLowerCase()]=elementStyles[key];
271+
}
272+
}
273+
}
274+
275+
// Finally, create array of key/value style pairs, also trimming whitespace as we go
276+
for(vari=0;i<styleText.length;i++){
277+
varthisItem=styleText[i].split(":");
278+
diff[thisItem[0].trim()]=thisItem[1].trim();
279+
}
280+
281+
// Leave behind a pointer for this DOM elem
282+
top.ICEcoder.respElemSelected=this;
283+
284+
// Also output to the output box in a nice-ish format
285+
pw.getElementById('outputBox').innerHTML=JSON.stringify(diff).replace(/\"\,/g,'"<br>').replace(/\{/g,'').replace(/\}/g,'');
286+
287+
},true);
288+
}
289+
}
290+
}
291+
}
292+
293+
// Function to add breakpoints to the bar
294+
functionaddBreakpoint(){
295+
// Work out the window width and height plus the body width from our bar
296+
varwinW=top.ICEcoder.previewWindow.outerWidth;
297+
varwinH=top.ICEcoder.previewWindow.outerHeight;
298+
varbodyW=parseInt(pw.getElementById('ICEcoderRespInnerBar').style.width,10);
299+
// Set the width to be the lesser of these
300+
varnewW=winW<bodyW ?winW :bodyW;
301+
302+
// If we haven't got this width in our array yet, we can add it in
303+
if(breakPoints.indexOf(newW)==-1){
304+
breakPoints.push(newW);
305+
thisBreakPoint=breakPoints.length-1;
306+
varthisBP=thisBreakPoint;
307+
308+
// Now setup a bar for this breakpoint, width as per our newW and with the next background color
309+
thisRespBar=document.createElement('div');
310+
thisRespBar.style.position="absolute";
311+
thisRespBar.style.display="inline-block";
312+
thisRespBar.style.width=newW+"px";
313+
thisRespBar.style.height="20px";
314+
thisRespBar.style.top="0";
315+
thisRespBar.style.boxSizing="border-box";
316+
thisRespBar.style.padding="3px 8px";
317+
thisRespBar.style.background=colors[thisBreakPoint];
318+
thisRespBar.style.color="#fff";
319+
thisRespBar.style.fontFamily="arial, verdana, helvetica, sans-serif";
320+
thisRespBar.style.fontSize="12px";
321+
thisRespBar.style.textAlign="right";
322+
thisRespBar.style.cursor="pointer";
323+
thisRespBar.innerHTML=newW+"px";
324+
thisRespBar.id="respBar"+thisBreakPoint;
325+
// Set an event so on click it sets the breakpoint and changes window width to match
326+
thisRespBar.addEventListener("click",function(){
327+
setBreakPoint(thisBP);
328+
changeWinW(newW,winH);
329+
},false);
330+
// Append that to our bar container
331+
pw.getElementById('ICEcoderRespInnerBar').appendChild(thisRespBar);
332+
// It exists already so trigger a click event to set it, set window size etc
333+
}else{
334+
pw.getElementById('respBar'+breakPoints.indexOf(newW)).click();
335+
}
336+
};
337+
338+
// Get a CSS path for given elem
339+
functiongetCSSPath(elem){
340+
varcssPath=[],item,entry;
341+
342+
// Get all parent items
343+
for(item=elem.parentNode;item;item=item.parentNode){
344+
entry=item.tagName.toLowerCase();
345+
if(entry==="html"){
346+
break;
347+
}
348+
if(item.className){
349+
entry+="."+item.className.replace(//g,'.');
350+
}
351+
cssPath.push(entry);
352+
}
353+
354+
// Reverse the array to run forwards
355+
cssPath.reverse();
356+
357+
// Add on this elem to the end of the array
358+
entry=elem.tagName.toLowerCase();
359+
if(elem.className){
360+
entry+="."+elem.className.replace(//g,'.');
361+
}
362+
cssPath.push(entry);
363+
364+
// Return the array as a space delimited string
365+
returncssPath.join(" ");
366+
};
367+
368+
// Change the window size on demand
369+
functionchangeWinW(winW,winH){
370+
top.ICEcoder.previewWindow.resizeTo(winW,winH);
371+
};
372+
373+
// Set the current breakpoint to one we've clicked on
374+
functionsetBreakPoint(newBP){
375+
thisBreakPoint=newBP;
376+
};
377+
378+
// Work out the offset from the top of the page
379+
varcumulativeOffset=function(element){
380+
vartop=0,left=0;
381+
do{
382+
top+=element.offsetTop||0;
383+
left+=element.offsetLeft||0;
384+
element=element.offsetParent;
385+
}while(element);
386+
387+
// Return it as an array
388+
return{
389+
top:top,
390+
left:left
391+
};
392+
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp