How to get the parent child relationship between connected mxgraph - javascript
I'm trying to get simplified relationship between connected mxgraph
Question: I'm trying to get the simplified relationship, once the graph is drawn.
i'm trying to get relationship between connected nodes in json.
Note: solution must work for every drawn state.
Here is codepen:
https://codepen.io/eabangalore/pen/pmELpL
i want to get the relationship from above code snippet.
Expected output (from drawn relationship):
[
{"id":0,"parent":"#","text":"A","child":[{"cid":1,"connectionText":"Bangalore"}]},
{"id":1,"parent":0,"text":"B","child":[{"cid":2,"connectionText":""}]},
{"id":2,"parent":1,"text":"C","child":[{"cid":null,"connectionText":""}]}
];
Please refer codepen, as below snippet is not working.
<!--
Copyright (c) 2006-2013, JGraph Ltd
Dynamic toolbar example for mxGraph. This example demonstrates changing the
state of the toolbar at runtime.
-->
<html>
<head>
<title>Toolbar example for mxGraph</title>
<!-- Sets the basepath for the library if not in same directory -->
<script type="text/javascript">
mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
function setGraphData(){
var graphState ={"tagName":"mxGraphModel","children":[{"tagName":"root","children":[{"tagName":"mxCell","attributes":{"id":"0"}},{"tagName":"mxCell","attributes":{"id":"1","parent":"0"}},{"tagName":"mxCell","attributes":{"id":"2","value":"A","style":"","vertex":"1","parent":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"271.56251525878906","y":"82.44792175292969","width":"100","height":"40","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"3","value":"B","style":"","vertex":"1","parent":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"678.2291717529297","y":"106.89236450195312","width":"100","height":"40","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"4","value":"Bangalore","edge":"1","parent":"1","source":"2","target":"3"},"children":[{"tagName":"mxGeometry","attributes":{"relative":"1","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"5","value":"C","style":"","vertex":"1","parent":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"1013.7847747802734","y":"83.55902862548828","width":"100","height":"40","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"6","edge":"1","parent":"1","source":"3","target":"5"},"children":[{"tagName":"mxGeometry","attributes":{"relative":"1","as":"geometry"}}]}]}]};
localStorage.setItem('graphState',JSON.stringify(graphState));
}
function html2json(html){
if(html.nodeType==3){
return {
"tagName":"#text",
"content":html.textContent
}
}
var element = {
"tagName":html.tagName
};
if(html.getAttributeNames().length>0){
element.attributes = html.getAttributeNames().reduce(
function(acc,at){acc[at]=html.getAttribute(at); return acc;},
{}
);
}
if(html.childNodes.length>0){
element.children = Array.from(html.childNodes)
.filter(
function(el){
return el.nodeType!=3
||el.textContent.trim().length>0
})
.map(function(el){return html2json(el);});
}
return element;
}
function json2html(json){
var xmlDoc = document.implementation.createDocument(null, json.tagName);
var addAttributes = function(jsonNode, node){
if(jsonNode.attributes){
Object.keys(jsonNode.attributes).map(
function(name){
node.setAttribute(name,jsonNode.attributes[name]);
}
);
}
}
var addChildren = function(jsonNode,node){
if(jsonNode.children){
jsonNode.children.map(
function(jsonChildNode){
json2htmlNode(jsonChildNode,node);
}
);
}
}
var json2htmlNode = function(jsonNode,parent){
if(jsonNode.tagName=="#text"){
return xmlDoc.createTextNode(jsonNode.content);
}
var node = xmlDoc.createElement(jsonNode.tagName);
addAttributes(jsonNode,node);
addChildren(jsonNode,node);
parent.appendChild(node);
}
addAttributes(json,xmlDoc.firstElementChild);
addChildren(json,xmlDoc.firstElementChild);
return xmlDoc;
}
</script>
<!-- Loads and initializes the library -->
<script type="text/javascript" src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>
<!-- Example code -->
<script type="text/javascript">
// Program starts here. Creates a sample graph in the
// DOM node with the specified ID. This function is invoked
// from the onLoad event handler of the document (see below).
function main()
{
setGraphData();
// Checks if browser is supported
if (!mxClient.isBrowserSupported())
{
// Displays an error message if the browser is
// not supported.
mxUtils.error('Browser is not supported!', 200, false);
}
else
{
// Defines an icon for creating new connections in the connection handler.
// This will automatically disable the highlighting of the source vertex.
mxConnectionHandler.prototype.connectImage = new mxImage('images/connector.gif', 16, 16);
// Creates the div for the toolbar
var tbContainer = document.createElement('div');
tbContainer.style.position = 'absolute';
tbContainer.style.overflow = 'hidden';
tbContainer.style.padding = '2px';
tbContainer.style.left = '0px';
tbContainer.style.top = '0px';
tbContainer.style.width = '24px';
tbContainer.style.bottom = '0px';
document.body.appendChild(tbContainer);
// Creates new toolbar without event processing
var toolbar = new mxToolbar(tbContainer);
toolbar.enabled = false
// Creates the div for the graph
var container = document.createElement('div');
container.style.position = 'absolute';
container.style.overflow = 'hidden';
container.style.left = '24px';
container.style.top = '0px';
container.style.right = '0px';
container.style.bottom = '0px';
container.style.background = 'url("editors/images/grid.gif")';
document.body.appendChild(container);
// Workaround for Internet Explorer ignoring certain styles
if (mxClient.IS_QUIRKS)
{
document.body.style.overflow = 'hidden';
new mxDivResizer(tbContainer);
new mxDivResizer(container);
}
// Creates the model and the graph inside the container
// using the fastest rendering available on the browser
var model = new mxGraphModel();
var graph = new mxGraph(container, model);
// Enables new connections in the graph
graph.setConnectable(true);
graph.setMultigraph(false);
// Stops editing on enter or escape keypress
var keyHandler = new mxKeyHandler(graph);
var rubberband = new mxRubberband(graph);
var addVertex = function(icon, w, h, style)
{
var vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);
vertex.setVertex(true);
var img = addToolbarItem(graph, toolbar, vertex, icon);
img.enabled = true;
graph.getSelectionModel().addListener(mxEvent.CHANGE, function()
{
var tmp = graph.isSelectionEmpty();
mxUtils.setOpacity(img, (tmp) ? 100 : 20);
img.enabled = tmp;
});
};
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rectangle.gif', 100, 40, '');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rounded.gif', 100, 40, 'shape=rounded');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/ellipse.gif', 40, 40, 'shape=ellipse');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rhombus.gif', 40, 40, 'shape=rhombus');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/triangle.gif', 40, 40, 'shape=triangle');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/cylinder.gif', 40, 40, 'shape=cylinder');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/actor.gif', 30, 40, 'shape=actor');
// read state on load
if(window.localStorage.graphState){
var doc = json2html(JSON.parse(localStorage.graphState));
var dec = new mxCodec(doc);
dec.decode(doc.documentElement, graph.getModel());
}
// save state on change
graph.getModel().addListener('change',function(){
var codec = new mxCodec();
window.localStorage.graphState = JSON.stringify(html2json(codec.encode(
graph.getModel()
)));
});
}
}
function addToolbarItem(graph, toolbar, prototype, image)
{
// Function that is executed when the image is dropped on
// the graph. The cell argument points to the cell under
// the mousepointer if there is one.
var funct = function(graph, evt, cell, x, y)
{
graph.stopEditing(false);
var vertex = graph.getModel().cloneCell(prototype);
vertex.geometry.x = x;
vertex.geometry.y = y;
graph.addCell(vertex);
graph.setSelectionCell(vertex);
}
// Creates the image which is used as the drag icon (preview)
var img = toolbar.addMode(null, image, function(evt, cell)
{
var pt = this.graph.getPointForEvent(evt);
funct(graph, evt, cell, pt.x, pt.y);
});
// Disables dragging if element is disabled. This is a workaround
// for wrong event order in IE. Following is a dummy listener that
// is invoked as the last listener in IE.
mxEvent.addListener(img, 'mousedown', function(evt)
{
// do nothing
});
// This listener is always called first before any other listener
// in all browsers.
mxEvent.addListener(img, 'mousedown', function(evt)
{
if (img.enabled == false)
{
mxEvent.consume(evt);
}
});
mxUtils.makeDraggable(img, graph, funct);
return img;
}
</script>
</head>
<!-- Calls the main function after the page has loaded. Container is dynamically created. -->
<body onload="main();" >
</body>
</html>
please help me thanks in advance!!!
Check out this CodePen link which has the modified version of the snippet you gave. In it, you can add new elements and change texts and see an updated json string representing the relationships in the graph: https://codepen.io/tien-q-nguyen2/pen/GaQXBO
I also edited the function a little from the first time I posted this answer.
Note: based on the expected output you put in the original question, there is only one parent per vertex element ({"id":1,"parent":0 <= in the example you gave), so if there are multiple nodes pointing to the same child , the child's parent property will only refer to the first parent's id. I can change the parent's property to be an array that can keep multiple parent's ids if you want.
function getNodesFrom(graph){
var cells = graph.getModel().cells;
var vertices = [], edges = [];
for (var key in cells) {
if (cells[key].isVertex()){
vertices.push(cells[key]);
}
else if (cells[key].isEdge()){
edges.push(cells[key]);
}
}
var simpleVertices = [], simpleEdges = [];
var newIndex = 0;
var newIndexOf = [];
vertices.forEach(function(vertex){
simpleVertices.push({id: newIndex, value: vertex.value});
newIndexOf[vertex.id] = newIndex++;
});
edges.forEach(function(edge){
if (edge.target === null || edge.source === null) return;
simpleEdges.push({
parentId: newIndexOf[edge.source.id],
childId: newIndexOf[edge.target.id],
value: edge.value
});
});
var edgesForParentIndex = [];
var edgesForChildIndex = [];
simpleEdges.forEach(function(edge){
if (edgesForParentIndex[edge.parentId] === undefined){
edgesForParentIndex[edge.parentId] = [];
}
edgesForParentIndex[edge.parentId].push(edge);
if (edgesForChildIndex[edge.childId] === undefined){
edgesForChildIndex[edge.childId] = [];
}
edgesForChildIndex[edge.childId].push(edge);
});
var nodes = [];
simpleVertices.forEach(function(vertex){
var node = {};
node.id = vertex.id;
if (edgesForChildIndex[node.id] === undefined){
node.parent = '#';
} else {
node.parent = edgesForChildIndex[node.id][0].parentId;
}
node.text = (vertex.value === undefined || vertex.value === null) ? '' : vertex.value;
node.child = [];
if (edgesForParentIndex[node.id] === undefined){
node.child.push({cid: null, connectionText: ""});
} else {
edgesForParentIndex[node.id].forEach(function(edge){
var text = (edge.value === undefined || edge.value === null) ? '' : edge.value;
node.child.push({cid: edge.childId, connectionText: text});
});
}
nodes.push(node);
});
return nodes;
}
Related
Problems with changing color of gltf object
With this answer as a reference, I have succeeded in changing the color of the gltf model. (Change the color of an object (.dae or gltf) in "AR.JS") However, the model texture will disappear. why? <!-- A FRAME --> <script src="https://aframe.io/releases/1.0.0/aframe.min.js"></script> <script src="https://unpkg.com/aframe-orbit-controls#1.2.0/dist/aframe-orbit-controls.min.js"></script> <script> AFRAME.registerComponent('carman', { init: function(){ let el = this.el; let self = this; self.cars = []; el.addEventListener("model-loaded", e => { let car3D = el.getObject3D('mesh'); if (!car3D){return;} //console.log('car', car3D); car3D.traverse(function(node){ if (node.isMesh){ // console.log(node); self.cars.push(node); if(node.name == "meta02t"){ self.carMat = node.material; } node.material.map = null; } }); }); el.addEventListener('changecolor', e => { let colorp = e.detail.color; let colorHex = Number(colorp.replace('#', '0x')); let color3D = new THREE.Color(colorHex); self.carMat.color = color3D; }); } }); AFRAME.registerComponent('click-listener', { init: function () { // Listen for click event let self = this; let el = this.el; this.el.addEventListener('click', function (evt) { // Call the Octahedron and trigger it's scalewave animation let car = document.querySelector('#car'); let color = el.getAttribute('material', 'color'); car.emit('changecolor', color); }); } }); </script> My Glitch Project https://glitch.com/~0421
There is no texture, because once the model is loaded, you go through the nodes and remove it: node.material.map = null; // removes the texture Furthermore - the car seems black even with the color changed. The "metal" parts are rough and not metallic (roughness: 0.5, metalness: 0). If you change that, the car will change its color (visually speaking): el.addEventListener('changecolor', e =>{ // set the new color let colorp = e.detail.color; let colorHex = Number(colorp.replace('#', '0x')); let color3D = new THREE.Color(colorHex); // apply for the "metal" materials for (var i = 0; i < self.cars.length; i++) { if (!self.cars[i].material) return if (self.cars[i].name.includes("meta")) { self.cars[i].material.metalness = 0.7 self.cars[i].material.roughness = 0.2 self.cars[i].material.color = color3D; } } }); Check it out in this glitch.
How do I change the color using an external color picker for Babylon.js?
I recently have a project to be working with Babylon.js and instead of using Colorpicker GUI, I must use an external color picker. In this case I'm using http://jscolor.com/. Here's my partial code (I'm only showing my small code, because of a strict post rule. Tell me if you still need more detailed code). <!-- This is the external color picker --> <input class="jscolor {onFineChange:'updateColor(this)'}" value="ffcc00" style="position: absolute;z-index: 999;"> <!-- end of external color picker --> <script type="text/javascript"> var divcvs = document.getElementById("cvs"); var loader = document.getElementById("load"); if (loader && loader.parentElement) loader.parentElement.removeChild(loader); var engine = new BABYLON.Engine(divcvs, antialias, null, adaptive); engine.enableOfflineSupport = offline; engine.clear(new BABYLON.Color3(0, 0, 0), true, true); engine.displayLoadingUI(); engine.loadingUIText = "Loading Content Assets"; var updateStatus = (status) => { engine.loadingUIText = status; }; var showSceneLoader = () => { divcvs.style.opacity = "0"; engine.clear(new BABYLON.Color3(0, 0, 0), true, true); engine.displayLoadingUI(); updateStatus("Loading Content Assets"); }; var removeSceneLoader = () => { engine.hideLoadingUI(); divcvs.style.opacity = "1"; updateStatus(""); }; var progressSceneLoader = () => { if (loaded === false && TimerPlugin && TimerPlugin.requestAnimFrame) { if (scene != null) { var waiting = 0 + scene.getWaitingItemsCount(); var content = (waiting > 1) ? " Content Assets" : " Content Asset"; updateStatus((waiting > 0) ? "Streaming " + waiting.toString() + content : ("Starting " + title)); } TimerPlugin.requestAnimFrame(progressSceneLoader); } }; // Only works on this part for the scene var executeSceneLoader = (root, name) => { progressSceneLoader(); BABYLON.SceneLoader.Load(root, name, engine, (newscene) => { scene = newscene; // Access the Babylon Mesh and create a default scene var pbr = new BABYLON.PBRMaterial("cube", scene); var cube = scene.getMeshByName("sample_Cube"); cube.material = pbr; pbr.albedoTexture = new BABYLON.Texture("scenes/KnittedMetal_AlbedoTransparency.png", scene); pbr.useRoughnessFromMetallicTextureGreen = true; // GUI and Controls var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI"); var panel = new BABYLON.GUI.StackPanel(); panel.width = "200px"; panel.isVertical = true; panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT; panel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER; advancedTexture.addControl(panel); // Babylon Color Picker, but I'm not using this. It's // only for testing. var textBlock = new BABYLON.GUI.TextBlock(); textBlock.text = "Choose color:"; textBlock.color = "#ffffff"; textBlock.height = "30px"; panel.addControl(textBlock); var picker = new BABYLON.GUI.ColorPicker(); picker.value = pbr.albedoColor; picker.height = "150px"; picker.width = "150px"; picker.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER; picker.onValueChangedObservable.add(function(value) { pbr.albedoColor.copyFrom(value); }); panel.addControl(picker); // End Babylon Color Picker // End GUI and Controls if (!scene.manager) { if (BABYLON.SceneManager && BABYLON.SceneManager.CreateManagerSession) { BABYLON.SceneManager.CreateManagerSession(root, scene); BABYLON.Tools.Warn("Babylon.js created default scene manager session"); } } scene.executeWhenReady(() => { loaded = true; if (scene.manager && scene.manager.start) { scene.manager.start(); } else { engine.runRenderLoop(function() { scene.render(); }); BABYLON.Tools.Warn("Babylon.js running default scene render loop"); } removeSceneLoader(); }); }); }; // Default babylon scene loader var defaultSceneLoader = (root, name) => { scene = null; loaded = false; showSceneLoader(); executeSceneLoader(root, name); }; if (engine) window.addEventListener("resize", () => { engine.resize(); }); </script> Where do I put this code below inside Babylon.js code? function updateColor(custPicker) { // This is only to show you the return value when the color picker is the trigger. // This returns a hexadecimal string ex: #FFCC00 var colorval = custPicker.toHEXString(); console.log(colorval); }
You can put it anywhere inside your script tag like this: <!-- this is the external color picker --> <input class="jscolor {onFineChange:'updateColor(this)'}" value="ffcc00" style="position: absolute;z-index: 999;"> <!-- end of external color picker --> <script type="text/javascript"> function updateColor(custPicker) { // this only to show you return value when color picker is trigger // this return hex string ex: #FFCC00 var colorval = custPicker.toHEXString(); console.log(colorval); } // Your other code goes here: // ... </script>
inherit the createjs.Container from easeljs library
I am using Easeljs in my spare time. I tried to inherit the Container from createjs object in easeljs library. var innovative = {}; innovative.object = {}; innovative.object.Basic = function () { }; //innovative.object.Basic.prototype = new createjs.Container; innovative.object.LocalPhoto = function (data) { }; innovative.object.LocalPhoto.prototype = new innovative.object.Basic; innovative.object.LocalPhoto.prototype.constructor = innovative.object.LocalPhoto; I have function in LocalPhoto which will add itself to the stage like this innovative.object.LocalPhoto.prototype.load = function (stage, event) { var self = this; stage.addChild(self); stage.update(); }; This is how i create LocalPhoto object var self = this; for (var i = 0; i < values.length; i++) { this.download (values[i], function (evt) { var photo; photo = new innovative.object.LocalPhoto(evt.target.object); photo.load(self.stage, evt); }); } Problem i am facing is when i add a LocalPhoto into the stage, the rest of the localPhoto within that stage will append the same photo as well. This is what i mean in steps : 1) insert a image within a container and added to the stage. 2) another image within a new container and added to the stage. At the same time, the later image also added to the other child container which i have added to the stage.
(function() { function YourFunc(param) { this.Container_constructor(); this.param = param; } var p = createjs.extend(YourFunc, createjs.Container); p.draw = function() { this.Container_draw(); // add custom logic here. } window.Button = createjs.promote(Button, "Container"); }()); Or Just var p = YourFunc.prototype = new createjs.Container();
Issue related to Registering Event in For loop
I have small application in Famo.us framework. I have added four images in mainContext with draggable modifier using four loop. I want fire an event when user drag the event for that I have added following code. var Engine = require('famous/core/Engine'); var Surface = require('famous/core/Surface'); var Transform = require('famous/core/Transform'); var MouseSync = require("famous/inputs/MouseSync"); var StateModifier = require('famous/modifiers/StateModifier'); var Draggable = require("famous/modifiers/Draggable"); var ImageSurface = require('famous/surfaces/ImageSurface'); var Transitionable = require("famous/transitions/Transitionable"); var SnapTransition = require("famous/transitions/SnapTransition"); Transitionable.registerMethod('snap', SnapTransition); // create the main context var mainContext = Engine.createContext(); var mouseSync = new MouseSync(); var isPlus; var isFirst = true; var oldValues = []; var mySurfaces=[]; var draggables = []; var myModifiers= []; var images = [ ['img/svelteMan.png', -0.4375 * window.innerWidth, -1.5 * window.innerWidth], ['img/swimmer.png', 0 * window.innerWidth, -0.96875 * window.innerWidth], ['img/soccerPlayer.png', -0.21875 * window.innerWidth, -0.984375 * window.innerWidth], ['img/breakDancer.png', 0 * window.innerWidth, -0.6875 * window.innerWidth] ]; for(var i=0;i<images.length;i++) { var mySurface = new ImageSurface({ }); mySurface.setContent(images[i][0]); var myModifier = new StateModifier({ origin: [0.5, 0.5] }); var draggable = new Draggable({ }); mySurface.pipe(draggable); mySurfaces.push(mySurface); myModifiers.push(myModifier); draggables.push(draggable); mainContext.add(draggables[i]).add(myModifiers[i]).add(mySurfaces[i]); var oldValue =0; oldValues.push(oldValue); } ActivateEvent(); function ActivateEvent(){ for(var i=0;i<images.length;i++) { draggables[i].on('update', function (data) { MakeMove(i); }); } }; function MakeMove(i) { //alert(i); if (oldValues[i] > draggables[i].getPosition()[0]) { myModifiers[i].setTransform(Transform.rotateZ(-0.1)); } else { myModifiers[i].setTransform(Transform.rotateZ(0.1)); } oldValues[i] = draggables[i].getPosition()[0]; } I have added onUpdate event of Draggable as following : for(var i=0;i<images.length;i++) { draggables[i].on('update', function (data) { MakeMove(i); }); } But I am getting error saying draggables[i] is not defined If I want to call an event of Third image on draggable then how to call event? How to register an events when surfaces added in for loop? Thanks
Add a closure: var cl = function(n) { return function(data){ MakeMove(n); }; }; for(var i=0;i<images.length;i++) { draggables[i].on('update', cl(i)); } Hope it helps.
You have a closure problem. Take a look of this: var draggables = []; for(i=0;i<10;i++) { var draggable = new Draggable({ }); draggables.push(draggable); } ActivateEvent(); function ActivateEvent(){ for(var i=0;i<10;i++) { setTimeout(function() { MakeMove(i); }(i),0); //<----- notice the (i), this how you can send the correct loop for MakeMove function, without that (i) the anonymous function scope breaks the loop } } function MakeMove(i) { console.log(draggables[i]); //==> this outputs the draggables } Maybe you can try this: draggables[i].on('update', function (data) { MakeMove(i); }(i)); <----- now the loop is send to makeMove
Adding a counter to a prev/next image slideshow(javascript/css only)?
I have created a "prev/next" slideshow using javascript, now I want to add a counter(1/10, 2/10, 3/10...) beside my "prev/next" buttons but nothing seemed to work. This is my first time attempting to make a website, I know nothing about jQuery, so please stick with html+javascript if possible. Here is my script var image = new Array( "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg", "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg") var imgNumber=1 var numberOfImg=2 function previousImage(){ if(imgNumber>1){ imgNumber-- } else{ imgNumber = numberOfImg } document.slideImage.src = image[imgNumber-1] } function nextImage(){ if(imgNumber < numberOfImg){ imgNumber++ } else{ imgNumber = 1 } document.slideImage.src = image[imgNumber-1] } if(document.images){ var image1 = new Image() image1.src = "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg" var image2 = new Image() image2.src = "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg" } Script+html: http://jsfiddle.net/nLHY9/5/ (Prev/Next buttons seem not to be working on this----they work fine when I launched them from laptop to browser.)
you could have used some existing javascript image sliders, for example, sliderman slider, for your current code, you can do like, add an element like span, to hold the count, and you could add a function like: function changeCounter(cur, total) { document.getElementById("counter").innerHTML = cur + "/" + total; } and call it in your previousImage() and nextImage() functions, as in this demo jsfiddle
There are many pure css slideshows that are beautiful and can do impressive things. However, as you try to support older browsers, the pure css slideshows get less and less impressive or even impossible. JavaScript is the most flexible and powerful way to go. That being, I wanted to help you clean up your code. I only had a few minutes, so this is a quickly thrown together plugin, but it should get you on the right track. First, a few notes on your code: //you're missing semicolons everywhere. ";" /* "var image" is very unclear. * it's an array, so it should be plural "images" * there aren't images in this array - it's image urls or sources * instead of "new Array" you could just use "[]" */ var image = new Array( "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg", "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg") var imgNumber=1 //the name doesn't mean anything. I have to assume that you mean "currentImgNumber" or something to that effect var numberOfImg=2 //this could be determined by checking the length of your array - myArray.length And here's my exampe plugin: Live demo here (click). /***** This section is how you use the plugin. I start writing with the usage and then I make it mean something *****/ window.onload = function() { //when the page is loaded var fooElem = document.getElementById('foo'); //get an element where we will attach the plugin var foo = Object.create(slideshow); //create a new slideshow object foo.create({ //create a slideshow with the given options element: fooElem, //the element where the slideshow will be sources: [ //image urls "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg", "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg" ] }); //we can make more of these and with different options var barElem = document.getElementById('bar'); var bar = Object.create(slideshow); bar.create({ element: barElem, sources: [ "http://eggboss.com/wp-content/uploads/2013/09/The-Gentleman-233x300.png", "http://fc07.deviantart.net/fs71/f/2013/040/8/a/profile_picture_by_classy_like_a_sir-d5uf426.jpg" ] }); }; /**** now let's create the plugin and make it work as it is used above *****/ var slideshow = { currentIndex: 0, imgs: [], create: function(options) { options.element.className+= ' slideshow'; //add a class to the main element for styling this.imgs = this.getImgs(options.sources); //make img html var controls = this.getControls(); //make controls //add the html to the element from the options var frag = document.createDocumentFragment(); this.imgs.forEach(function(img) { frag.appendChild(img); }); frag.appendChild(controls); options.element.appendChild(frag); }, getImgs: function(sources) { var imgs = []; sources.forEach(function(src, i) { var img = document.createElement('img'); img.src = src; imgs.push(img); if (i > 0) { img.style.display = 'none'; //hide all but first image } }); return imgs; }, getControls: function() { var that = this; //so that we can access "this" within the click functions var controls = document.createElement('div'); controls.className = 'controls'; var counter = document.createElement('span'); counter.className = 'counter'; this.setCounter(counter); var prev = document.createElement('a'); prev.textContent = 'Prev'; prev.className = 'prev'; prev.addEventListener('click', function() { newIndex = (that.currentIndex) ? that.currentIndex-1 : that.imgs.length-1; that.changeImg(newIndex, counter); }); var next = document.createElement('a'); next.textContent = 'Next'; next.className = 'next'; next.addEventListener('click', function() { newIndex = (that.currentIndex !== that.imgs.length-1) ? that.currentIndex+1 : 0; that.changeImg(newIndex, counter); }); controls.appendChild(prev); controls.appendChild(next); controls.appendChild(counter); return controls; }, changeImg: function(newIndex, counter) { this.imgs[this.currentIndex].style.display = 'none'; this.imgs[newIndex].style.display = 'inline'; this.currentIndex = newIndex; this.setCounter(counter); }, setCounter: function(counter) { counter.textContent = (this.currentIndex+1)+' / '+this.imgs.length; } };