right elFinder and CKeditor integration to upload files directly - javascript

I uses elFinder laravel package file Manager with ckeditor. I follow all Instructions step and all things work except one.
When I click on image button in ckEditor to select (or upload) an Image , on the upload tab after select an image from my computer and click Send it to the Server button NotFoundHttpException in RouteCollection.php line 161 shown and upload fails.
this is ckEditor initialization code :
<textarea name="content_fa" id="fa_post_content" class="form-control"
rows="10"></textarea>
<script>
var fa_post_content = CKEDITOR.replace('fa_post_content', {
toolbar: 'admin_mode',
filebrowserBrowseUrl : '{{route('elfinder.ckeditor')}}',
filebrowserUploadUrl : '/elfinder/connector.php?cmd=upload'
});
</script>
According to This Issue , I add filebrowserUploadUrl option as you see above. but this not work too.
How can I solve this ?

This code (+ DnD upload) using demo site is here.
CKEDITOR.on('dialogDefinition', function (event) {
var editor = event.editor,
dialogDefinition = event.data.definition,
tabCount = dialogDefinition.contents.length,
uploadButton, submitButton, inputId,
elfUrl = editor.config.filebrowserUploadUrl,
// elFinder configs
elfDirHashMap = { // Dialog name / elFinder holder hash Map
image : '',
flash : '',
files : '',
link : '',
fb : 'l1_Lw' // fallback target
},
customData = {}; // any custom data to post
for (var i = 0; i < tabCount; i++) {
uploadButton = dialogDefinition.contents[i].get('upload');
submitButton = dialogDefinition.contents[i].get('uploadButton');
if (uploadButton !== null && submitButton !== null) {
uploadButton.hidden = false;
submitButton.hidden = false;
uploadButton.onChange = function() {
inputId = this.domId;
}
submitButton.onClick = function(e) {
dialogName = CKEDITOR.dialog.getCurrent()._.name;
var target = elfDirHashMap[dialogName]? elfDirHashMap[dialogName] : elfDirHashMap['fb'],
name = $('#'+inputId),
input = name.find('iframe').contents().find('form').find('input:file'),
error = function(err) {
alert(err.replace('<br>', '\n'));
};
if (input.val()) {
var fd = new FormData();
fd.append('cmd', 'upload');
fd.append('overwrite', 0); // disable upload overwrite to make to increment file name
fd.append('target', target);
$.each(customData, function(key, val) {
fd.append(key, val);
});
fd.append('upload[]', input[0].files[0]);
$.ajax({
url: elfUrl,
type: 'POST',
data: fd,
processData: false,
contentType: false,
dataType: 'json'
})
.done(function( data ) {
if (data.added && data.added[0]) {
var url = data.added[0].url;
var dialog = CKEDITOR.dialog.getCurrent();
if (dialogName == 'image') {
var urlObj = 'txtUrl'
} else if (dialogName == 'flash') {
var urlObj = 'src'
} else if (dialogName == 'files' || dialogName == 'link') {
var urlObj = 'url'
} else {
return;
}
dialog.selectPage('info');
dialog.setValueOf(dialog._.currentTabId, urlObj, url);
} else {
error(data.error || data.warning || 'errUploadFile');
}
})
.fail(function() {
error('errUploadFile');
})
.always(function() {
input.val('');
});
}
return false;
}
}
}
});

For anyone running into this issue now, the thing that resolved it for me was setting filebrowserBrowseUrl. The mistake I was making was setting filebrowserUploadUrl instead of the filebrowserBrowseUrl. Elfinder handles the upload inside itself, so you should not have to use the 'send to the server' button at all, just the browse server button.
So the ckeditor code looked like such
CKEDITOR.replace('your-id-here', {
filebrowserBrowseUrl: '/elfinder/ckeditor',
}
);
noting to replace your-id-here with your own id.

Related

Quill: Loading data from database shows 'True' instead of stored value

