Normalmente, cuando desarrollamos una aplicación que maneja muchas imágenes, probablemente queramos utilizar un carrusel de imágenes, Oracle APEX nos brinda una plantilla llamada Carousel Container la cual se puede aplicar a una región de Oracle APEX y añadirle todas las secciones que queramos para tener un carrusel, sin embargo, este carrusel es estático y lo que vamos a hacer hoy es crear un carrusel dinámico, llamando las imágenes desde la base de datos.

Los primero que debemos hacer es crea un API para llamar imágenes utilizando un URL y el id de la imagen, esto lo podemos hacer siguiendo la siguiente documentación:

Posterior de haber creado nuestra API, vamos a ir a la pantalla donde queramos mostrar nuestro carrusel de imágenes, crearemos una región de tipo static content y en la sección de source text añadiremos el siguiente código:

<div class="slider" id="slider">
  <button type="button" class="button button-prev">
    <i class="fa fa-chevron-left" aria-hidden="true"></i>
  </button>
  <button type="button" class="button button-next">
    <i class="fa fa-chevron-right" aria-hidden="true"></i>
  </button>
</div>
Para que el fondo de la región no se vea, me gusta usar la plantilla llamada Title Bar en la sección de Appearance

Con esto se crearán los botones con los que pasaremos las imágenes.

Dentro de esta región creamos un item de tipo hidden llamado P2_STORE_SLIDER_JSON:

Ahora bien, la tabla que contiene las imágenes de mis productos es la misma tabla que utilice para la creación de mi API, la única diferencia esque le añadí un campo llamado ID_PRODUCTO para filtrar las imágenes:

De esta manera, tendré datos para que cuando haga un filtro pueda llamar las imágenes de un producto, por ejemplo, con el id 203 traigo 2 registros o con el id 242 traigo 2 registros también, esas serán las imágenes a presentar de cada producto:

Lo siguiente que haremos será crear un proceso en la sección de after header en processes:

En la seccion de PL/SLQ Code añadiremos el siguiente código, aquí es donde necesitamos utilizar el url del API creada para llamar las imágenes, si analizamos el código, lo que hago es crear un json donde colocaré la lista de imágenes que necesito cargar, para ello creo un cursor para llamar todas las imágenes pertenecientes a un id y utilizo un item llamado :P4_ID_PRODUCTO de tipo texto para filtrar por el número que tenga ese campo y traer la lista de imágenes que requiero. Al llenar el cursor con la lista de id de imágenes, la recorro y en la línea 28 del script, ejecuto un comando que llama el URL del API y la imagen que pertenece a ese id.

DECLARE
  URL_SERVER_NAME VARCHAR2(500):= 'http://192.168.1.50:8080/ords/tesis/imagenes/';
  --Use your Image Restful Service URL into URL_SERVER_NAME Variable
   CURSOR REPORT 
         IS  
         SELECT
         ID_IMAGEN_PRODUCTO
		 FROM IMAGEN_PRODUCTO WHERE ID_PRODUCTO=:P4_ID_PRODUCTO;
			
		TYPE L_REPORT_TYPE IS RECORD 
	    ( 
        ID_IMAGEN_PRODUCTO             IMAGEN_PRODUCTO.ID_IMAGEN_PRODUCTO%TYPE
		); 
            
		TYPE L_REPORT_TAB IS TABLE OF L_REPORT_TYPE; 
	    L_REPORT		L_REPORT_TAB; 
	 
