i am new to js.
i am trying to grab a image from an array with similar class names which
has a specific src saved in a variable bigImgPath
here is my Updated Code..
var moniqueThumbs=document.getElementsByClassName('moniqueThumbs'); // Grab the ThumbNails
var bigImagesList=document.getElementsByClassName('monique-image'); // Grabs All Big Images
var currentBigImg='';
var currentBigImageFilePath=""; // Current Big Image path Captured by current Thumb Click //s
for(var i = 0; i < moniqueThumbs.length; i++){
moniqueThumbs[i].addEventListener("click", grabBigImgPath); // Added a myFunction Click event to Thumbs
}
// Grab Big Image Path from Clicked Thumb
function grabBigImgPath()
{
currentBigImageFilePath=this.getAttribute('data-bigImgPath'); // grabs the current bigPath from the thumb//
var currentBigImageToDisplay;
for (var i = 0; i < bigImagesList.length; i++)
{
if (bigImagesList[i].getAttribute('src') == currentBigImageFilePath)
{
currentBigImageToDisplay = bigImagesList[i];
console.log(currentBigImageToDisplay);
break;
}
}
}
Still not displaying the current image in console.log
You need to use the getAttribute method to get the src:
currentBigImageToDisplay = bigImagesList[i].getAttribute('src') == bigImgPath;
That's still not right however, as it will just return true or false, so you want something like:
var currentBigImageToDisplay;
for (var i = 0; i < bigImagesList.length; i++) {
if (bigImagesList[i].getAttribute('src') == bigImgPath) {
currentBigImageToDisplay = bigImagesList[i];
break;
}
}
Alternatively, you could use the filter syntax:
bigImagesList = Array.prototype.slice.call(bigImagesList);
var currentBigImageToDisplay = bigImagesList.filter(function(item) {
return item.getAttribute('src') == bigImgPath;
})[0]
Working JSFIddle
Related
As the title suggests I am trying to find the index of a placeholder text element in a google doc table so that I can replace it with text stored in a different doc.
I can get the pre-formatted text to be added to the document - not the place in the table required - using other examples I have found on stackoverflow.
However I am unclear as how to find the index of the placeholder element within one of many tables in the template document.
I need the index of the placeholder text to be able to use the insertParagraph function.
To add slightly more detail: I am able to find the placeholder text and insert an image using the below code.
function replaceTextToImage(body, searchText, image, width) {
var next = body.findText(searchText);
if (!next) return;
var r = next.getElement();
r.asText().setText("");
var img = r.getParent().asParagraph().insertInlineImage(0, image);
if (width && typeof width == "number") {
var w = img.getWidth();
var h = img.getHeight();
img.setWidth(width);
img.setHeight(width * h / w);
}
return next;
};
However, I need to preserve the formatting of the doc I want to import. So I open the document with the formatted text and then loop through the different element types with a conditional to insert the text/image if the element type is matched. This is why I need the index of the placeholder text. See for function below:
function replaceTextWithDoc(body, searchText, id) {
let doc = DocumentApp.openById(id)
var numElements = body.getNumChildren();
var index = numElements;
for (var i = 0; i < numElements; i++) {
var child = body.getChild(i);
if (child.asText().getText() == searchText){
index = i;
body.removeChild(child);
break;
}
}
var totalElements = doc.getNumChildren();
for( var j = 0; j < totalElements; ++j ) {
var element = doc.getChild(j).copy();
var type = element.getType();
if( type == DocumentApp.ElementType.PARAGRAPH )
body.insertParagraph(index, element);
else if( type == DocumentApp.ElementType.TABLE )
body.insertTable(index, element);
else if( type == DocumentApp.ElementType.LIST_ITEM )
body.insertParagraph(index, element);
else
throw new Error("According to the doc this type couldn't appear in the body: "+type);
}
}
Here is an example of the placeholder text ( {iText} ) in a table: https://docs.google.com/document/d/1mZWpQqk4gYAF6UCRALrT8S99-01RYNfwni_kqDzOg7E/edit?usp=sharing
Here is an example of text and images that I need to replace the placeholder text with - maintaining all/any formatting. https://docs.google.com/document/d/1wuX0g5W2GL0YJ7admiv3TNEepb_zVwQleKwazCiAMBU/edit?usp=sharing
Issue:
If I understand you correctly, you want to copy the contents of one document (made up of text and inline images) to certain table cells that contain a certain placeholder text.
Solution:
In that case, I'd suggest the following:
Iterate through all tables in the target document, using Body.getTables().
For each table, iterate through all its cells.
For each cell, check whether its text contains the placeholder.
If the placeholder is included, clear the current cell content via TableCell.clear().
Iterate through all source document elements (see for example, this answer).
For each element, check its type (Element.getType()).
If the element is a paragraph, append the paragraph to the cell via TableCell.appendParagraph.
If the element is an image, append it via TableCell.appendImage.
Code sample:
const PLACEHOLDER = "{iText}";
function myFunction() {
const doc = DocumentApp.openById(TARGET_ID);
const sourceDoc = DocumentApp.openById(SOURCE_ID);
const body = doc.getBody();
const tables = body.getTables();
tables.forEach(table => {
const numRows = table.getNumRows();
for (let i = 0; i < numRows; i++) {
const row = table.getRow(i);
const numCells = row.getNumCells();
for (let j = 0; j < numCells; j++) {
const cell = row.getCell(j);
const cellText = cell.editAsText();
const text = cellText.getText();
if (text.includes(PLACEHOLDER)) {
cell.clear();
appendSourceContent(sourceDoc, cell);
}
}
}
});
}
function appendSourceContent(doc, cell) {
const numChildren = doc.getNumChildren();
for (let j = 0; j < numChildren; j++) {
const element = doc.getChild(j).copy();
const type = element.getType();
if (type == DocumentApp.ElementType.PARAGRAPH) {
cell.appendParagraph(element);
} else if (type == DocumentApp.ElementType.INLINE_IMAGE) {
cell.appendImage(element);
}
}
}
Note:
Add additional else if blocks if the source content can have different ElementTypes than paragraphs and inline images.
I assumed that you want to preserve none of the current content in the table cell.
I want to fill my Selection by Script. I am struggling with the filling method.
When I want to fill my FontSizeMenu I use this code:
function FillFontSizeMenu() { // run this at Start
FillSelection(GetPossibleFontSizes(), "fontSizeMenu"); // Fill the selection with values
}
function GetPossibleFontSizes(){ // Return all values for the menu
var sizeMin = 1;
var sizeMax = 100;
var possibleSizes = [];
for(var i = sizeMin; i <= sizeMax; i++)
{
possibleSizes.push(i);
}
return possibleSizes;
}
function FillSelection(possibleValues, elementId){ // Fill the menu
for(var i = 0; i < possibleValues.length; i++)
{
var optionElement = "<option></option>"; // add one option element per value
optionElement.html(possibleValues[i]);
optionElement.val(possibleValues[i]);
$(elementId).append(optionElement); // add the option element to the selection
}
}
Something is wrong with the "FillSelection" method, it says the option element is not a function.
Does someone knows what is wrong or missing?
Thanks
Wrap html string in jQuery()
var optionElement = $("<option></option>");
You can also use jQuery() to set html, value and call .appendTo()
$("<option></option>", {
html: possibleValues[i],
value: possibleValues[i],
appendTo: $(elementId)
});
Here is one more solution
You need to create new Option object
$(elementId).append(new Option("Font size "+i, possibleValues[i]));
and you should pass #id to function:
FillSelection(GetPossibleFontSizes(), "#fontSizeMenu")
function FillFontSizeMenu() { // run this at Start
FillSelection(GetPossibleFontSizes(), "#fontSizeMenu"); // Fill the selection with values
}
function GetPossibleFontSizes(){ // Return all values for the menu
var sizeMin = 1;
var sizeMax = 100;
var possibleSizes = [];
for(var i = sizeMin; i <= sizeMax; i++)
{
possibleSizes.push(i);
}
return possibleSizes;
}
function FillSelection(possibleValues, elementId){ // Fill the menu
for(var i = 0; i < possibleValues.length; i++)
{
$(elementId).append(new Option("Font size "+i, possibleValues[i])); // add the option element to the selection
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="FillFontSizeMenu()">Populate it</button>
<select id="fontSizeMenu">
</select>
You have to create an element first then append properties using jquery. Something like this
var ele = document.createElement("<option>");
$("body").append(ele);
$(ele).html(possibleValues[i]);
$(ele).val(possibleValues[i]);
I am trying to write a script (because I can't find one that works) that will export all my separate layers, paths, etc to transparent png files. I have seen many scripts, but all of them do not export all the layers, etc. They seem to just try and export parent layers. So if there are sub layers, these are missed.
Here is my script:
var doc = app.activeDocument;
var counter = 0;
hideOrShowItems(doc, false);
// processLayers(doc);
// displayLayer(doc, true);
function hideOrShowItems(root, show) {
for(var i = 0; i < root.layers.length; i++) {
var layer = root.layers[i];
var pathCount = layer.pathItems.length;
var layerCount = layer.layers.length;
if (pathCount > 0) {
hideOrShowPaths(layer, show);
}
if (layerCount > 0) {
hideOrShowItems(layer, show);
}
layer.visible = show;
}
}
function hideOrShowPaths(root, show) {
for(var i = 0; i < root.pathItems.length; i++) {
root.pathItems[i].visible = show;
}
}
// -- Removed for brievety
When I run the script, the only thing that gets hidden is the top layer
All of the rest are untouched.
I put a counter in and did counter++ in the for loop of hideOrShowPaths and it counts 246, so I know it can see the paths and is actually trying to hide them, but they stay visible.
Has anyone done this before? Can I hide paths, groups, clips and export them all as pngs? or will I have to do this manually?
Looks like the flag you are looking for is hidden not visible.
var doc = app.activeDocument;
var root = doc.layers[0];
// just for testing purpose. Change the color
var newRGBColor = new RGBColor();
newRGBColor.red = 255;
newRGBColor.green = 255;
newRGBColor.blue = 255;
// make all items hidden
for (var i = 0; i < root.pathItems.length; i++) {
var item = root.pathItems[i];
item.hidden = true;
item.fillColor = newRGBColor; // just for testing
}
// now loop all pathItems
for (var i = 0; i < root.pathItems.length; i++) {
var item = root.pathItems[i];
item.hidden = !item.hidden; //make one visible
// export visible part
redraw();
item.hidden = !item.hidden; // hide it again
}
In your script you will need to hide every item first, then unhide one, export and hide it again.
I Hope that snippet helps with your problem
I have a huge collection of list elements.
the concept is that the user can select only two items from that collection.
I am showing a check/Uncheck as an image infront of the list item, just for visual purposes that the list is selected or not.
The image is defined in a class, so I have to switch classes to show selected or unselected.
This is they way I am currently modifying the class but I think it might be too heavy.
function showAsSelected(selectedArr, selectedCat) {
var allLinks = document.getElementsByClassName("linkRef");
var len = allLinks.length;
for (var i = 0; i < len; i++) {
allLinks[i].setAttribute('class', 'linkRef subCategLink');
}
for (var i = 0; i < selectedArr.length; i++) {
selectedArr[i].setAttribute('class', 'linkRef subCategLinkChkd');
}
}
'allLinks' gets all the elements having class "linkRef". counting above 100 sometimes. The first loop modifies class to 'linkRef subCategLink'. This means it will remove 'subCategLinkChkd' from two elements (Running a loop on hundreds only to modify two).
The second loop sets the class only on the two elements which are referenced in the "selectedArr" array.
I assuming that you have a similar HTML structure (and if so) you can try something like this.
jsFiddle
(function () {
"use strict";
var list = document.getElementById("list"),
selectedInputs = [],
shifted = null;
list.addEventListener("change", function (e) {
var target = e.target,
index = selectedInputs.indexOf(target);
if (target.nodeName.toLowerCase() === "input" &&
target.type.toLowerCase() === "checkbox" &&
target.classList.contains("linkRef")) {
if (target.checked && index === -1) {
target.setAttribute('class', 'linkRef subCategLinkChkd');
selectedInputs.push(target);
} else if (target.checked === false && index !== -1) {
selectedInputs.splice(index, 1);
target.setAttribute('class', 'linkRef subCategLink');
}
if (selectedInputs.length > 2) {
shifted = selectedInputs.shift();
shifted.setAttribute('class', 'linkRef subCategLink');
shifted.checked = false;
}
}
}, false);
}());
Updated
I am trying to use <label> elements in my html contact form like the HTML5 placeholder attribute for inputs. I have written the following JavaScript to to act as a reusable function witch will provide the following functionality.
Find the input by name.
Get the value of the input.
Find the label belonging to the input.
Change the label style depending on the state of the input.
Change the label style depending on the value of the input.
However it is not working and I don't know why as no errors appear in the console. What am I doing wrong? here is a JS Fiddle with code
function placeholder(field_name) {
// Get the input box with field_name
// Then get input value
var box = document.getElementsByName(field_name);
var i;
for (i = 0; i < box.length; i++) {
var value = document.getElementById(box[i].value);
}
// Get the labels belonging to each box using the HTML for attribute
var labels = document.getElementsByTagName('LABEL');
for (i = 0; i < labels.length; i++) {
if (labels[i].htmlFor !== '') {
var elem = document.getElementById(labels[i].htmlFor);
if (elem) {
box.label = labels[i];
}
}
}
// Colors
var focusColor = "#D5D5D5";
var blurColor = "#B3B3B3";
// If no text is in the box then show the label grey color
box.onblur = function () {
box.label.style.color = blurColor;
};
// If input focuses change label color to light grey
box.onfocus = function () {
box.label.style.color = focusColor;
};
// If there is text in the box then hide the label
if (box.value !== "") {
// Quick do something, hide!
box.label.style.color = "transparent";
}
}
// Call the function passing field names as parameters
placeholder(document.getElementsByName("email"));
placeholder(document.getElementsByName("firstName"));
placeholder(document.getElementsByName("lastName"));
This might be considered a little overkill on the number of listeners I've used, feel free to remove any you think unnecessary, but I've tried to employ your HTML structure as you have it and give you all desired effects. It should work for either the <label>s for matching the <input>s id OR matching it's <name> (given no id matches). I'll always say prefer using an id over name. I believe this JavaScript should also work in all browsers too, except the addEventListener for which you'd need a shim for old IE versions (let me know if it doesn't in one/the error message).
Demo
var focusColor = "#D5D5D5", blurColor = "#B3B3B3";
function placeholder(fieldName) {
var named = document.getElementsByName(fieldName), i;
for (i = 0; i < named.length; ++i) { // loop over all elements with this name
(function (n) { // catch in scope
var labels = [], tmp, j, fn, focus, blur;
if ('labels' in n && n.labels.length > 0) labels = n.labels; // if labels provided by browser use it
else { // get labels from form, filter to ones we want
tmp = n.form.getElementsByTagName('label');
for (j = 0;j < tmp.length; ++j) {
if (tmp[j].htmlFor === fieldName) {
labels.push(tmp[j]);
}
}
}
for (j = 0; j < labels.length; ++j) { // loop over each label
(function (label) { // catch label in scope
fn = function () {
if (this.value === '') {
label.style.visibility = 'visible';
} else {
label.style.visibility = 'hidden';
}
};
focus = function () {
label.style.color = focusColor;
};
blur = function () {
label.style.color = blurColor;
};
}(labels[j]));
n.addEventListener('click', fn); // add to relevant listeners
n.addEventListener('keydown', fn);
n.addEventListener('keypress', fn);
n.addEventListener('keyup', fn);
n.addEventListener('focus', fn);
n.addEventListener('focus', focus);
n.addEventListener('blur', fn);
n.addEventListener('blur', blur);
}
}(named[i]));
}
};
placeholder("email"); // just pass the name attribute
placeholder("firstName");
placeholder("lastName");
http://jsfiddle.net/cCxjk/5/
var inputs = document.getElementsByTagName('input');
var old_ele = '';
var old_label ='';
function hide_label(ele){
var id_of_input = ele.target.id;
var label = document.getElementById(id_of_input + '-placeholder');
if(ele.target == document.activeElement){
label.style.display = 'none';
}
if (old_ele.value == '' && old_ele != document.activeElement){
old_label.style.display = 'inline';
}
old_ele = ele.target;
old_label = label;
}
for(var i = 0; i < inputs.length; i++){
inputs[i].addEventListener('click', hide_label);
}
I will point out a couple things, you will have to find away around the fact that the label is inside the input so users now can't click on half of the input and actually have the input gain focus.
Also I guess you want to do this in IE (otherwise I would strongly advise using the html5 placeholder!) which means you would need to change the ele.target to ele.srcElement.