I'm using Quill as an editor. One of the functions I made adds timestamps to the text. The blot works fine and timestamps are added as expected. When the data is loaded back into the Quill editor from the database, though, instead of the timestamp value, Quill marks it as 'True' instead. The timestamp data is saved in the database properly. I'm having an issue figuring out how to make Quill load that data properly.
This is what the timestamp looks like in the editor:
enter image description here
This is what it looks like when inspected:
enter image description here
Here's what it looks like after loading (editor view and code in inspector):
enter image description here
enter image description here
Here's the code I have for my blot currently:
var Embed = Quill.import('blots/embed');
class QuillHashtag extends Embed {
static create(value) {
let node = super.create(value);
node.innerHTML = `${value}`;
node.setAttribute("data", value);
return node;
}
static formats(node) {
// We will only be called with a node already
// determined to be a Link blot, so we do
// not need to check ourselves
return node.getAttribute('data');
}
}
QuillHashtag.blotName = 'timeStamp';
QuillHashtag.className = 'quill-hashtag';
QuillHashtag.tagName = 'timeStamp';
Quill.register({
'formats/timeStamp': QuillHashtag
});
Here's my code for saving the editor:
function saveTrascription() {
var file_data = document.getElementById("transcriptEditorBox").innerHTML;
var jobID = document.getElementById("jobSelect").value;
var set = "set";
$.ajax({
type: "POST",
url: "/transcribe/worker.php",
data: {
transcriptionText: file_data,
saveTranscription: set,
jobID: jobID
},
success: function (response) {
toastr.success(response);
}
});
}
Here's my code for loading the data:
function getTranscriptionJob() {
var jobID = document.getElementById("jobSelect").value;
var audioPlayer = document.getElementById("audioPlayerDiv");
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var returnedData = JSON.parse(this.responseText);
if (
returnedData.transcriptionText ==
"Transcription job not finshed. Try again shortly."
) {
toastr.warning("Transcription job not finshed. Try again shortly.");
return true;
} else {
document.getElementById("jobSelectRow").style.display = "none";
document.getElementById("editorRow").style.display = "block";
var delta = quill.clipboard.convert(returnedData.transcriptionText);
quill.setContents(delta, 'silent');
//quill.clipboard.dangerouslyPasteHTML(0, returnedData.transcriptionText);
audioPlayer.innerHTML =
'<audio onloadeddata="initProgressBar()" onplay="showPauseButton()" onpause="showPlayButton()" ontimeupdate="updateProgressBar()" controls id="audioPlayer" ><source src="' +
returnedData.audioFile +
'" type="audio/mpeg" >Your browser does not support the audio element.</audio>';
toastr.info("Press Alt+P to play/pause the audio file.");
return true;
}
}
};
var url = "/transcribe/worker.php?getTranscriptionJob=set&jobID=" + jobID;
xhttp.open("GET", url, true);
xhttp.send();
}
Any help with this is really appreciated! I'm very lost on what is going wrong. I think it has something to do with that formats snippet in the blot code, but not entirely sure.

How to make progress bar on Ajax Upload

Hi I am using Ajax Upload JS 3.5 is there a way to make a progress upon uploading of image / File ?. All I see in my net is by using the <input type="file"> button and my project is not a bootstrap.
Here is my currently code
jQuery(document).ready(function () {
var extension = "";
var btnUploadDrvr = $("#btnFitaDocBrowse");
var hidFilenameDrvr = $("#imgFitaDoc");
var hidDoccFrame = $("#frmFitaDoc");
InitAjaxUpload(btnUploadDrvr, hidFilenameDrvr, hidDoccFrame );
function InitAjaxUpload(btnUpload, imgHolder, hidDoccFrame) {
new AjaxUpload(btnUpload, {
action: '../UploadDownload/UploadLocalPic',
data: '',
name: 'uploadfile',
onSubmit: function (file, ext) {
extension = ext[0];
if (!(ext && /^(jpg|png|jpeg|gif|pdf|PDF)$/.test(ext))) {
alert("File format is not supported.");
return false;
}
},
onComplete: function (file, response) {
//Add uploaded file to list
if (response !== "failed") {
$("#frmFitaDoc").attr('src', 'data:application/pdf;base64,' + response);
}
}
});
}
});
And I saw this can this be possible to embed in my code?.

PHP AJAX upload is not working correctly with php://input

