I have a web page that uses dropzone.js. My web page lets people choose their profile picture. If they have already set it, I want to show their picture, but allow them to change it. In an attempt to do this, I'm using the following dropzone code:
var currentPicture = null;
function removeCurrentPicture() {
try {
if (dropzone) {
for (var i = 1; i < dropzone.files.length; i++) {
dropzone.removeFile(dropzone.files[i-1]);
}
}
} catch (ex1) {
console.log(ex1);
}
return false;
}
function setThumbnailWidths() {
var thumbnails = $("*[data-dz-thumbnail]");
for (var i=0; i<thumbnails.length; i++) {
$(thumbnails[i]).css('max-width', '150px');
}
}
var pictureDropZone = new Dropzone("#myPicture", {
url: "/profile/picture/",
maxFilesize: 5,
clickable: true,
uploadMultiple: false,
previewTemplate: previewTemplate,
previewsContainer: "#previews",
init: function () {
dropzone = this;
// add picture if it exists
var pictureUrl = 'DYNAMICALLY POPULATED FROM SERVER';
if (pictureUrl) {
var pictureSize = // POPULATED FROM SERVER;
var pictureFileName = // POPULATED FROM SERVER;
var pictureMimeType = 'img/png';
var currentPicture = { name: pictureFileName, size: pictureSize, type: pictureMimeType };
this.addFile.call(this, currentPicture);
this.options.thumbnail.call(this, currentPicture, pictureUrl);
this.files.push(currentPicture);
$('#picturePrompt').hide();
}
this.on('addedfile', function (file) {
if (dropzone.files.length > 1) {
removeCurrentPicture();
}
$('#picturePrompt').hide();
$("#errorMessage").hide();
});
this.on('removedfile', function (file) {
$('#picturePrompt').show();
});
this.on('success', function (file, res) {
setThumbnailWidths();
});
this.on('error', function (e, m) {
$("#previews").hide();
$("#errorMessage").html('An unknown error has happened. Please try again.');
$("#errorMessage").show();
});
}
});
The HTML that complements this dropzone looks like this:
<div id="myPicture" style="padding:40px; cursor:pointer;">
<div id="picturePrompt">Drop a picture here or just click</div>
<div id="errorMessage" class="error" style="display:none; margin-bottom:8px;"></div>
<div class="files" id="previews">
<div id="template" class="file-row">
<ul class="list-inline">
<li>
<span class="preview" style="width:350px;"><img data-dz-thumbnail /></span>
<p class="size" data-dz-size></p>
</li>
<li style="vertical-align:top;">
<button data-dz-remove class="btn btn-danger" style="margin-top:8px;">
<i class="glyphicon glyphicon-trash pull-left"></i>
<span class="pull-left">Delete</span>
</button>
</li>
</ul>
</div>
</div>
</div>
This code works unless a picture is loaded from the server when the page loads. In the event that pictureUrl is set, the picture renders fine. I can "delete" it. However, if I try to add a new picture, the new thumbnail does not appear. The size of the file does. But the thumbnail does not show.
What am I doing wrong?
Related
I'm trying to upload an image on a Ruby on Rails view using a button that on-click should send an argument to a python script. However I am facing issues.
Here is the code in my index.html.erb:
<div class="container">
<div class="wrapper">
<div class="image">
<img src="" onerror="this.style.display='none'" id = 'image_file'/>
</div>
<div class="content">
<div class="icon">
<i class="fas fa-cloud-upload-alt"></i>
</div>
<div class="text" style="text-align:center;">
No Image
</div>
</div>
<div id="cancel-btn">
<i class="fas fa-times"></i>
</div>
<div class="file-name">
File name here
</div>
</div>
<button onclick="defaultBtnActive()" id="custom-btn" class="active-btn" name="default-btn">Choose a file</button>
<input id="default-btn" type="file" name ='file' hidden>
<button id="submit-btn" class="active-btn modal-btn">Submit</button>
</div>
<div class="bg-modal">
<div id="error">
<div class="close">+</div>
<h1>Error</h1>
<p>Error occurred with uploading image. Did you upload the right file type?</p>
</div>
</div>
</div>
<script>
const wrapper = document.querySelector(".wrapper");
const fileName = document.querySelector(".file-name");
const defaultBtn = document.querySelector("#default-btn");
const customBtn = document.querySelector("#custom-btn");
const cancelBtn = document.querySelector("#cancel-btn i");
const img = document.querySelector("img");
const submitBtn = document.querySelector("#submit-btn");
let regExp = /[0-9a-zA-Z\^\&\'\#\{\}\[\]\,\$\=\!\-\#\(\)\.\%\+\~\_ ]+$/;
function defaultBtnActive(){
defaultBtn.click();
}
defaultBtn.addEventListener("change", function(){
var file = this.files[0];
if(isFileImage(file)){
const reader = new FileReader();
reader.onload = function(){
const result = reader.result;
img.src = result;
img.style.display = 'inline';
const placeholder = document.querySelector(".content");
placeholder.style.visibility = "hidden";
wrapper.classList.add("active");
}
cancelBtn.addEventListener("click", function(){
img.src = "";
wrapper.classList.remove("active");
location.reload();
})
reader.readAsDataURL(file);
}
else {
modalBg.classList.add('bg-active');
}
if(this.value){
let valueStore = this.value.match(regExp);
fileName.textContent = valueStore;
}
});
var modalBtn = document.querySelector('.modal-btn');
var modalBg = document.querySelector('.bg-modal');
var modalClose = document.querySelector('.close');
let {PythonShell} = require('python-shell');
var cloudurl = 'gs://uscentralbucket-vcm/testus.csv';
let options = {
mode: 'text',
pythonOptions: ['-u'], // get print results in real-time
scriptPath: '../auto-ml/',
args: [cloudurl]
};
modalBtn.addEventListener('click', function() {
var file = defaultBtn.files[0];
if (isFileImage(file)) {
window.location.href = "<%= main_review_path %>";
python_script.stdout.on('data', (data) =>{
console.log('Data received from python script', data.toString())
});
PythonShell.run('consolidated_steps.py', options, function (err, results) {
if (err) throw err;
// results is an array consisting of messages collected during execution
console.log('results: %j', results);
});
}
else {
modalBg.classList.add('bg-active');
}
});
modalClose.addEventListener('click', function() {
modalBg.classList.remove('bg-active');
})
function isFileImage(file) {
const acceptedImageTypes = ['image/gif', 'image/jpeg', 'image/png'];
return file && acceptedImageTypes.includes(file['type'])
}
</script>
After applying the relevant PythonShell code, the button in my Rails view does not work anymore. It works if I comment out let{PythonShell} = require('python-shell').
Is there a way to fix the button to be functional again and run the function in the javascript code (and link to my python script), or is there another way to link Javascript within a .erb file to Python?
So i have a project in Laravel, I have added filters, and it filters the products fine. However, when products are filterd my add to cart buttons become unresponsive. I figured after inspecting the rendered code in the browser that the JS was not loaded. However if i manually refresh the page (or refresh in the code with location.reload()) then it works. However I want to avoid manual refresh because then I would lose the colour class added to the button to show that its active filter.
Below is the code for my product file which loads the products in a for loop from the controller:
products.blade.php
<div class="container">
<!--Grid row-->
<div class="row">
#foreach ($products as $p)
<div class="col-lg-3">
<div class="container">
<form action="{{ route('cart.add', $p->id) }}" data-id="{{ $p->id }}" id="addtocart">
<div class="row">
<h5>{{ $p -> name }}</h5>
<button type="button" id="submit" class="button has-shadow is-danger submit is-small">
Add to Cart
</button>
</div>
</form>
</div>
</div>
#endforeach
</div>
<div class="container">
{{ $products ->appends($request->query()) -> links() }}
</div>
</div>
products_show.blade.php - Where the JS is and where the above file is loaded. The issue occurs after the $('body').on('click', '.btn-filter' is called.
#extends ('layouts.app')
#section ('content')
<div class="box text-right">
<div class="row">
<button type="button" name="filter[]" value="Jackets" id="filterJackets" class="button is-info btn-filter">Jackets</button>
<button type="button" name="filter[]" value="Hoodies" id="filterHoodies" class="button is-info btn-filter">Hoodies</button>
</div>
</div>
<section class="products">
#include('product.products')
</section>
#endsection
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$(document)
.ajaxStart(function () {
$("#modal").show();
})
.ajaxStop(function () {
$("#modal").hide();
});
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
// Pagination
$('body').on('click', '.pagination a', function(e) {
var url = $(this).attr('href');
$.ajax({
url : url
}).done(function (data) {
$('.products').html(data);
}).fail(function () {
alert('Products could not be loaded.');
});
window.history.pushState("", "", url);
});
// Add to cart
$(".submit").click(function (e) {
e.preventDefault();
var p_id = $(this).closest("form").data('id');
var product_id = $("#product_id").val();
var url = $(this).closest('form').attr('action');
$.ajax({
url:url,
method:'POST',
data:{
product_id:product_id
},
success:function(response){
console.log("added to cart success");
},
});
});
$('body').off('click', '.btn-filter', function(e) {
$(this).removeClass("is-success");
});
$(".btn-filter").hover(function(){
$(this).addClass("is-danger");
}, function(){
$(this).removeClass("is-danger");
});
var filters = [];
$('body').on('click', '.btn-filter', function(e) {
e.preventDefault();
$(this).toggleClass('is-success');
filters = []; // reset
$('button[name="filter[]"]').each(function()
{
if ($(this).hasClass("is-success")) {
filters.push($(this).val());
}
});
var url = '{{ route('products.type') }}'+'?filter[storage]='+filters
$.ajax({
url : url
}).done(function (data) {
$('.products').html(data);
}).fail(function () {
alert('Products could not be loaded.');
});
window.history.pushState("", "", url);
});
});
</script>
I am not sure if the php code matters because the problem here is the add to cart button JS is not being called, but here it is anyways:
public function filterByType(Request $request){
$products = QueryBuilder::for(Auth::user()->products())
->allowedFilters(['type'])->paginate()
->appends(request()->query());
// Check if request is from ajax
if ($request->ajax()) {
return view('product.products', ['products' => $products])->render();
}
return view('product.products_show', compact('products'));
}
Thanks.
So i found a hackway to do this, However is there a better solution or a way to fix my issue? And is what i did here bad?:
I added location.reload() to the end of the btn-filter on click which will reload the page since reloading the page fixes the issue for me.
I then added the code below to the top of the script:
var window_url = window.location.href;
var url_filter_params = window_url.substr(window_url.indexOf("=") + 1)
var filter_params_array = url_filter_params.split(',');
$('button[name="filter[]"]').each(function()
{
if ($.inArray($(this).val(), filter_params_array) >= 0){
$(this).addClass('is-success');
}
});
This basically gets the URL parses it to get the params, and then shows adds the is-warning class back to the button to make it appear as selected. The filters also work.
I'm using the jquery and jquery UI plugin to drag and drop elements (folders and files) just like in a filebrowser.
I can manage to have the file go 'into' the folder, but not a folder to go into another.
Here is a demo :
There seems to be something conflicting, but I don't know where to look anymore.
The javascript is like this :
$(function () {
// fancytree is part of another script
$("#tree").fancytree({
expandLazy: true,
activate: function (event, data) {
var node = data.node;
if (node.data.href) {
window.open(node.data.href, node.data.target);
}
}
});
/* DRAG AND DROP STARTS HERE */
$(".listitems").draggable();
$(".droppable").droppable({
//preventCollision: true,
drop: function (event, ui) {
var draggableId = ui.draggable.attr("id");
var droppableId = $(this).attr("id");
//alert('FILE'+draggableId+' DROPED INTO '+droppableId);
$(this).append(ui.draggable);
var itemid = ui.draggable.attr('data-itemid');
var folderid = ui.draggable.attr('data-fldmid');
if (typeof folderid == 'undefined') {
folderid = 0;
}
if (typeof itemid == 'undefined') {
itemid = 0;
}
if (typeof droppableId == 'undefined') {
droppableId = 0;
}
$.ajax({
method: "POST",
url: "_ajax/filemanager/dragdrop.php",
//data : 'FileID='+ itemid +'&FolderID='+ droppableId,
data: 'FileID=' + itemid + '&FolderID=' + folderid + '&DropID=' + droppableId,
}).done(function (data) {
var result = $.parseJSON(data);
if (folderid == 0) {
//alert('FILE MOVED - FileID='+ itemid +'&FolderID='+ folderid+'&DropID='+ droppableId);
// Done moving file, hiding it
$("div#" + itemid).hide(500);
} else {
//alert('FOLDER MOVED - FileID='+ itemid +'&FolderID='+ folderid+'&DropID='+ droppableId);
// Done moving directory, hiding it
$("div#" + folderid).hide(500);
}
//$("div#"+folderid).hide(500);
//$("div#"+droppableId).hide(500);
});
}
});
$(".listitems").sortable();
$(".listitems").disableSelection();
var shouldCancel = false;
$('.dragMe').draggable({
containment: '.moveInHere',
revert: function () {
if (shouldCancel) {
shouldCancel = false;
return true;
} else {
return false;
}
}
});
$('.butNotHere').droppable({
over: function () {
shouldCancel = true;
},
out: function () {
shouldCancel = false;
}
});
});
And here is the html
<div class="box-body">
<div class="table-responsive mailbox-messages moveInHere" style="overflow: hidden; min-height:600px;">
<p>
<!--id, data-fldmid and data-itemid were added for testing purposes -->
<div class="boxFile small droppable listitems dragMe drag" id="D.4" data-fldmid='D.4' data-itemid='4'>
<a href="?n=9">
<div class="ffolder small yellow"></div>
</a>
<div class="boxFileTitle">Folder 1 (4)</div>
</div>
<div class="boxFile small droppable listitems dragMe drag" id="D.7" data-fldmid='D.7' data-itemid='7'>
<a href="?n=7">
<div class="ffolder small yellow"></div>
</a>
<div class="boxFileTitle">Folder A (7)</div>
</div>
<p>
<div style="" class="boxFile small listitems butNotHere dragMe drag" id="26" data-itemid='26'>
<img src='image.php?id=26' class='UploadedImageThumb'>
<div class="boxFileTitle">2016-12-12 14.50.14.jpg26</div>
<div class="boxFileOption">Preview | Edit | Trash</div>
</div>
</p>
<p>
<div style="" class="boxFile small listitems butNotHere dragMe drag" id="25" data-itemid='25'>
<img src='image.php?id=25' class='UploadedImageThumb'>
<div class="boxFileTitle">test.jpg25</div>
<div class="boxFileOption">Preview | Edit | Trash</div>
</div>
</p>
</p>
</div>
</div>
The 'butNotHere' class is to prevent files to be on top of each other. All this works fine, except the folder-into-folder dragging as described above.
I found the error, the variable in JS (folderid) had a letter 'D' in front of the real id. I did this during test to check if it was a file being moved or folder. So 'F' or 'D'.
So I changed this line
data-fldmid='D.7'
To this and it worked
data-fldmid='7'
I'm pretty new at JavaScript / jQuery.
The below example does call the .each part for every waterfall-item in my list. But the $img.load is never called for some reason?
Can't really figure out what I'm doing wrong?
(function($) {
$(document).ready(function(e) {
var $waterfall = $('.waterfall');
if ($waterfall.length) {
$waterfall.waterfall({});
}
// sort the waterfall when images are loaded
var $waterfallItem = $('.waterfall-item');
$waterfallItem.each(function(j, image) {
var $img = $(image);
$img.load(function() {
$waterfall.waterfall({});
});
});
});
})(jQuery);
<ul class="waterfall">
<li class="waterfall-item">
<a href="hidden link" title="hidden title">
<img alt="hidden alt" title="hidden title" data-srcset="hidden in this example" data-src="also hidden in this example" src="still hidden in this example" data-sizes="(min-width:440px) 300px, 95vw" class=" lazyloaded" sizes="(min-width:440px) 300px, 95vw"
srcset="think I'll hide this one too">
<span class="waterfallImgOverlay"></span>
</a>
</li>
</ul>
Solved it like this:
var $waterfall = $('.waterfall');
if ($waterfall.length) {
$waterfall.waterfall({});
}
// sort the waterfall when images are loaded
var $waterfall_images = $waterfall.find('img');
$waterfall_images.each(function(j, image) {
var $img = $(image);
$img.load(function() {
$waterfall.waterfall({});
});
});
I've been wracking my brain on this but I just can't seem to get it to happen.
So I have a asp.net application that when clicking a button, instantiates a dialog box with ckeditor, and then it takes the data that's inside ckeditor's textarea and posts it to a discussion area on that same page, This all works, however the issue is that I want to remove the dialog box completely and just have ckeditor open on page load somewhere without waiting for the "click".
PLEASE someone help me understand a solution.
Here's the code:
function DiscussionViewModel() {
var self = this;
self.New = ko.mapping.fromJS(newDiscussion);
self.Threads = ko.mapping.fromJS(threads, mapping);
self.AddNewThread = function () {
$("#dvAddDiscussion").dialog('open');
ko.mapping.fromJS(newDiscussion, self.New);
if (CKEDITOR.instances["txtDiscussioinDescription"] != undefined) {
CKEDITOR.instances["txtDiscussioinDescription"].setData('');
}
};
This then links with the dialog box.
$(function () {
$("#accordion").accordion();
var dialog = $("#dvAddDiscussion").dialog({
autoOpen: true,
width: 720,
height: 500,
title: 'Discussion',
modal: true,
open: function () {
if (typeof DISABLE_FOR_DIALOG != 'undefined')
DISABLE_FOR_DIALOG = true;
CKEDITOR.replace('txtDiscussioinDescription');
},
close: function (parameters) {
if (typeof DISABLE_FOR_DIALOG != 'undefined')
DISABLE_FOR_DIALOG = false;
if (CKEDITOR.instances["txtDiscussioinDescription"] != undefined) {
CKEDITOR.instances.txtDiscussioinDescription.updateElement();
CKEDITOR.instances.txtDiscussioinDescription.destroy();
}
}
});
dialog.parent().appendTo($("#dvDialogs"));
$("#frmAddDiscussion").data("validator").settings.submitHandler = discussionViewmodel.SubmitReply;
$("#frmAddDiscussion").bind('click', function () {
CKEDITOR.instances.txtDiscussioinDescription.updateElement();
});
});
UPDATE: Adding in the HTML as requested by J.
#using System.Web.Script.Serialization
#model List
#{
ViewBag.Title = "Threads";
Layout = null;// "~/views/shared/_Layout.cshtml";
}
<div class="threads" id="dvThreads">
<div class="thread">
<a href="javascript:void(0)" data-bind="click: $parent.GetReplies.bind($data)">
</a>
</div>
<script type="text/html" id="tmplReply">
<div class="detail">
<div class="miniDesc">
<span>by </span>
<span data-bind="text: User"></span>
<abbr class="timeago" data-bind="text: CreatedDate,attr:{title:CreatedDate}"></abbr>
Edit
</div>
<p data-bind="html: Description"> </p>
<br class="clear" />
</div>
</script>
<div id="dvDialogs">
#Html.Partial("Add", Model[Model.Count - 1].New)
</div>
</div>
<script type="text/javascript">
var newDiscussion=#Html.Raw(new JavaScriptSerializer().Serialize(Model[Model.Count - 1].New));
var type=#Html.Raw(new JavaScriptSerializer().Serialize(Model[Model.Count - 1].New.Type));
var objectId=#Html.Raw(new JavaScriptSerializer().Serialize(Model[Model.Count - 1].New.TypeId));
var threads=#Html.Raw(new JavaScriptSerializer().Serialize(Model));
var addDiscussionUrl = '#Url.Action("Add","Discussion")';
var threadsUrl ='#Url.Action("ThreadsJson","Discussion")';
var summariesUrl='#Url.Action("Summaries","Discussion")';
</script>