Related
In a project I have to create a carousel in Elementor which should look like the one below:
carousel design
Using the widget from Elementor I couldn't create a carousel like this so I tried to create my own carousel using Easy-Responsive-jQuery-Carousel:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>jQuery FilmRoll Examples</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="https://www.jqueryscript.net/demo/Easy-Responsive-jQuery-Carousel-Slider-Plugin-FilmRoll/css/bootstrap.min.css">
<link rel="stylesheet" href="https://www.jqueryscript.net/demo/Easy-Responsive-jQuery-Carousel-Slider-Plugin-FilmRoll/css/bootstrap-responsive.min.css">
<style type="text/css">
body {
padding-top: 0;
padding-bottom: 40px;
}
.hero-unit {
text-align: center;
border-radius: 0;
margin: 150px 0 0 0;
background: #1e5799; /* Old browsers */
background: -moz-linear-gradient(top, #1e5799 0%, #338cd6 59%, #ffffff 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#1e5799), color-stop(59%,#338cd6), color-stop(100%,#ffffff)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #1e5799 0%,#338cd6 59%,#ffffff 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #1e5799 0%,#338cd6 59%,#ffffff 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #1e5799 0%,#338cd6 59%,#ffffff 100%); /* IE10+ */
background: linear-gradient(to bottom, #1e5799 0%,#338cd6 59%,#ffffff 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1e5799', endColorstr='#ffffff',GradientType=0 ); /* IE6-9 */
}
.hero-unit h1, .hero-unit p.white { color: white; }
.hero-unit h1 img { vertical-align: bottom; }
.hero-unit p { margin-top: 30px; }
.film_roll_wrapper img {
border: 10px solid white;
box-shadow: 7px 7px 15px #777;
margin-left: 5px;
margin-right: 5px;
transition: all 1s ease;
}
.film_roll_wrapper .active img {
border: 10px solid yellow;
height: 600px;
}
.film_roll_container {
position: relative;
}
.film_roll_child.active {
padding-top: 70px;
}
#media (max-width: 979px) {
body {
padding-top: 0px;
}
.navbar-fixed-top {
margin-bottom: 0;
}
}
#media (max-width: 767px) {
.hero-unit {
margin-left: -20px;
margin-right: -20px;
}
}
</style>
</head>
<body>
<div id='film_roll_1'>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
<script src="https://www.jqueryscript.net/demo/Easy-Responsive-jQuery-Carousel-Slider-Plugin-FilmRoll/js/bootstrap.min.js"></script>
<!--<script src="https://www.jqueryscript.net/demo/Easy-Responsive-jQuery-Carousel-Slider-Plugin-FilmRoll/js/jquery.film_roll.js"></script>-->
<script type="text/javascript">
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
this.FilmRoll = (function() {
function FilmRoll(options) {
this.options = options != null ? options : {};
this.rotateRight = __bind(this.rotateRight, this);
this.rotateLeft = __bind(this.rotateLeft, this);
this.moveRight = __bind(this.moveRight, this);
this.moveLeft = __bind(this.moveLeft, this);
this.clearScroll = __bind(this.clearScroll, this);
this.configureScroll = __bind(this.configureScroll, this);
this.configureWidths = __bind(this.configureWidths, this);
this.configureHover = __bind(this.configureHover, this);
if (this.options.container) {
this.div = jQuery(this.options.container);
if (this.div.length) {
this.configure();
}
}
}
FilmRoll.prototype.configure = function() {
var first_child, shuttle_width,
_this = this;
this.children = this.div.children();
this.children.wrapAll('<div class="film_roll_wrapper"></div>');
this.children.wrapAll('<div class="film_roll_shuttle"></div>');
this.wrapper = this.div.find('.film_roll_wrapper');
this.shuttle = this.div.find('.film_roll_shuttle');
this.rotation = [];
shuttle_width = this.options.shuttle_width ? parseInt(this.options.shuttle_width, 10) : 10000;
this.shuttle.width(shuttle_width);
this.height = this.options.height ? parseInt(this.options.height, 10) : 0;
this.wrapper.height(this.height);
this.shuttle.height(this.height);
if (!(this.options.no_css === true || document.film_roll_styles_added)) {
jQuery("<style type='text/css'> .film_roll_wrapper {display: block; text-align: center; float: none; position: relative; top: auto; right: auto; bottom: auto; left: auto; z-index: auto; width: 100%; margin: 0 !important; padding: 0 !important; overflow: hidden; width: 100%} .film_roll_shuttle {text-align: left; float: none; position: absolute; top: 0; left:0; right: auto; bottom: auto; margin: 0 !important; padding: 0 !important; z-index: auto} .film_roll_prev, .film_roll_next {position:absolute; top:48%; left:15px; width:40px; height:40px; margin:-20px 0 0 0; padding:0; font-size:60px; font-weight:100; line-height:30px; color:white; text-align: center; background: #222; border: 3px solid white; border-radius:23px; opacity:0.5} .film_roll_prev:hover, .film_roll_next:hover {color:white; text-decoration:none; opacity:0.9} .film_roll_next {left:auto; right:15px} .film_roll_pager {text-align:center} .film_roll_pager a {width:5px; height:5px; border:2px solid #333; border-radius:5px; display:inline-block; margin:0 5px 0 0; transition: all 1s ease} .film_roll_pager a:hover {background: #666} .film_roll_pager a.active {background: #333;} .film_roll_pager span {display:none} .film_roll_child .active{padding-top: 70px!important;} </style>").appendTo('head');
document.film_roll_styles_added = true;
}
if (this.options.pager !== false) {
this.pager = jQuery('<div class="film_roll_pager">');
this.div.append(this.pager);
this.children.each(function(i, e) {
var link;
link = jQuery("<a href='#' data-id='" + e.id + "'><span>" + (i + 1) + "</span></a>");
_this.pager.append(link);
return link.click(function() {
var direction, rotation_index;
_this.index = i;
rotation_index = jQuery.inArray(_this.children[i], _this.rotation);
direction = rotation_index < (_this.children.length / 2) ? 'right' : 'left';
_this.moveToIndex(_this.index, direction, true);
return false;
});
});
}
this.pager_links = this.div.find('.film_roll_pager a');
this.mouse_catcher = jQuery('<div style="position:absolute; top:0; left: 0; height: 100%; width: 100%;" class="film_roll_mouse_catcher"></div>');
this.mouse_catcher.appendTo(this.wrapper).mousemove(function(event) {
_this.clearScroll();
return _this.mouse_catcher.remove();
});
first_child = null;
this.children.each(function(i, e) {
var $el;
$el = jQuery(e);
$el.attr('style', 'position:relative; display:inline-block; vertical-align:middle');
$el.attr('data-film-roll-child-id', i);
$el.addClass("film_roll_child");
return _this.rotation.push(e);
});
if (this.options.prev && this.options.next) {
this.prev = jQuery(this.options.prev);
this.next = jQuery(this.options.next);
} else {
this.wrapper.append('<a class="film_roll_prev" href="#">‹</a>');
this.wrapper.append('<a class="film_roll_next" href="#">›</a>');
this.prev = this.div.find('.film_roll_prev');
this.next = this.div.find('.film_roll_next');
}
this.prev.click(function() {
_this.clearScroll();
return _this.moveRight();
});
this.next.click(function() {
_this.clearScroll();
return _this.moveLeft();
});
this.index = this.options.start_index || 0;
this.interval = this.options.interval || 4000;
this.animation = this.options.animation || this.interval / 4;
jQuery(window).resize(function() {
return _this.resize();
});
jQuery(window).load(function() {
_this.configureWidths();
_this.moveToIndex(_this.index, 'right', true);
if (_this.options.scroll !== false) {
_this.configureScroll();
return _this.configureHover();
}
});
this.div.trigger(jQuery.Event("film_roll:dom_ready"));
return this;
};
FilmRoll.prototype.configureHover = function() {
this.div.hover(this.clearScroll, this.configureScroll);
if (this.options.prev && this.options.next) {
this.prev.hover(this.clearScroll, this.configureScroll);
return this.next.hover(this.clearScroll, this.configureScroll);
}
};
FilmRoll.prototype.configureWidths = function() {
var max_el_height,
_this = this;
this.div.trigger(jQuery.Event("film_roll:before_loaded"));
this.width = max_el_height = 0;
this.children.each(function(i, e) {
var $el, el_height;
$el = jQuery(e);
_this.width += $el.outerWidth(true);
el_height = $el.outerHeight(true);
if (el_height > max_el_height) {
return max_el_height = el_height;
}
});
if (!this.options.height) {
this.height = max_el_height;
}
this.wrapper.height(this.height);
this.shuttle.height(this.height);
this.real_width = this.width;
this.shuttle.width(this.real_width * 2);
return this;
};
FilmRoll.prototype.configureScroll = function() {
var _this = this;
if (this.scrolled !== true) {
this.timer = setInterval(function() {
return _this.moveLeft();
}, this.interval);
this.scrolled = true;
}
return this;
};
FilmRoll.prototype.clearScroll = function() {
if (this.scrolled !== false) {
clearInterval(this.timer);
this.scrolled = false;
}
return this;
};
FilmRoll.prototype.marginLeft = function(rotation_index, offset) {
var child, i, margin, _i, _len, _ref;
if (offset == null) {
offset = 0;
}
margin = 0;
_ref = this.rotation;
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
child = _ref[i];
if (i < rotation_index && i >= offset) {
margin += jQuery(child).outerWidth(true);
}
}
return margin;
};
FilmRoll.prototype.marginRight = function(rotation_index, offset) {
var child, i, margin, _i, _len, _ref;
if (offset == null) {
offset = 0;
}
offset = this.rotation.length - offset - 1;
margin = 0;
_ref = this.rotation;
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
child = _ref[i];
if (i > rotation_index && i <= offset) {
margin += jQuery(child).outerWidth(true);
}
}
return margin;
};
FilmRoll.prototype.moveLeft = function() {
this.index = (this.index + 1) % this.children.length;
this.moveToIndex(this.index, 'left', true);
return false;
};
FilmRoll.prototype.moveRight = function() {
this.index -= 1;
if (this.index < 0) {
this.index = this.children.length - 1;
}
this.moveToIndex(this.index, 'right', true);
return false;
};
FilmRoll.prototype.moveToIndex = function(index, direction, animate) {
var child, new_left_margin, rotation_index, visible_margin, wrapper_width,
_this = this;
if (animate == null) {
animate = true;
}
child = this.children[index];
rotation_index = jQuery.inArray(child, this.rotation);
this.children.removeClass('active');
jQuery(child).addClass('active').trigger(jQuery.Event("film_roll:activate"));
this.pager_links.removeClass('active');
jQuery(this.pager_links[index]).addClass('active');
wrapper_width = this.wrapper.width();
if (wrapper_width < this.real_width) {
visible_margin = (wrapper_width - jQuery(child).outerWidth(true)) / 2;
if (direction === 'right') {
while (rotation_index === 0 || this.marginLeft(rotation_index) < visible_margin) {
this.rotateRight();
rotation_index = jQuery.inArray(child, this.rotation);
}
} else {
while (rotation_index === this.children.length - 1 || this.marginRight(rotation_index) < visible_margin) {
this.rotateLeft();
rotation_index = jQuery.inArray(child, this.rotation);
}
}
new_left_margin = -1 * (this.marginLeft(rotation_index) - visible_margin);
if (animate) {
this.shuttle.stop().animate({
'left': new_left_margin
}, this.animation, 'swing', function() {
return _this.div.trigger(jQuery.Event("film_roll:moved"));
});
} else {
this.shuttle.css('left', new_left_margin);
this.div.trigger(jQuery.Event("film_roll:moved"));
}
} else {
this.shuttle.css('left', (wrapper_width - this.width) / 2);
}
return this;
};
FilmRoll.prototype.resize = function() {
var _this = this;
this.clearScroll();
clearTimeout(this.resize_timer);
this.resize_timer = setTimeout(function() {
_this.configureScroll();
_this.moveToIndex(_this.index, 'left');
return _this.div.trigger(jQuery.Event("film_roll:resized"));
}, 200);
return this;
};
FilmRoll.prototype.rotateLeft = function() {
var _css_left, _first_child, _shuttle_left;
_css_left = this.shuttle.css('left');
_shuttle_left = _css_left ? parseInt(_css_left, 10) : 0;
_first_child = this.rotation.shift();
this.rotation.push(_first_child);
this.shuttle.css('left', _shuttle_left + jQuery(_first_child).outerWidth(true));
return this.shuttle.append(this.shuttle.children().first().detach());
};
FilmRoll.prototype.rotateRight = function() {
var _css_left, _last_child, _shuttle_left;
_css_left = this.shuttle.css('left');
_shuttle_left = _css_left ? parseInt(_css_left, 10) : 0;
_last_child = this.rotation.pop();
this.rotation.unshift(_last_child);
this.shuttle.css('left', _shuttle_left - jQuery(_last_child).outerWidth(true));
return this.shuttle.prepend(this.shuttle.children().last().detach());
};
return FilmRoll;
})();
}).call(this);
</script>
<script type="text/javascript">
(function() {
jQuery(function() {
this.film_rolls || (this.film_rolls = []);
this.film_rolls['film_roll_1'] = new FilmRoll({
container: '#film_roll_1',
height: 750
});
//return true;
});
}).call(this);
</script>
</body>
</html>
The customer wants the carousel to be modified not from Custom FIeld which was easier to do and directly from the Elementor.So I tried to create my own widget for that.
after a tutorial on youtube and using information from the official documentation from Elementor
Website and I created the following files.
The filles are situated in boostrap4-child in a folder call custom_widget_elementor after I created this php files in boostrap4-child theme in a folder call custom_widget_elementor.
//my-widgets.php
<?php
class My_Elementor_Widgets {
protected static $instance = null;
public static function get_instance() {
if ( ! isset( static::$instance ) ) {
static::$instance = new static;
}
return static::$instance;
}
protected function __construct() {
require_once('widget1.php');
add_action( 'elementor/widgets/widgets_registered', [ $this, 'register_widgets' ] );
}
public function register_widgets() {
\Elementor\Plugin::instance()->widgets_manager->register_widget_type( new \Elementor\My_Widget_1() );
}
}
add_action( 'init', 'my_elementor_init' );
function my_elementor_init() {
My_Elementor_Widgets::get_instance();
}
?>
//widget1.php
<?php
namespace Elementor;
class My_Widget_1 extends Widget_Base {
public function get_name() {
return 'title-subtitle';
}
public function get_title() {
return 'title & sub-title';
}
public function get_icon() {
return 'fa fa-font';
}
public function get_categories() {
return [ 'basic' ];
}
protected function _register_controls() {
$this->start_controls_section(
'section_title',
[
'label' => __( 'Content', 'elementor' ),
]
);
$this->add_control(
'title',
[
'label' => __( 'Title', 'elementor' ),
'label_block' => true,
'type' => Controls_Manager::TEXT,
'placeholder' => __( 'Enter your title', 'elementor' ),
]
);
$this->add_control(
'subtitle',
[
'label' => __( 'Sub-title', 'elementor' ),
'label_block' => true,
'type' => Controls_Manager::TEXT,
'placeholder' => __( 'Enter your sub-title', 'elementor' ),
]
);
$this->add_control(
'link',
[
'label' => __( 'Link', 'elementor' ),
'type' => Controls_Manager::URL,
'placeholder' => __( 'https://your-link.com', 'elementor' ),
'default' => [
'url' => '',
]
]
);
$this->end_controls_section();
}
protected function render() {
$settings = $this->get_settings_for_display();
$url = $settings['link']['url'];
echo "<a href='$url'><div class='title'>$settings[title]</div> <div class='subtitle'>$settings[subtitle]</div></a>";
}
protected function _content_template() {
}
}
?>
In child theme in function.php as I see in exemple i write this.
//Function.php
require_once('elementor_custom_catousel/widget1.php');
But this does not work, although I have tried as many examples from the official documentation.that is, when I save, nothing appears in the basic categories in the elementor if i would solve this problem to build a carousel i just need to make html template.
Clearly mentioned on Official Documentation.
First, you need to register "elementor/widgets/widgets_registered" hook with a function. For Themes apply you can apply this way -
//Add Elementor Widgets
add_action('elementor/widgets/widgets_registered', 'widgets_registered');
public function widgets_registered() {
// We check if the Elementor plugin has been installed / activated.
if (defined('ELEMENTOR_PATH') && class_exists('Elementor\Widget_Base')) {
$files_directory = get_template_directory() . '/widgets/*.php';
$files = glob( $files_directory );
foreach($files as $widgets){
require_once $widgets;
}
}
}
Create a directory name "widgets", place all widget files. On this directory all Addons will be registered.
I want some suggestions regarding image upload form like facebook and tumblr which can preview multiple images with caption and description fields with each image and if user wants to remove any image before uploading he is able to do that. So please suggest me how to achieve this i have tried this but i am having issue with removing image from input type = file as it is readonly i am facing problem when i am submitting the form on server. Please give me your ideas i really need help i have deadline of this month i am badly stuck in this problem. I am using php and jquery. Note: Please dont suggest any plugins.
Thanks in advance.
I have face same problem like you
now i have found solution for that i think this will be useful for you to solve your problem
<input type="file" id="attachfile" name="replyFiles" multiple> <!--File Element for multiple intput-->
<div id="#filelist"></div>
<script>
var selDiv = "";
var storedFiles = []; //store the object of the all files
document.addEventListener("DOMContentLoaded", init, false);
function init() {
//To add the change listener on over file element
document.querySelector('#attachfile').addEventListener('change', handleFileSelect, false);
//allocate division where you want to print file name
selDiv = document.querySelector("#filelist");
}
//function to handle the file select listenere
function handleFileSelect(e) {
//to check that even single file is selected or not
if(!e.target.files) return;
//for clear the value of the selDiv
selDiv.innerHTML = "";
//get the array of file object in files variable
var files = e.target.files;
var filesArr = Array.prototype.slice.call(files);
//print if any file is selected previosly
for(var i=0;i<storedFiles.length;i++)
{
selDiv.innerHTML += "<div class='filename'> <span class='removefile' data-file='"+storedFiles[i].name+"'> " + storedFiles[i].name + "</span></div>";
}
filesArr.forEach(function(f) {
//add new selected files into the array list
storedFiles.push(f);
//print new selected files into the given division
selDiv.innerHTML += "<div class='filename'> <span class='removefile' data-file='"+storedFiles[i].name+"'> " + f.name + "</span></div>";
});
//store the array of file in our element this is send to other page by form submit
$("input[name=replyfiles]").val(storedFiles);
}
//This function is used to remove the file form the selection
function removeFile(e) {
var file = $(this).data("file"); //To take the name of the file
for(var i=0;i<storedFiles.length;i++) { //for find the file from the array
if(storedFiles[i].name === file) {
storedFiles.splice(i,1); //remove file from the list
break;
}
}
//now store the list of the all remaining file in our element name which will submit with the form
$("input[name=replyfiles]").val(storedFiles);
$(this).parent().remove();
}
$(document).ready(function(){
$("body").on("click", ".removefile", removeFile);
})
</script>
//I added event handler for the file upload control to access the files properties.
document.addEventListener("DOMContentLoaded", init, false);
//To save an array of attachments
var AttachmentArray = [];
//counter for attachment array
var arrCounter = 0;
//to make sure the error message for number of files will be shown only one time.
var filesCounterAlertStatus = false;
//un ordered list to keep attachments thumbnails
var ul = document.createElement("ul");
ul.className = "thumb-Images";
ul.id = "imgList";
function init() {
//add javascript handlers for the file upload event
document
.querySelector("#files")
.addEventListener("change", handleFileSelect, false);
}
//the handler for file upload event
function handleFileSelect(e) {
//to make sure the user select file/files
if (!e.target.files) return;
//To obtaine a File reference
var files = e.target.files;
// Loop through the FileList and then to render image files as thumbnails.
for (var i = 0, f; (f = files[i]); i++) {
//instantiate a FileReader object to read its contents into memory
var fileReader = new FileReader();
// Closure to capture the file information and apply validation.
fileReader.onload = (function(readerEvt) {
return function(e) {
//Apply the validation rules for attachments upload
ApplyFileValidationRules(readerEvt);
//Render attachments thumbnails.
RenderThumbnail(e, readerEvt);
//Fill the array of attachment
FillAttachmentArray(e, readerEvt);
};
})(f);
// Read in the image file as a data URL.
// readAsDataURL: The result property will contain the file/blob's data encoded as a data URL.
// More info about Data URI scheme https://en.wikipedia.org/wiki/Data_URI_scheme
fileReader.readAsDataURL(f);
}
document
.getElementById("files")
.addEventListener("change", handleFileSelect, false);
}
//To remove attachment once user click on x button
jQuery(function($) {
$("div").on("click", ".img-wrap .close", function() {
var id = $(this)
.closest(".img-wrap")
.find("img")
.data("id");
//to remove the deleted item from array
var elementPos = AttachmentArray.map(function(x) {
return x.FileName;
}).indexOf(id);
if (elementPos !== -1) {
AttachmentArray.splice(elementPos, 1);
}
//to remove image tag
$(this)
.parent()
.find("img")
.not()
.remove();
//to remove div tag that contain the image
$(this)
.parent()
.find("div")
.not()
.remove();
//to remove div tag that contain caption name
$(this)
.parent()
.parent()
.find("div")
.not()
.remove();
//to remove li tag
var lis = document.querySelectorAll("#imgList li");
for (var i = 0; (li = lis[i]); i++) {
if (li.innerHTML == "") {
li.parentNode.removeChild(li);
}
}
});
});
//Apply the validation rules for attachments upload
function ApplyFileValidationRules(readerEvt) {
//To check file type according to upload conditions
if (CheckFileType(readerEvt.type) == false) {
alert(
"The file (" +
readerEvt.name +
") does not match the upload conditions, You can only upload jpg/png/gif files"
);
e.preventDefault();
return;
}
//To check file Size according to upload conditions
if (CheckFileSize(readerEvt.size) == false) {
alert(
"The file (" +
readerEvt.name +
") does not match the upload conditions, The maximum file size for uploads should not exceed 300 KB"
);
e.preventDefault();
return;
}
//To check files count according to upload conditions
if (CheckFilesCount(AttachmentArray) == false) {
if (!filesCounterAlertStatus) {
filesCounterAlertStatus = true;
alert(
"You have added more than 10 files. According to upload conditions you can upload 10 files maximum"
);
}
e.preventDefault();
return;
}
}
//To check file type according to upload conditions
function CheckFileType(fileType) {
if (fileType == "image/jpeg") {
return true;
} else if (fileType == "image/png") {
return true;
} else if (fileType == "image/gif") {
return true;
} else {
return false;
}
return true;
}
//To check file Size according to upload conditions
function CheckFileSize(fileSize) {
if (fileSize < 300000) {
return true;
} else {
return false;
}
return true;
}
//To check files count according to upload conditions
function CheckFilesCount(AttachmentArray) {
//Since AttachmentArray.length return the next available index in the array,
//I have used the loop to get the real length
var len = 0;
for (var i = 0; i < AttachmentArray.length; i++) {
if (AttachmentArray[i] !== undefined) {
len++;
}
}
//To check the length does not exceed 10 files maximum
if (len > 9) {
return false;
} else {
return true;
}
}
//Render attachments thumbnails.
function RenderThumbnail(e, readerEvt) {
var li = document.createElement("li");
ul.appendChild(li);
li.innerHTML = [
'<div class="img-wrap"> <span class="close">×</span>' +
'<img class="thumb" src="',
e.target.result,
'" title="',
escape(readerEvt.name),
'" data-id="',
readerEvt.name,
'"/>' + "</div>"
].join("");
var div = document.createElement("div");
div.className = "FileNameCaptionStyle";
li.appendChild(div);
div.innerHTML = [readerEvt.name].join("");
document.getElementById("Filelist").insertBefore(ul, null);
}
//Fill the array of attachment
function FillAttachmentArray(e, readerEvt) {
AttachmentArray[arrCounter] = {
AttachmentType: 1,
ObjectType: 1,
FileName: readerEvt.name,
FileDescription: "Attachment",
NoteText: "",
MimeType: readerEvt.type,
Content: e.target.result.split("base64,")[1],
FileSizeInBytes: readerEvt.size
};
arrCounter = arrCounter + 1;
}
/*Copied from bootstrap to handle input file multiple*/
.btn {
display: inline-block;
padding: 6px 12px;
margin-bottom: 0;
font-size: 14px;
font-weight: normal;
line-height: 1.42857143;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: none;
border: 1px solid transparent;
border-radius: 4px;
}
/*Also */
.btn-success {
border: 1px solid #c5dbec;
background: #d0e5f5;
font-weight: bold;
color: #2e6e9e;
}
/* This is copied from https://github.com/blueimp/jQuery-File-Upload/blob/master/css/jquery.fileupload.css */
.fileinput-button {
position: relative;
overflow: hidden;
}
.fileinput-button input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
-ms-filter: "alpha(opacity=0)";
font-size: 200px;
direction: ltr;
cursor: pointer;
}
.thumb {
height: 80px;
width: 100px;
border: 1px solid #000;
}
ul.thumb-Images li {
width: 120px;
float: left;
display: inline-block;
vertical-align: top;
height: 120px;
}
.img-wrap {
position: relative;
display: inline-block;
font-size: 0;
}
.img-wrap .close {
position: absolute;
top: 2px;
right: 2px;
z-index: 100;
background-color: #d0e5f5;
padding: 5px 2px 2px;
color: #000;
font-weight: bolder;
cursor: pointer;
opacity: 0.5;
font-size: 23px;
line-height: 10px;
border-radius: 50%;
}
.img-wrap:hover .close {
opacity: 1;
background-color: #ff0000;
}
.FileNameCaptionStyle {
font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div>
<label style="font-size: 14px;">
<span style='color:navy;font-weight:bold'>Attachment Instructions :</span>
</label>
<!--To give the control a modern look, I have applied a stylesheet in the parent span.-->
<span class="btn btn-success fileinput-button">
<span>Select Attachment</span>
<input type="file" name="files[]" id="files" multiple accept="image/jpeg, image/png, image/gif,"><br />
</span>
<output id="Filelist"></output>
</div>
i have following code for get data from database and sort draggable list using jquery ui elements.
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<style>
#sortable { list-style-type: none; margin: 0; padding: 0; width: 60%; }
#sortable li { margin: 0 3px 3px 3px; padding: 0.4em; padding-left: 1.5em; font-size: 1.4em; height: 18px; background-color:#CCC;}
#sortable li span { position: absolute; margin-left: -1.3em; }
</style>
<script>
$(function() {
$( "#sortable" ).sortable();
$( "#sortable" ).disableSelection();
});
</script>
<?php
$con=mysqli_connect("localhost","root","","db_name");
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$user_id = $_SESSION['user_id'];
$result = mysqli_query($con,"SELECT * FROM users WHERE user_id = '$user_id'");
echo "<ul id='sortable'>";
while($row = mysqli_fetch_array($result))
{
echo "<li class='ui-state-default'>" . $row['Name'] . ' ' . $row['UserName'] . $row['sort'] ."</li>";
}
echo "</ul>";
mysqli_close($con);
?>
This is my database table structure
Table Name = users
Columns = user_id, Name, UserName, Password, sort
Example Results
user_id Name UserName Password sort
1 AAA aa *** 1
2 BBB bb *** 2
3 CCC cc *** 3
4 DDD dd *** 4
what i am asking is, i can Reorder list items by using jquery draggable properties, but how can i save sort number to database if reordered list items.?
jQuery UI sortable has a stop callback which is called when you stop moving a sortable. It also has a serialize function that you can use in combination to send the order of your sortables to your to the process which updates your database. You can use it like this:
To use serialize you need to amend your sortable element in the DOM so that it contains a reference to the user_id. E.g.
<li class="ui-state-default" id="id_<?php echo $row['user_id'] ?>">...</li>
Then when you serialize the sortable, it will build a list of parameters. You don't have to use the id attribute to reference your data, read more about the serialize method here. But below is an example of how you can do it using the id attribute
var $sortable = $( "#sortable" );
$sortable.sortable({
stop: function ( event, ui ) {
// parameters will be a string "id[]=1&id[]=3&id[]=10"...etc
var parameters = $sortable.sortable( "serialize" );
// send new sort data to process
$.post("/sort/my/data.php?"+parameters);
}
});
You then need a process that receives this data and updates the database. I'll leave most of this up to you, but here's a minimal example.
<?php
// Store user IDs in array. E.g. array(0 => "1", 1 => "3", 2 => "10"....)
$userIds = $_POST['id'];
// Connect to your database
$conn = mysqli_connect("localhost","root","","db_name");
foreach ($userIds as $key => $userId) {
$sequence = $key + 1;
$stmt = $conn->prepare("UPDATE users SET sort = $sequence WHERE user_id = ?");
$stmt->bind_param("i", (int) $userId);
$stmt->execute();
}
$stmt->close();
i have searched feverishly for a solution to my gallery, which doesnt apply the centering function to the image as i click it's respective thumbnail. instead i have to click the thumbnail at least twice for the large image to pop up in the center of the page. the gallery is a jquery/php. i have dynamically loaded my thumbnails using php and link them to the respective large image with the same name using php. I am wondering preloading the large image would help this problem if so how can i preload them seeing as though its an entire directory which has alot of pictures, hence why i didnt manually load them. the script is below:
<?php
error_reporting(0);
/* function: returns files from dir */
function get_files($images_dir,$exts = array('jpeg','gif','png','jpg')) {
$files = array();
if($handle = opendir($images_dir)) {
while(false !== ($file = readdir($handle))) {
$extension = strtolower(get_file_extension($file));
if($extension && in_array($extension,$exts)) {
$files[] = $file;
}
}
closedir($handle);
}
return $files;
}
/* function: returns a file's extension */
function get_file_extension($file_name) {
return substr(strrchr($file_name,'.'),1);
}
$images_dir = 'hftpnyc/thumbs/';
$thumbs_dir = 'hftpnyc/thumbs/thumbnails/';
$thumbs_width = 100;
$images_per_row = 11;
$string = "";
/** generate photo gallery **/
$image_files = get_files($images_dir);
if(count($image_files)) {
$index = 0;
foreach($image_files as $index=>$file) {
$index++;
$thumbnail_image = $thumbs_dir.$file;
//if(!file_exists($thumbnail_image)) {
//$extension = get_file_extension($thumbnail_image);
//if($extension) {
//make_thumb($images_dir.$file,$thumbnail_image,$thumbs_width);
//}
//}
error_reporting(0);
echo '<div class="smllpic" style=" padding: 0px; margin: 0px; border: 1px solid black; display: block; width: 100px; height:100px; float: left; "> <img id="thumbs" src="',$thumbnail_image,'" width="100px"/></div>';
if($index % $images_per_row == 0) { echo '<div class="clear"></div>'; }
}
}
else {
echo '<p>There are no images in this gallery.</p>';
}
?>
<script type="text/javascript">
$(document).ready(function(){
$('.smllpic img').hover(function () {
var $this = $(this);
$this.stop().animate({'opacity':'1.0'},200);
},function () {
var $this = $(this);
$this.stop().animate({'opacity':'0.7'},200);
});
function centreit(){
//get the height and width of the modal
var modal_height = $('.box').height();
var modal_width = $('.box').width();
//get the height and width of the page
var window_width = $(window).width();
var window_height = $(window).height();
//calculate top and left offset needed for centering
var topp = (window_height - modal_height)/2;
var left = (window_width - modal_width)/2;
//apply new top and left css values
$('.box').css({'top' : topp+'px' , 'left' : left+'px', 'right': left+'px','bottom':topp+'px'});
$('.motown').css({'top' : topp+'px' , 'left' : left+'px', 'right': left+'px','bottom':topp+'px'});
};
$('.lightbox').click(function(e) {
e.preventDefault(); // keeps new page from loading
var thisPicture = $(this).attr('href'); // path to full sized picture,
function getit(){
$('body').append('<div class="backdrop" label="click to close"></div><div class="box" id="centre" ><div class="close">x</div><div style="cursor:pointer; opacity:1;font-family:Agency FB;margin-top:50%; right:-20px;position:fixed;color:white;font-size:50px; z-index:50;-webkit-border-radius: 5px;-moz-border-radius: 5px;border-radius: 5px;-moz-box-shadow:0px 0px 5px #444444;-webkit-box-shadow:0px 0px 5px #444444;box-shadow:0px 0px 5px #444444;">></div><div style="cursor:pointer; opacity:.35;font-family:Agency FB;margin-top:50%; left:-20px; position:absolute; font-size:50px;color:white; z-index:70;-webkit-border-radius:5px;-moz-border-radius: 5px; border-radius:5px;-moz-box-shadow:0px 0px 5px #444444; -webkit-box-shadow:0px 0px 5px #444444; box-shadow:0px 0px 5px #444444;"><</div><img class="motown" src="'+thisPicture+'" style="max-height:705px;max-width:905px;" ></div>');
};
centreit();
$(window).resize(function(){
$('.box').resize();
$('.motown').resize();
centreit();
});
if ($('.smllpic').click()){
getit();
centreit();
$("html").css("overflow", "hidden");
$('.backdrop').fadeTo(500,0.9);
$('.box').children().fadeIn(1000);
};
//$('.backdrop').css({ 'display' : 'block', opacity : 0});
$('.close').click(function(){
close_box();});
$('.backdrop').click(function(){
close_box();});
function close_box(){
$('.backdrop').remove();
$('.box').remove();
$("html").css("overflow", "");};
});});
</script>
Don't preload the larger images. You are better off using jQuery to display a loading indicator (you can download gif loading indicators from - http://ajaxload.info/) while the image is being loaded. Once the image has been loaded, remove the indicator.
I am working with a school project. The basic ide of the project is, that we have some arduino boxes the sends some sensor data to a mysql db and we have a website that display it. Sensor data is sending lets say every 6sec.
I don´t have a lot of experience with PHP. But i am tinkerin my way, learing step by step..cowboy style? =)
The html/ajax/css:
<!DOCTYPE html>
<html>
<head>
<title>Arduino event poller</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<style type = "text/css" media="screen">
body{ font:13px/1.5 "helvetica neue", helvetica, arial, san-serif; background:#FFF; }
#main{ width:430px; height: 300px; display:block; padding:10px 0; float: left; overflow: auto;}
.event { display:block; background: #ececec; width:380px; padding:10px; margin:10px; overflow:hidden; text-align: left; }
.event img { display:block; float:left; margin-right:10px; }
.event p { font-weight: bold; }
.event img + p { display:inline; }
.patient-name { display:inline; color: #999999; font-size: 9px; line-height:inherit; padding-left: 5px; }
.event-text{ color: #999999; font-size: 12px; padding-left: 5px; }
.event-timestamp{ color: #000; padding-left: 5px; font-size: 9px;}
</style>
<script type="text/javascript" charset="utf-8">
var timeStamp = null;
/* Simple helper to add some divs.*/
function addevents(patientroom, patientname, eventtyp, timestamp)
{
$("#main").append(
"<div class='event'>"
"<p>" + patientroom + "</p>"
"<p class='patient-name'>" + patientname + "</p>"
"<p class='event-text'>" + eventtyp + "</p>"
"<p class='event-timestamp'>" + timestamp + "</p>"
"</div>"
);
}
/*This requests the url "getevents.php" When it complete*/
function waitForEvents()
{
$.ajax({
type: "GET",
url: "getevents.php?timeStamp=" + timeStamp,
async: true, /* If set to non-async, browser shows page as "Loading.."*/
cache: false,
timeout:50000, /* Timeout in ms */
success: function(data, textStatus, jqXHR) /* called when request to getevents.php completes */
{
addevents(data.patientroom, data.patientname, data.eventtyp, data.timestamp);
setTimeout(
waitForEvents, /* Request next event */
1000 /* ..after 1 seconds */
);
},
error: function (XMLHttpRequest, textStatus, errorThrown){
alert("Error:" + textStatus + " (" + errorThrown + ")");
setTimeout(
'waitForEvents()', /* Try again after.. */
"5000"); /* milliseconds (5seconds) */
},
});
};
$(document).ready(function(){
waitForEvents(); /* Start the inital request */
});
</script>
</head>
<body>
<div id="main">
</div>
</body>
</html>
My backend php:
<?php
function getEvents()
{
$con = mysql_connect("localhost","***","***");
if(!con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("arduino_db",$con);
$result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");
if($result)
{
$patientroom = $row['rumNr'];
$patientname = $row['inneboendeNamn'];
$eventtyp = $row['handelse'];
$timestamp = $row['timestamp'];
}
if($row)
{
header('application/json');
echo json_encode($row);
exit;
}
$lastmodif = isset($_GET['timeStamp']) ? $_GET['timeStamp'] : 0;
$currentmodif = filemtime($result);
while($currentmodif <= $lastmodif)
{
unsleepp(1000);
clearstatcache();
$currentmodif = filemtime($result);
}
}
?>
My question:
How to I fetch each row from the db and return each row in JSON format to the method "waitForEvents" in the frontend.
The example doesn't have to be scaleable, secure or complete, it just needs to work =)
UPDATE: new code based on Johns tips. All I gets is a blank page, and no errors.
The first thing that popped out to me is that your MySQL call is sort of blown.
When you run this line:
$result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");
You're going to get a MySQL resource. You need to utilize that to get your row:
$result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");
if ($result)
{
$row = mysql_fetch_assoc($result);
if ($row)
{
// Your result is here, as a big associative array. Each column in your
// table is now keyed to this array. Exact fields will depend on your DB.
//
// Just access it like something like this:
$id = $row['id'];
$time = $row['time_stamp'];
}
}
to echo it back out as JSON:
... // snip
if ($row)
{
header('application/json');
echo json_encode($row);
exit;
}
}
// handle your errors!
added: Additional error found in OP question:
// The following line isn't valid. This isn't what you'll get back from $.ajax.
// success: function(patientroom, patientname, eventtyp, timestamp)
// Corrected code:
success: function(data, textStatus, jqXHR)
/* called when request to getevents.php completes */
{
addevents(data.patientroom, data.patientname, data.eventtyp, data.timestamp);
setTimeout(
waitForEvents, /* Request next event */
1000 /* ..after 1 seconds */
);
},
Further updates. You mixed & matched the code from above.
$result = mysql_query("SELECT * FROM events ORDER BY eventID DESC LIMIT 1");
if($result)
{
// this has to go inside of this check. This is where you *ASSIGN* $row.
$row = mysql_fetch_assoc($result);
// You need to rekey $row before you output:
$retVal = array('patientroom'=>$row['rumNr'],
'patientname'=>$row['inneboendeNamn'],
'eventtyp'=>$row['handelse'],
'timestamp'=>$row['timestamp']);
// I'm not sure what you're doing with the incoming timestamp. Should we just
// return it back out?
$retVal['ajax_timestamp'] = $_GET['timeStamp'];
header('application/json');
echo json_encode($retVal);
exit; // this exits. Comment this out if you want, but don't try to write anything else out to the buffer.
}
// Not sure what you're trying to do here. I'll comment out for now.
/*
$lastmodif = isset($_GET['timeStamp']) ? $_GET['timeStamp'] : 0;
$currentmodif = filemtime($result);
while($currentmodif <= $lastmodif)
{
unsleepp(1000);
clearstatcache();
$currentmodif = filemtime($result);
}
*/
}
I understand know that you shouldnt do long-polling with php. It's to messy if you aint a pro php-hacker and for many other reasons like:
PHP is made for fast execution (not for waiting)
PHP will force you to do some kind of polling on the server side and relying on sleep()
PHP will eat your RAM while so are spawning processes for each requests (Apache will do so)
The thing I need for my project is to show new data without refreshing the hole site. I did it like this:
<script type="text/javascript">
var timeoutId;
var intervalId;
function doIt(){
$("#main").load("refresh.php");
}
$(document).ready(function(){
timeoutId = setTimeout(function(){
doIt();
intervalId = setInterval(function(){
doIt();
}, 5000); //Request the doIt() method every 5ms.
}, 3000); //Delay calculated on the server to trigger the function at the appropriate time
});
</script>