I am trying to use the JavaScript/jQuery Ajax File Uploader by Jordan Feldstein available at https://github.com/jfeldstein/jQuery.AjaxFileUpload.js
It is an older library but still very popular due to it's simplicity and for being so lightweight (around 100 lines) and you can attach it to a single form input filed and it simply works! You select a file as normal with the form inut filed and on selection it instantly uploads using AJAX and returns the uploaded file URL.
This makes the library good for my use where I am uploading a file inside a modal window which is also generate with AJAX and I have used this library in many similar projects.
My backend is using PHP and Laravel and that is where my issue seems to be.
My test script works but when I implement it into my Laravel app it returns this error....
ERROR: Failed to write data to 1439150550.jpg, check permissions
This error is set in my controller below when this code is not retuning a value...
$result = file_put_contents( $folder . '/' .$filename, file_get_contents('php://input') );
So perhaps this part file_get_contents('php://input') does not contain my file data?
It does create the proper directory structure and even a file which is /uploads/backing/2015/08/1439150550.jpg
The 1439150550.jpg is a timestamp of when the upload took place. It create this file in the proper location however the file created has no content and is 0 bytes!
Below is my Laravel Controller action which handles the back-end upload and below that the JavaScript....
PHP Laravel Controller Method:
public function uploadBackingStageOneFile(){
// Only accept files with these extensions
$whitelist = array('ai', 'psd', 'svg', 'jpg', 'jpeg', 'png', 'gif');
$name = null;
$error = 'No file uploaded.';
$destination = '';
//DIRECTORY_SEPARATOR
$utc_str = gmdate("M d Y H:i:s", time());
$utc = strtotime($utc_str);
$filename = $utc . '.jpg';
$folder = 'uploads/backing/'.date('Y') .'/'.date('m');
//if Directory does not exist, create it
if(! File::isDirectory($folder)){
File::makeDirectory($folder, 0777, true);
}
// Save Image to folder
$result = file_put_contents( $folder . '/' .$filename, file_get_contents('php://input') );
if (!$result) {
Log::info("ERROR: Failed to write data to $filename, check permissions");
return "ERROR: Failed to write data to $filename, check permissions\n";
}
$url = $folder . '/' . $filename;
return Response::json(array(
'name' => $name,
'error' => $error,
'destination' => $url
));
}
JavaScript AJAX FIle Upload LIbrary
/*
// jQuery Ajax File Uploader
//
// #author: Jordan Feldstein <jfeldstein.com>
// https://github.com/jfeldstein/jQuery.AjaxFileUpload.js
// - Ajaxifies an individual <input type="file">
// - Files are sandboxed. Doesn't matter how many, or where they are, on the page.
// - Allows for extra parameters to be included with the file
// - onStart callback can cancel the upload by returning false
Demo HTML upload input
<input id="new-backing-stage-1-file" type="file">
Demo JavaScript to setup/init this lbrary on the upload field
$('#new-backing-stage-1-file').ajaxfileupload({
'action': '/upload.php',
'params': {
'extra': 'info'
},
'onComplete': function(response) {
console.log('custom handler for file:');
alert(JSON.stringify(response));
},
'onStart': function() {
if(weWantedTo) return false; // cancels upload
},
'onCancel': function() {
console.log('no file selected');
}
});
*/
(function($) {
$.fn.ajaxfileupload = function(options) {
var settings = {
params: {},
action: '',
onStart: function() { },
onComplete: function(response) { },
onCancel: function() { },
validate_extensions : true,
valid_extensions : ['gif','png','jpg','jpeg'],
submit_button : null
};
var uploading_file = false;
if ( options ) {
$.extend( settings, options );
}
// 'this' is a jQuery collection of one or more (hopefully)
// file elements, but doesn't check for this yet
return this.each(function() {
var $element = $(this);
// Skip elements that are already setup. May replace this
// with uninit() later, to allow updating that settings
if($element.data('ajaxUploader-setup') === true) return;
$element.change(function()
{
// since a new image was selected, reset the marker
uploading_file = false;
// only update the file from here if we haven't assigned a submit button
if (settings.submit_button == null)
{
upload_file();
}
});
if (settings.submit_button == null)
{
// do nothing
} else
{
settings.submit_button.click(function(e)
{
// Prevent non-AJAXy submit
e.preventDefault();
// only attempt to upload file if we're not uploading
if (!uploading_file)
{
upload_file();
}
});
}
var upload_file = function()
{
if($element.val() == '') return settings.onCancel.apply($element, [settings.params]);
// make sure extension is valid
var ext = $element.val().split('.').pop().toLowerCase();
if(true === settings.validate_extensions && $.inArray(ext, settings.valid_extensions) == -1)
{
// Pass back to the user
settings.onComplete.apply($element, [{status: false, message: 'The select file type is invalid. File must be ' + settings.valid_extensions.join(', ') + '.'}, settings.params]);
} else
{
uploading_file = true;
// Creates the form, extra inputs and iframe used to
// submit / upload the file
wrapElement($element);
// Call user-supplied (or default) onStart(), setting
// it's this context to the file DOM element
var ret = settings.onStart.apply($element, [settings.params]);
// let onStart have the option to cancel the upload
if(ret !== false)
{
$element.parent('form').submit(function(e) { e.stopPropagation(); }).submit();
}
}
};
// Mark this element as setup
$element.data('ajaxUploader-setup', true);
/*
// Internal handler that tries to parse the response
// and clean up after ourselves.
*/
var handleResponse = function(loadedFrame, element) {
var response, responseStr = $(loadedFrame).contents().text();
try {
//response = $.parseJSON($.trim(responseStr));
response = JSON.parse(responseStr);
} catch(e) {
response = responseStr;
}
// Tear-down the wrapper form
element.siblings().remove();
element.unwrap();
uploading_file = false;
// Pass back to the user
settings.onComplete.apply(element, [response, settings.params]);
};
/*
// Wraps element in a <form> tag, and inserts hidden inputs for each
// key:value pair in settings.params so they can be sent along with
// the upload. Then, creates an iframe that the whole thing is
// uploaded through.
*/
var wrapElement = function(element) {
// Create an iframe to submit through, using a semi-unique ID
var frame_id = 'ajaxUploader-iframe-' + Math.round(new Date().getTime() / 1000)
$('body').after('<iframe width="0" height="0" style="display:none;" name="'+frame_id+'" id="'+frame_id+'"/>');
$('#'+frame_id).get(0).onload = function() {
handleResponse(this, element);
};
// Wrap it in a form
element.wrap(function() {
return '<form action="' + settings.action + '" method="POST" enctype="multipart/form-data" target="'+frame_id+'" />'
})
// Insert <input type='hidden'>'s for each param
.before(function() {
var key, html = '';
for(key in settings.params) {
var paramVal = settings.params[key];
if (typeof paramVal === 'function') {
paramVal = paramVal();
}
html += '<input type="hidden" name="' + key + '" value="' + paramVal + '" />';
}
return html;
});
}
});
}
})( jQuery );
My JavaScript usage of the above library:
// When Modal is shown, init the AJAX uploader library
$("#orderModal").on('shown.bs.modal', function () {
// upload new backing file
$('#new-backing-stage-1-file').ajaxfileupload({
action: 'http://timeclock.hgjghjg.com/orders/orderboards/order/uploadbackingimage',
params: {
extra: 'info'
},
onComplete: function(response) {
console.log('custom handler for file:');
console.log('got response: ');
console.log(response);
console.log(this);
//alert(JSON.stringify(response));
},
onStart: function() {
//if(weWantedTo) return false; // cancels upload
console.log('starting upload');
console.log(this);
},
onCancel: function() {
console.log('no file selected');
console.log('cancelling: ');
console.log(this);
}
});
});
The problem is like you said, file_get_contents('php://input') does not contain your file data.
jQuery.AjaxFileUpload plugin wrap file input element with a form element that contains enctype="multipart/form-data" attribute. 1
From php documentation: 2
php://input is not available with enctype="multipart/form-data".