BEGIN
                   OPEN REPORT; 
				   FETCH REPORT BULK COLLECT INTO L_REPORT; 
                    CLOSE REPORT;
                   
                   APEX_JSON.INITIALIZE_CLOB_OUTPUT;
                   APEX_JSON.OPEN_ARRAY; -- {
                   FOR L_CNT IN L_REPORT.FIRST .. L_REPORT.LAST 
				   LOOP
                       APEX_JSON.OPEN_OBJECT; -- {
                       APEX_JSON.WRITE('imagePath',URL_SERVER_NAME||L_REPORT(L_CNT).ID_IMAGEN_PRODUCTO);
                       APEX_JSON.WRITE('order',  L_REPORT(L_CNT).ID_IMAGEN_PRODUCTO);
                       APEX_JSON.WRITE('url',  '#');
                       APEX_JSON.CLOSE_OBJECT; -- } 
                   END LOOP; 
                   
                    APEX_JSON.CLOSE_ARRAY; -- } 
                    :P2_STORE_SLIDER_JSON:=APEX_JSON.GET_CLOB_OUTPUT;
                    apex_util.set_session_state('P2_STORE_SLIDER_JSON', APEX_JSON.GET_CLOB_OUTPUT);
                    DBMS_OUTPUT.PUT_LINE(APEX_JSON.GET_CLOB_OUTPUT);
                    APEX_JSON.FREE_OUTPUT;
  
 
END;

Esto nos devolverá un json como el siguiente en el campo P2_STORE_SLIDER_JSON:

Ahora para mostrar las imágenes cargadas en el json de nuestro item, iremos a la sección de Function and Global Variables de nuestra página y ahí añadiremos el siguiente código:

Código:

$(function() {
	'use strict';

	var slider = $('#slider'),
	sliderList = $('<ul></ul>'),
	bulletList = $('<ul></ul'),
	sliderJSON =  sliderJSON =  JSON.parse($v( "P2_STORE_SLIDER_JSON" )) ;
	sliderJSON.sort(function(a, b) {
		return a.order - b.order;
	});

	$.each(sliderJSON, function(index, element) {
		sliderList.append("<li><a href='"+ element.url +"'><img src='" + element.imagePath + "' alt=''></a>");
         //+ "<div class='content'>"+ element.slideText +"</div></li>");
		bulletList.append("<li id='bullet_"+ (index + 1) +"'></li>");
	});

	
	sliderList.addClass('sliderList');
	bulletList.addClass('bulletList');
	slider.append(sliderList);
	slider.append(bulletList);

	bulletList.find("li:first-child").addClass('bulletActive');

	var firstSlide = sliderList.find("li:first-child"),
	lastSlide = sliderList.find("li:last-child"),
	buttonPrev = $(".button-prev"),
	buttonNext = $(".button-next"),
	sliderCount = sliderList.children().length,
	sliderWidth = 100.0 / sliderCount,
	slideIndex = 0,
	intervalID;

	lastSlide.clone().prependTo(sliderList);
	firstSlide.clone().appendTo(sliderList);

	sliderList.css({"width": (100 * sliderCount) + "%"});
	sliderList.css({"margin-left": "-100%"});

	sliderList.find("li").each(function(index) {
		var leftPercent = (sliderWidth * index) + "%";
		$(this).css({"left": leftPercent});
		$(this).css({"width": sliderWidth + "%"});
	});

	buttonPrev.on('click', function() {
		slide(slideIndex - 1);
	});
	buttonNext.on('click', function() {
		slide(slideIndex + 1);
	});
	$('.bulletList li').on('click', function() {
		var id = ($(this).attr('id').split('_')[1]) - 1;
		slide(id);
	});

	startTimer();
	slider.on('mouseenter mouseleave', function(e){ 
    	var onMouEnt = (e.type === 'mouseenter') ?  
        clearInterval(intervalID) : startTimer();               
	});


	function slide(newSlideIndex) {

		var marginLeft = (newSlideIndex * (-100) - 100) + "%";
		sliderList.animate({"margin-left": marginLeft}, 400, function() {
			if ( newSlideIndex < 0 ) {
				$(".bulletActive").removeClass('bulletActive');
				bulletList.find("li:last-child").addClass("bulletActive");
				sliderList.css({"margin-left": ((sliderCount) * (-100)) + "%"});
        		newSlideIndex = sliderCount - 1;
        		slideIndex = newSlideIndex;
        		return;
			} else if ( newSlideIndex >= sliderCount ) {
				$(".bulletActive").removeClass('bulletActive');
				bulletList.find("li:first-child").addClass("bulletActive");
				sliderList.css({"margin-left": "-100%"});
				newSlideIndex = 0;
				slideIndex = newSlideIndex;
				return;
			}
			$(".bulletActive").removeClass('bulletActive');
			bulletList.find('li:nth-child('+ (newSlideIndex + 1) +')').addClass('bulletActive');
			slideIndex = newSlideIndex;
		});
	};

	function startTimer() {
		intervalID = setInterval(function() { buttonNext.click(); }, 5000);
		return intervalID;
	};
});

