I managed to pull together a script that will increase the font sizes of parts of a web page using buttons or links. It works in Moz/Chrome, but sticks on IE, tho theoretically it shouldn't have a issue in these major browsers. But I'm stuck on whether or not it's possible to use currentStyle to get the fontSize from a variable populated by getElementsByName; certainly IE is drawing blanks.
Here's my script:
function changeFontSize(element,step)
{
var styleProp = 'font-size';
step = parseInt(step,10);
var x = document.getElementsByName(element);
for(i=0;i<x.length;i++) {
if (x[i].currentStyle) {
var y = parseInt(x[i].currentStyle[styleProp],10);
} else if (window.getComputedStyle) {
var y = parseInt(document.defaultView.getComputedStyle(x[i],null).getPropertyValue(styleProp),10);
}
x[i].style.fontSize = (y+step) + 'px';
}
}
The 3 sites I've used to pull this together are:
www.vijayjoshi.org
www.quirksmode.org
and (this isn't spam, this is actually important) //http://www.white-hat-web-design.co.uk/blog/controlling-font-size-with-javascript/
Can anyone point out a solution please? Thanks in advance!
what about updating your code with the following :
function changeFontSize(element,step)
{
function computeFontSizeUpdate(oE)
{
//- init fSize with proper null value
var fSize = null;
//- retrieve fSize from style
if (oE.currentStyle) {
fSize = parseInt(oE.currentStyle[styleProp], 10);
}
else if (window.getComputedStyle) {
var s = document.defaultView.getComputedStyle(oE,null);
fSize = (s) ? parseInt(s.getPropertyValue(styleProp),10) : NaN;
}
//- check fSize value based on return of parseInt function
if( isNaN(fSize) == false && fSize != null)
{
fSize += nStep + 'px';
if(oE.currentStyle)
oE.currentStyle.fontSize = fSize;
else
oE.style.fontSize = fSize;
}
};
var styleProp = 'font-size';
var nStep = parseInt(step, 10);
//- ensure step value
if( isNaN(nStep) ) nStep = 0;
//- get target elements
var oElems = document.getElementsByName(element);
if ( oElems && oElems.length == 0)
{
var oE = document.getElementById(element);
if(oE) computeFontSizeUpdate(oE);
}
else
{
for(oE in oElems)
{
computeFontSizeUpdate(oE);
}
}
}
I have updated script with fix and few better naming for some variables.
Also, I am sorry cause I am on Mac right now, I wasn't able to test the provided script in IE ... but from what I remember it should do the trick.
Using some JS console you can directly execute directly on this page
changeFontSize("nav-tags", 50);
and you will notice that the Tags element in the menu bar would get affected :)
Hope this helps
Related
I am trying to work out how to use javascript with photoshop, but eventhough i dont find a logical error in the code, it doesnt work properly.
I have a folder of 1000+ images/.ai files that have varying dimensions. I need these images on the Pillow and saved as .jpeg.
I choose the smartlayer and run the script to choose the images and it saves them correctly. The only problem is, that the resizing of images and positioning dont work properly.
If i put the image in manually, it works without issues, but not with the script.
If the width is greater than the height, it should set the width to 1200 px and calculate the height according to that. (and vice versa) and place in the middle of the layer.
How do i fix the resizing and positioning?
Is it possible to choose a folder where the images are inside instead of selecting the images?
How do i handle it when there are 2 smart layers to change in the mockup instead of 1?
Anyone know where the problem lies this code?
Im grateful for any bit of help!
// Replace SmartObject’s Content and Save as JPG
// 2017, use it at your own risk
// Via #Circle B: https://graphicdesign.stackexchange.com/questions/92796/replacing-a-smart-object-in-bulk-with-photoshops-variable-data-or-scripts/93359
// JPG code from here: https://forums.adobe.com/thread/737789
#target photoshop
if (app.documents.length > 0) {
var myDocument = app.activeDocument;
var theName = myDocument.name.match(/(.*)\.[^\.]+$/)[1];
var thePath = myDocument.path;
var theLayer = myDocument.activeLayer;
// JPG Options;
jpgSaveOptions = new JPEGSaveOptions();
jpgSaveOptions.embedColorProfile = true;
jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpgSaveOptions.matte = MatteType.NONE;
jpgSaveOptions.quality = 8;
// Check if layer is SmartObject;
if (theLayer.kind != "LayerKind.SMARTOBJECT") {
alert("selected layer is not a smart object")
} else {
// Select Files;
if ($.os.search(/windows/i) != -1) {
var theFiles = File.openDialog("please select files", "*.psd;*.tif;*.jpg;*.ai", true)
} else {
var theFiles = File.openDialog("please select files", getFiles, true)
};
};
(function (){
var startRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
var bounds = activeDocument.activeLayer.bounds;
var height = bounds[3].value - bounds[1].value;
var width = bounds[2].value - bounds[0].value;
if (height > width){
var newSize1 = (100 / width) * 800;
activeDocument.activeLayer.resize(newSize1, newSize1, AnchorPosition.MIDDLECENTER);
app.preferences.rulerUnits = startRulerUnits;
}
else{
var newSize2 = (100 / height) * 800;
activeDocument.activeLayer.resize(newSize2, newSize2, AnchorPosition.MIDDLECENTER);
app.preferences.rulerUnits = startRulerUnits;
}
})();
if (theFiles) {
for (var m = 0; m < theFiles.length; m++) {
// Replace SmartObject
theLayer = replaceContents(theFiles[m], theLayer);
var theNewName = theFiles[m].name.match(/(.*)\.[^\.]+$/)[1];
// Save JPG
myDocument.saveAs((new File(thePath + "/" + theName + "_" + theNewName + ".jpg")), jpgSaveOptions, true,Extension.LOWERCASE);
}
}
};
// Get PSDs, TIFs and JPGs from files
function getFiles(theFile) {
if (theFile.name.match(/\.(psd|tif|jpg)$/i) != null || theFile.constructor.name == "Folder") {
return true
}
};
// Replace SmartObject Contents
function replaceContents(newFile, theSO) {
app.activeDocument.activeLayer = theSO;
// =======================================================
var idplacedLayerReplaceContents = stringIDToTypeID("placedLayerReplaceContents");
var desc3 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc3.putPath(idnull, new File(newFile));
var idPgNm = charIDToTypeID("PgNm");
desc3.putInteger(idPgNm, 1);
executeAction(idplacedLayerReplaceContents, desc3, DialogModes.NO);
return app.activeDocument.activeLayer
};
I have attached 2 pictures. 1 how it needs to look like and 2 what the script outputs
Correct
Wrong
Your replaced images have to be the same resolution as the smart object.
You can declare the folder path in your code. If you still want to select the path by hand, you can select one image in the path, and extract the parent folder path.
You can recursively go through all of the layers in the documents and extract all the smart objects that you want to replace.
You may want a function to recursively traverse all the layers in the document
function browseLayer(layer, fn) {
if (layer.length) {
for (var i = 0; i < layer.length; ++i) {
browseLayer(layer[i], fn)
}
return;
}
if (layer.layers) {
for (var j = 0; j < layer.layers.length; ++j) {
browseLayer(layer.layers[j], fn);
}
return;
}
//apply this function for every layer
fn(layer)
}
Get all the smart objects in the document
const smartObjects = [];
//The smart objects can be visit twice or more
//use this object to mark the visiting status
const docNameIndex = {};
const doc = app.open(new File("/path/to/psd/file"));
browseLayer(doc.layers, function (layer) {
//You cannot replace smart object with position is locked
if (layer.kind == LayerKind.SMARTOBJECT && layer.positionLocked == false) {
smartLayers.push(layer);
doc.activeLayer = layer;
//open the smart object
executeAction(stringIDToTypeID("placedLayerEditContents"), new ActionDescriptor(), DialogModes.NO);
//activeDocument is now the smart object
const docName = app.activeDocument.name;
if (!docNameIndex[docName]) {
docNameIndex[docName] = true;
smartObjects.push({
id: layer.id,
name: layer.name,
docName: docName,
width : app.activeDocument.width.as('pixels'),
height : app.activeDocument.height.as('pixels'),
resolution : app.activeDocument.resolution //important
});
}
//reactive the main document
app.activeDocument = doc;
}
});
I assume that you have two smart objects needed to replace, the images for replacement are stored in different folders with the same name.
smartObjects[0].replaceFolderPath = "/path/to/folder/1";
smartObjects[1].replaceFolderPath = "/path/to/folder/2";
//we need temp folder to store the resize images
smartObjects[0].tempFolderPath = "/path/to/temp/folder/1";
smartObjects[1].tempFolderPath = "/path/to/temp/folder/2";
Ex: The first iteration will replace smartObjects[0] with "/path/to/folder/1/image1.jpg", and smartObjects[1] with "/path/to/folder/image1.jpg"
Now resize all the images following the properties of the smart objects
smartObjects.forEach(function(smartObject){
//Get all files in the folder
var files = new Folder(smartObject.replaceFolderPath).getFiles();
//Resize all the image files
files.forEach(function (file) {
var doc = app.open(file);
doc.resizeImage(
new UnitValue(smartObject.width + ' pixels'),
new UnitValue(smartObject.height + ' pixels'),
smartObject.resolution
);
//save to temp folder
doc.saveAs(
new File(smartObject.tempFolderPath + "/" + file.name),
new PNGSaveOptions(),
true
);
doc.close(SaveOptions.DONOTSAVECHANGES)
});
});
Finally, replace the smart object
//get list of file again
var files = new Folder(smartObject.replaceFolderPath).getFiles();
files.forEach(function(file){
var fileName = file.name;
smartObjects.forEach(function(smartObject){
//active the window opening the smart object
app.activeDocument = app.documents.getByName(args.documentName);
var desc = new ActionDescriptor();
desc.putPath(charIDToTypeID("null"), new File(smartObject.tempFolderPath + "/" + fileName));
executeAction(stringIDToTypeID( "placedLayerReplaceContents" ), desc, DialogModes.NO);
});
//Now export document
var webOptions = new ExportOptionsSaveForWeb();
webOptions.format = SaveDocumentType.PNG; // SaveDocumentType.JPEG
webOptions.optimized = true;
webOptions.quality = 100;
doc.exportDocument(new File("/path/to/result/folder" + file.name), ExportType.SAVEFORWEB, webOptions);
});
Now you can close all the opening smart objects
smartObjects.forEach(function (s) {
app.documents.getByName(r.docName).close(SaveOptions.DONOTSAVECHANGES);
});
I just recently startet with Javascript and had the following Idea:
I would like to have short text (maybe just a headline) on my website which single chars will have a rainbow-color that travells from left to right.
So I wrote this short script.
var Count = 6;
setInterval(function RainbowColorFunction()
{
var Rainbow_Colors = ["#FFFF00","#FF7F00","#FF0000","#9400D3","#4B0082","#0000FF","#00FF00"];
var Color_Element = document.getElementById("RainbowColorText");
var Color_String = Color_Element.textContent;
var Letter = "";
var NewText = "";
var RainbowCount = Count;
var Stringlenght = Color_String.length;
Color_String = reverse(Color_String);
for (var i = Stringlenght, min = 0; i > min; i--)
{
Letter = Color_String.charAt(i -1);
if(Letter == " ")
{
NewText += Letter;
continue;
}
NewText += Letter.fontcolor(Rainbow_Colors[RainbowCount]);
RainbowCount--;
if(RainbowCount < 0){RainbowCount = 6;}
}
Count--;
if(Count < 0){Count = 6;}
Color_Element.innerHTML=NewText;
}, 60);
function reverse(s) {
return (s === '') ? '' : reverse(s.substr(1)) + s.charAt(0);
}
My Issue is now that the text changes colour from right to left. But I want it the other way around. Without the reverse Function my text is a big mess, but I am quite sure thats the point where I have to change things.
Short answer: just increment instead of decrement Count:
Count++;
if(Count>6 ){Count = 0;}
Other observations:
it's "length" not "lenght"
try to use singlequotes in Javascript and doublequotes for html
attributes. You will see that writing html in javascript and the
reverse become simple.
also the naming conventions for Javascript usually use lowercase
Camel variables, uppercase is reserved for class names, public
members maybe, etc. Whatever you use, be consistent after you choose.
you can move a lot of the function outside the interval, like the
part that gets the element.
you don't need to name the function that you give setInterval as an
attribute. Alternately you can name it then use
setInterval(functionName,500) on a separate line.
If I would do it, I would try to encapsulate it better. Here is my 5 minute effort:
function RainbowColor(elem)
{
this.Colors=["#FFFF00","#FF7F00","#FF0000","#9400D3","#4B0082","#0000FF","#00FF00"];
this.Speed=16.66;
this.Direction=1;
this._offset=0;
this._elem=elem;
this._originalContent=elem.innerHTML;
}
RainbowColor.prototype={
Colorize:function() {
var self=this;
function mod(v,l) {
var result=v%l;
return result<0?result+l:result;
}
function rainbowColorFunction() {
var text=self._elem.textContent;
var result='';
var k=self._offset;
for (var i=0; i<text.length; i++) {
var letter=text.charAt(i);
if (!letter) continue;
result+=letter.fontcolor(self.Colors[mod(k,self.Colors.length)]);
k-=self.Direction;
}
self._elem.innerHTML=result;
self._offset++;
}
this._interval=setInterval(rainbowColorFunction,1000/self.Speed);
},
Stop:function() {
if (this._interval) clearInterval(this._interval);
},
Restore:function() {
this._elem.innerHTML=this._originalContent;
}
}
var colorizer=new RainbowColor(document.getElementById('RainbowColorText'));
colorizer.Colorize();
setTimeout(function() { colorizer.Direction=-1; },5000);
setTimeout(function() { colorizer.Colors=['lightgray','gray','black'] },10000);
setTimeout(function() { colorizer.Speed=10; },15000);
setTimeout(function() { colorizer.Stop(); },20000);
setTimeout(function() { colorizer.Restore(); },23000);
I also looked into using CSS to create a text gradient, but I couldn't find any cross-browser solution (More details : How do I use a gradient as a font color in CSS?)
Speaking of cross-browser, perhaps you should use jQuery to get and set HTML content in order for this to work everywhere correctly.
I have created a loader for tiled in the JSON format for my JavaScript game. The game is based on a 2048 x 1280 map and my canvas size is 704 x 608.
So my predicament is how would i create a viewport/camera when the player approaches the edge of the canvas ,so that the map will move?
In my situation, it is a little more difficult, because im not using a standard 2D array like most of the tutorials, so it is confusing me very much.
The code for loading my map is like so:
function Level (){
var data;
this.tileset = null;
var returned;
var t = this;
this.load = function(name){
$.ajax({
type:"POST",
url: "maps/" + name + ".json",
dataType: 'JSON',
async: false,
success: function(success){
returned = loadTileset(success);
}
});
return returned;
};
function loadTileset(json){
data = json;
Level.tileset = $("<img />", { src: json.tilesets[0].image })[0]
Level.tileset.onload = done = true;
if(done){
return data;
}
else
return 0;
}
this.draw_layer = function(layer){
if (layer.type !== "tilelayer" || !layer.opacity) { return; }
// if (layer.properties && layer.properties.collision) {
// return;
// }
var size = data.tilewidth;
layer.data.forEach(function(tile_idx, i) {
if (!tile_idx) { return; }
var img_x, img_y, s_x, s_y,
tile = data.tilesets[0];
tile_idx--;
img_x = (tile_idx % (tile.imagewidth / size)) * size;
img_y = ~~(tile_idx / (tile.imagewidth / size)) * size;
s_x = (i % layer.width) * size;
s_y = ~~(i / layer.width) * size;
ctx.drawImage(Level.tileset, img_x, img_y, size, size,
s_x, s_y, size, size);
});
};
this.collisionLayer = function(layer){
var row = [];
t.solids = [];
layer.data.forEach(function(idx, i) {
var s_x,s_y,
size = 32;
s_x = (i % layer.width) * size;
s_y = ~~(i / layer.width) * size;
if (i % layer.width === 0 && i) {
t.solids.push(row);
row = [];
}
row.push([idx,s_x,s_y]);
});
t.solids.push(row);
};
return t.solids;
}
And this Level class is called from my main javascript file like this:
layer = scene.load("level_"+level);
layer = $.isArray(layer) ? layer : layer.layers;
layer.forEach(function(layer){
if(layer.name == "v.bottom" && layer.type == "tilelayer"){
b_layer = layer;
}
else if(layer.type == "tilelayer" && !layer.properties){
t_layer.push(layer);
}
else if (layer.type == "objectgroup"){
$.each(layer.objects, function(i, value){
coll_layer.push([value.x,value.y,value.width,value.height,"dialogue"]);
});
}
});
And then scene.draw_layer() is called from my update function lower in my main javascript function.
My map holds different layers and you can see in the code above there is and if statement determining where the layer is the bottom layer, top layer or and object layer and storing it in the specific array. This is just so the player is shown between layers.
So to clarify, for my game, how would i create a view port/camera according to my map loader?
Also do i move the map or the player?
And should i keep the player centered? if the player is centered then what happens when the edge of the map is visible?
Here is a live version of the game so you can see how it works etc:
LIVE DEMO
Use guest as the username and password
Thankyou very much
UPDATE
I have made a small progression i believe but with big consequences. I have tried implementing a viewport from a JSFIDDLE on one of the questions on here, its designed to work with a 2D array, but thought id give it a go.
and the result can be found here:
Updated link
If anyone could have a look to see where im going wrong it would be much appreciated. Thanks
I am trying to put a font-resizer on my company' website since a lot of our customers are the elderly and they have no idea about Ctrl + "+".
Here are the codes we have. The resizer works fine under FF, Chrome, and IE9. But not in IE8 and IE7. I omit the create cookies/read cookies parts here.
function createCookie(name,value,days) {.....codes for create cookies......}
function changeFont(incfont) {
try{
var p = document.getElementsByClassName('resizable');
for(n=0; n<p.length; n++) {
if(p[n].style.fontSize) {
var size = parseInt(p[n].style.fontSize.replace("px", ""));
} else {
var size = parseInt(window.getComputedStyle(p[n],null).getPropertyValue('font-size').replace("px", ""));
}
p[n].style.fontSize = size+ incfont + 'px';
}
p = document.getElementsByTagName('p');
for(n=0; n<p.length; n++) {
if(p[n].style.fontSize) {
var size = parseInt(p[n].style.fontSize.replace("px", ""));
} else {
var size = parseInt(window.getComputedStyle(p[n],null).getPropertyValue('font-size').replace("px", ""));
}
p[n].style.fontSize = size+ incfont + 'px';
}
} catch(err) {}
}
function readCookie(name) { ....code for read cookies ....}
function increaseFontSize() {
var inc=0;
try {
var x = readCookie('textsize')
if (x && x!=0) {
x = parseInt(x);
inc = x;
}
} catch (e) {}
if (inc<3) {
inc++;
changeFont(1);
createCookie('textsize',inc,1);
}
}
function decreaseFontSize() {
var inc=0;
try {
var x = readCookie('textsize')
if (x && x!=0) {
x = parseInt(x);
inc = x;
}
} catch (e) {}
if (inc>0) {
inc--;
changeFont(-1);
createCookie('textsize',inc,1);
}
}
Thanks in advance!
YN
Your solution seems overcomplex to me, I will suggest you a different approach, set a base text size for the page body, and then for the rest elements set font-sizes in percentage, that way when you want to resize the text of all the site you just have to do:
$("body").css("font-size", newFontSize);
getComputedStyle doesn't work for IE prior to 9.
See:
https://developer.mozilla.org/en-US/docs/DOM/window.getComputedStyle
A fix might be available here : http://snipplr.com/view/13523/
I didn't test it,
Good luck !
I have a javascript function for shrinking images but I dont want the shrinking function to work if an administrator logs in.
Here is part of the code
function shrinkImages(){
var i=0, maxWidth;
//if (/^(?:artistnews|albums|news|exitnews|reviews)$/.test(arg(0))) maxWidth=236;
if(typeof homepage != 'undefined') maxWidth=530;
else maxWidth=236;
var first = getElementsByClassName('first');
if(first.length>1)
first = first[0].getElementsByTagName('img');
var imgs = document.getElementsByTagName('img');
while(imgs[i]) {
if(imgs[i].width > maxWidth && imgs[i].name!="shadow") {
if (has(imgs[i], first) && maxWidth==236) {
imgs[i].height = Math.round(521 * imgs[i].height / imgs[i].width);
imgs[i].width = 521;
i++;
continue;
}
imgs[i].height = Math.round(maxWidth * imgs[i].height / imgs[i].width);
imgs[i].width = maxWidth;
}
i++;
}
imgs = null;
Define a Javascript variable called isAdmin and set it to true when an administrator logs in, then stick this at the beginning of that function...
if(isAdmin) return;
switch(userType || undefined) #Small update
{
case 'admin':
//Nothing
break;
case 'user':
case undefined: /*user or unknown*/
var imgs = document.getElementsByTagName('img');
for(i=0;i<=imgs.lenght;i++)
{
if(imgs[i].width > maxWidth && imgs[i].name!="shadow")
{
//ETC, You know the rest
}
}
break;
}
then within your html head do
var userType = 'admin'; // or w.e
And if you only define it for admin and dont define it for anyone else they still will get shrunk down