Add to cart button - Javascript/JQuery error

When webpage loads:
Invalid App Id: Must be a number or numeric string representing the application id.
When Add to Cart button is clicked:
Uncaught TypeError: Cannot read property 'id' of undefined - (index):459
Below is the Javascript, I have marked the area with "ERROR LINE" at (index):459
var productAddToCartForm = new VarienForm('product_addtocart_form');
productAddToCartForm.submit = function(button, url) {
if (this.validator.validate()) {
var form = this.form;
var oldUrl = form.action;
if (url) {
form.action = url;
}
var e = null;
if ($(button).id.indexOf('ec_shortcut') != -1) { // -ERROR LINE
try {
this.form.submit();
return;
} catch (e) {}
}
if (!url) {
url = jQuery('#product_addtocart_form').attr('action');
}
url = url.replace("checkout/cart", "oxajax/cart");
url = url.replace("wishlist/index/cart", "oxajax/cart/add");
var data = jQuery('#product_addtocart_form').serialize();
data += '&isAjax=1';
if ('https:' == document.location.protocol) {
url = url.replace('http:', 'https:');
}
jQuery.fancybox.showActivity();
jQuery.ajax({
url: url,
dataType: 'jsonp',
type: 'post',
data: data,
success: function(data) {
Olegnax.Ajaxcart.helpers.showMessage(data.message);
Olegnax.Ajaxcart.helpers.cartSuccessFunc(data);
}
});
this.form.action = oldUrl;
if (e) {
throw e;
}
}
}.bind(productAddToCartForm);
$(button).id - Error Cause
$(button) is a jQuery object, use $(button)[0].id or $(button).prop('id') or just button.id
Assuming button is a DOMElement you can use:
if (button.id.indexOf('ec_shortcut') != -1) {
Alternatively, you can get the id property from the jQuery object using prop():
if ($(button).prop('id').indexOf('ec_shortcut') != -1) {
Try this: button.id.indexOf('ec_shortcut')
use attr to get the id value
$(button).attr('id');
NOTE: You can get any attribute value using this method
See jQuery Docs for more info

Weceem plugin unable to edit content

recently I have been trying to install weceem 1.2-M1 plugin on grails but it just refuses to let me edit content. Whenever I try to edit content, a chunk of JS is served as text in the header of the page(sorry cant post pictures yet).
<script language="javascript" type="text/javascript"> function styleButtons() { $('button.removeTag').button({ icons: { primary: 'ui-icon-closethick' }, text: false }); } $(function() { styleButtons(); $('button.addTag').button(); /*{icons: { primary: 'ui-icon-plus' }});*/ $('#tagsfield_tags .addTag').click( function(event) { event.preventDefault(); var dataElem = $("input[name='tags']"); var existingTags = dataElem.val().split(','); var displayTagsParent = $("#tagsfield_tags .existingTagList"); var newTagsElem = $("input[name='newTags_tags']"); var newTags = newTagsElem.val().split(','); var exists = false; $.each(newTags, function(index, t) { t = $.trim(t).toLowerCase(); var exists = false for (i = 0; i < existingTags.length; i++) { if (existingTags[i] == t) { exists = true; break; } } if (!exists) { existingTags[existingTags.length] = t; $('<div class="existingTag"><span class="tagtext">'+t+'</span><button class="removeTag">Remove</button></div>').appendTo(displayTagsParent); styleButtons(); } }) dataElem.val(existingTags.join(',')); newTagsElem.val(''); }); $('#tagsfield_tags .removeTag').live('click', function(event) { event.preventDefault(); var tagParentDiv = $(event.target).parentsUntil('.existingTagList'); var tagToRemove = $('.tagtext', tagParentDiv).text(); $(tagParentDiv).fadeOut(500, function() { $(this).remove(); }); var dataElem = $("input[name='tags']"); var currentTags = dataElem.val().split(','); var newVal = ''; $.each(currentTags, function(index, t) { t = $.trim(t).toLowerCase(); if (t != tagToRemove) { newVal += t + ',' } }); dataElem.val(newVal); }); }); </script>
I have already included the 2 lines below into the Config file.
grails.resources.adhoc.excludes = ['/plugins/weceem-1.2-M1/*']
grails.mime.disable.accept.header.userAgents = ['Gecko', 'WebKit', 'Presto', 'Trident']
grails.mime.file.extensions = false
grails.mime.types = [ // the first one is the default format
all: '*/*', // 'all' maps to '*' or the first available format in withFormat
atom: 'application/atom+xml',
css: 'text/css',
csv: 'text/csv',
form: 'application/x-www-form-urlencoded',
html: ['text/html','application/xhtml+xml'],
js: 'text/javascript',
json: ['application/json', 'text/json'],
multipartForm: 'multipart/form-data',
rss: 'application/rss+xml',
text: 'text/plain',
hal: ['application/hal+json','application/hal+xml'],
xml: ['text/xml', 'application/xml']
]
grails.resources.adhoc.excludes = ['/plugins/weceem-1.2-M1/*']
//grails.resources.adhoc.patterns = ['/images/*', '/css/*', '/js/*', '/plugins/*']
and this is my buildconfig file
plugins {
checksums false
build ":tomcat:7.0.50"
compile ":twitter-bootstrap:3.1.0"
compile ":scaffolding:2.0.1"
compile ':cache:1.1.1'
compile ":jquery:1.8.3"
compile ":jquery-ui:1.8.24"
compile (':weceem:1.2-M1')
compile ":hibernate:3.6.10.7"
runtime ":database-migration:1.3.8"
compile ":resources:1.2.1"
runtime ":twitter-bootstrap:3.0.3"
}
and lastly, here is my urlmapping
class UrlMappings {
static mappings = {
// "/$controller/$action?/$id?(.$format)?"{
// constraints {
// // apply constraints here
// }
// }
//"/"(view:"/index")
"500"(view:'/error')
}
}
Con somebody help me figure out what's wrong or point me to the right direction? thank you so much!
What about your security settings for plugin? Maybe you don't have rights to edit content? You can check demo application with weceem plugin, see http://www.weceem.org/weceem/ or https://github.com/jCatalog/weceem-app for example of configuration.

Categories