Nota: En la función startTimer() los 5000 ms son para que las imágenes cambien cada 5 segundos, el tiempo se puede cambiar a gusto.

Por último, para darle un diseño responsivo al carrusel con los distintos tamaños de pantalla, añadiremos el siguiente código en la sección de CSS en inline:

Código:

img{
	width: 100%;
}
.t-Form-fieldContainer--floatingLabel .t-Form-inputContainer .apex-item-display-only{
	border-style:none;
	background-color: rgba(0,0,0,0);
	border-color: rgba(0,0,0,0);
	padding-top: 0px;
	min-height: 0px;
}

@media (max-width: 400px){

.slider {
  width: 100% !important;
  overflow: hidden !important;
  height: 370px !important;
  position: relative !important;
}

}

.slider {
  width: 100%;
  overflow: hidden;
  height: 430px;
  position: relative;
}

.sliderList {
  position: absolute;
  top: 0;
  width: 300%;
  height: 100%;
  list-style: none;
}

.sliderList li {
  position: absolute;
  top: 0;
  bottom: 0;
  overflow: hidden;
  width: 33.333333%;
  height: 100%;
  padding: 0;
  margin: 0;
}

.sliderList li img {
  width: 100%;
  border: none;
}

.bulletList {
  position: absolute;
  bottom: 15px;
  width: 100%;
  margin: 0px 38% 0px 38%;
  list-style: none;
}

.bulletList li {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin: 0 5px;
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  -ms-border-radius: 50%;
  border-radius: 50%;
  background-color: #4040407d;
  cursor: pointer;
}

.bulletList .bulletActive { background-color: #0b0d18; }



.button {
  position: absolute;
  bottom: 15px;
  z-index: 2;
  display: block;
  width: 40px;
  height: 40px;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border: none;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  border-radius: 5px;
  background-color: rgb(5 0 36 / 21%);
  color: #fff;
}

.button-prev { left: 15px; }

.button-next { right: 15px; }



Probamos la carga de las imágenes asignando el id 242 al campo de ID_PRODUCTO este campo es un ítem al que le asigno el id estático del producto que quiero que me cargue la lista de imágenes y es el mismo que llamamos el proceso PL/SQL en la línea 8:

Nota: Este id es importante que pueda ser dinámico también, para ello usted puede crear un botón que al presionarlo ejecute el proceso PL/SQL que creamos o bien enviar el id y asignarlo al campo por un url utilizando un formato como el siguiente:

http://host:puerto/ords/f?p=&APP_ID.:<id de la página>:&APP_SESSION.:::: P4_ID_PRODUCTO:242

Puede probarlo colocando el id estático en el campo:

Resultado:

Primera imagen
Segunda imagen
Tercer imagen

O bien llamar las imágenes utilizando el formato de enviar el id por el URL:

De ambas maneras se cargará la lista de imágenes del producto.

En pantallas de celulares se verá de la siguiente forma, si queremos que las imágenes sean más pequeñas o más grandes, podemos jugar con los valores de CSS .slider :

Recuerde cambiar el campo de ID_PRODUCTO a tipo hidden para que el usuario final no lo vea, por último, queda a la creatividad de cada persona sobre como lo quieran implementar en sus aplicaciones.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *