I have an existing web service that handles user input of a photo (as well as some other number and text data). The photo is captured via the input tag:
<input type="file" id="image-input-solo" accept="image/*" capture="capture" />
In the javascript I grab the image via the Files API like so:
$('#image-input-solo').on('change', function() {
window.__file = this.files[0];
});
// which gives me a File Object like this:
File {
lastModified: 1507749812264
lastModifiedDate: Wed Oct 11 2017 12:23:32 GMT-0700 (PDT) {}
name: "image000987u.jpg"
size: 441738
type: "image/jpeg"
webkitRelativePath: ""
__proto__: File
}
So in my native app context (using Cordova and the Camera Plugin) I am successfully grabbing the photo file:
//HTML
<div id="button-drink-it-now" ng-click="nativeCamera();">
// JAVASCRIPT
$scope.nativeCamera = function() {
if (!navigator.camera) {
alert("Camera API not supported", "Error");
return;
}
var options = { quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: 1, // 0:Photo Library, 1=Camera, 2=Saved Album
encodingType: 0 // 0=JPG 1=PNG
};
navigator.camera.getPicture(
function(imgData) {
var fd = new FormData();
var reader;
var imgBlob;
window.resolveLocalFileSystemURL(imgData, function(fileEntry) {
fileEntry.file(function(file) {
reader = new FileReader();
reader.onloadend = function(e) {
imgBlob = new Blob([ this.result ], { type: "image/jpeg" } );
fd.append('attachment', imgBlob);
window.__file = imgBlob; // MY ATTEMPT TO GET THE IMAGE IN THE CORRECT WAY
};
reader.readAsArrayBuffer(file);
}, function(e){
console.log('error with photo file');
});
}, function(e){
console.log('error with photo file');
});
},
function() {
alert('Error taking picture', 'Error');
},
options);
};
// THE OBJECT I GET FORM THE imgBlob:
Blob {
size: 6268043
type: "image/jpeg"
}
My question is, how can I get the photo file from the native camera and format it into the same File Object as I get from the HTML input, this.files[0] so I can continue using my existing web service to store the photo?
Turns out it was a simple fix:
navigator.camera.getPicture(
function(imgData) {
var fd = new FormData();
var reader;
var imgBlob;
window.resolveLocalFileSystemURL(imgData, function(fileEntry) {
fileEntry.file(function(file) {
reader = new FileReader();
reader.onloadend = function(e) {
imgBlob = new Blob([ this.result ], { type: "image/jpeg" } );
window.__file = imgBlob; // PLACE THE FILE ASSIGNMENT HERE AFTER THE READER HAS INGESTED THE FILE BYTES
};
reader.readAsArrayBuffer(file);
// window.__file = imgBlob; // FILE ASSIGNMENT USED TO BE HERE
}, function(e){
console.log('error with photo file');
});
}, function(e){
console.log('error with photo file');
});
},
function() {
alert('Error taking picture', 'Error');
},
options);
};
I would like to do tab capture by postmessage in chrome.
Below is the code that I have created.
The message will be sent by the content script.
Once the message is received, it will try to capture the current tab.
chrome.runtime.onConnect.addListener(function(port){
port.onMessage.addListener(function(message,sender){
chrome.tabs.query({"active": true, "currentWindow": true}, function(tab) {
chrome.tabCapture.capture(captureOptions,
function(stream) {
mediaRecorder = new MediaRecorder(stream, options);
if (stream && message.status == 'started') {
var options = {mimeType: "video/webm"};
mediaRecorder.start();
mediaRecorder.ondataavailable = function(event) {
if (event.data.size > 0) {
recordedChunks.push(event.data);
var blob = new Blob(recordedChunks, {
type: 'video/mp4'
});
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
document.body.appendChild(a);
a.style = 'display: none';
a.href = url;
a.download = 'test.webm';
a.click();
window.URL.revokeObjectURL(url);
stream.getVideoTracks()[0].stop();
}
}
}else if(message.status = "stopped"){
mediaRecorder.stop();
}
}
);
});
});
});
With the code above I am getting the Error
Unchecked runtime.lastError while running tabCapture.capture: Extension has not been invoked for the current page (see activeTab permission). Chrome pages cannot be captured.
at Object.callback (chrome-extension://haogilhkbanjpnkjbdgnefdgllfhldci/background.js:32:31)
Is there a way to bypass this?
I have this Select2 working with its supplied example when loading
Github users data: https://api.github.com/search/repositories
but NOT working anymore when replace the AJAX url call to
Google Address Autocomplete:
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Vict&types=geocode&language=fr&key=*************************
my codes:
<select class="js-data-example-ajax">
<option value="3620194" selected="selected">select2/select2</option>
</select>
<script>
function formatRepo (repo) {
if (repo.loading) return repo.text;
var markup = '<div class="clearfix">' +
'<div class="col-sm-1">' +
'<img src="' + repo.owner.avatar_url + '" style="max-width: 100%" />' +
'</div>' +
'<div clas="col-sm-10">' +
'<div class="clearfix">' +
'<div class="col-sm-6">' + repo.full_name + '</div>' +
'<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + repo.forks_count + '</div>' +
'<div class="col-sm-2"><i class="fa fa-star"></i> ' + repo.stargazers_count + '</div>' +
'</div>';
if (repo.description) {
markup += '<div>' + repo.description + '</div>';
}
markup += '</div></div>';
return markup;
}
function formatRepoSelection (repo) {
//return repo.description || repo.text;
return repo.full_name || repo.text;
}
$(document).ready(function(){
$(".js-data-example-ajax").select2({
ajax: {
url: "https://api.github.com/search/repositories",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, page) {
// parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to
// alter the remote JSON data
return {
results: data.items
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
});
</script>
the error showing is :
XMLHttpRequest cannot load https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Vict&types=geocode&language=fr&key=**************************&q=v. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access.
Can someone who has integrated Google Map Api and Select2 help? I am not too sure where to troubleshoot from here now...
***I am building my app in Laravel 5
***I already tried installing barryvdh/laravel-cors, but same problem!!
Try to add $.ajaxSetup with csrf token:
before ajax call:
$.ajaxSetup({
headers: {'X-CSRF-Token': $('meta[name=_token]').attr('content')}
});
and in your head meta:
<meta name="_token" content="{{ csrf_token() }}"/>
Your problem come from a security control on the HTTP protocol called 'CORS' who prevent you from making a ajax call to another domain than the one your currently on.
To fix CORS issue you must implement a specific HEADER on the server. Since Google are not owned by you it a impossibility.
So to fix this issue you can use Google Api Service and make the API do the ajax call for you. Thats mean in Select2 you will need to use not ajax{url} but ajax{transport}.
Im not sure of that part but i suppose that the Google API will create himself a frame to is service site and from that same frame do all ajax request so CORS will not be a problem.
this is a working example:
https://jsfiddle.net/sebastienhawkins/b1ws2h07/
$(document).ready(function(){
$('.placecomplete').placecomplete({
placeServiceResult:function(data,status){
console.log(data);
$('#show_something').html(data.adr_address);
},
language:'fr'
});
});
//jquery.placecomplete.js file content
//! jquery.placecomplete.js
//! version : 0.0.1
//! authors : Sébastien Hawkins
//! license : Apache
(function($){
if(typeof $.fn.select2 == 'undefined'){
console.log("ERROR: Placecomplete need Select2 plugin.")
}
//Google services
var ac = null; //Autocomplete
var ps = null; //Place
//Google config
// https://developers.google.com/maps/documentation/javascript/reference#AutocompletionRequest
var googleAutocompleteOptions = {
types: ["geocode"]
};
//Google init
window.initGoogleMapsAPI = function(){
ac = new google.maps.places.AutocompleteService();
ps = new google.maps.places.PlacesService($('<div/>')[0]); //Google need a mandatory element to pass html result , we do not need this.
}
//Google Loading
if (window.google && google.maps && google.maps.places) {
window.initGoogleMapsAPI();
} else {
$.ajax({
url: "https://maps.googleapis.com/maps/api/js?libraries=places&sensor=false&callback=initGoogleMapsAPI",
dataType: "script",
cache: true
});
}
//Google placeservice result map
var placeServiceResult = function(data,status){
var CIVIC = 0, STREET = 1, CITY = 2, SECTEUR = 3, STATE = 4, COUNTRY = 5, ZIPCODE = 6;
//todo If the result does not have 7 element data map is not the same
//maybe we will need that html element google put mandatory
var adrc = data.address_components;
if(adrc.length != 7) return;
$('.address input.address').val(adrc[CIVIC].long_name +' '+ adrc[STREET].long_name);
$('.address input.city').val(adrc[CITY].long_name);
$('.address input.state').val(adrc[STATE].long_name);
$('.address input.country').val(adrc[COUNTRY].long_name);
$('.address input.zipcode').val(adrc[ZIPCODE].long_name);
}
//Select2 default options
var select2DefaultOptions = {
closeOnSelect: true,
debug: false,
dropdownAutoWidth: false,
//escapeMarkup: Utils.escapeMarkup,
language: 'en',
minimumInputLength: 2,
maximumInputLength: 0,
maximumSelectionLength: 0,
minimumResultsForSearch: 0,
selectOnClose: false,
theme: 'default',
width: 'resolve',
placeholder: {
id: '-1', // the value of the option
text: 'Search for address'
},
ajax:{
delay:100
}
};
//jQuery Plugin
var pluginDefault = {
placeServiceResult:placeServiceResult
}
$.fn.placecomplete = function (options) {
this.each(function () {
//Variable by instance
var $s2 = $(this);
//Init select2 for $this
$s2.select2($.extend(true,{
ajax: {
transport: function (params, success, failure) {
// is caching enabled?
//TODO(sébastien) ajouter le cache pour google autocomplete
if ($s2.data('ajax--cache')) {
}
else {
ac.getPlacePredictions($.extend(googleAutocompleteOptions,params.data),success);
}
},
data: function (params) {
return {input: params.term };
},
processResults: function (data, status) {
var response = {results:[]}
$.each(data,function(index,item){
item.text = item.description;
response.results.push(item)
});
return response;
}
}
}, select2DefaultOptions, options || {} ));
options = $.extend(true,pluginDefault,options);
$s2.on('select2:select', function (evt) {
ps.getDetails({ placeId: evt.params.data.place_id}, options.placeServiceResult);
});
});
return this;
};
})(jQuery);
I have to upload a file from the local memory of application (HTML5 File api). Onselect, the user should be able to upload directly without any question. The idea is to manage download/upload seamless to the user. Here is the code :
$("body").on("click", ".upload-file", function(e){
var fileToUpload = $('input:radio[name=optionsRadios]:checked').val();
var formData = new FormData();
$('input:radio[name=optionsRadios]:checked').parent().parent().parent().remove();
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.TEMPORARY, 50*1024*1024, initFS, errorHandler);
var reader = new FileReader();
function initFS(fs){
fs.root.getDirectory('/', {}, function(dirEntry){
var dirReader = dirEntry.createReader();
dirReader.readEntries(function(entries) {
for(var key = 0; key < entries.length; key++) {
var entry = entries[key];
if (entry.isFile){
var name = entry.name;
if(name == fileToUpload){
getAsText(entry.toURL());
formData.append('file', entry.toURL);
break;
}
}
}
}, errorHandler);
}, errorHandler);
}
function errorHandler(){
console.log('An error occured');
}
function getAsText(readFile) {
alert ("getting as text :" +readFile);
var reader = new FileReader();
// Read file into memory as UTF-16
reader.readAsText(readFile, "UTF-16");
// Handle progress, success, and errors
reader.onprogress = updateProgress;
reader.onload = loaded;
reader.onerror = errorHandler;
}
function loaded(evt) {
// Obtain the read file data
alert("loaded file");
var fileString = evt.target.result;
// Handle UTF-16 file dump
if(utils.regexp.isChinese(fileString)) {
//Chinese Characters + Name validation
}
else {
// run other charset test
}
// xhr.send(fileString)
}
var serverurl = "/fileserver/uploadFile?selpath="+fileToUpload;
var xhr = new XMLHttpRequest();
xhr.open('POST', serverurl);
xhr.onload = function () {
if (xhr.status === 200) {
console.log('all done: ' + xhr.status);
} else {
console.log('Something went terribly wrong...');
}
};
xhr.send(formData);
});
Now, I am trying to read the file as text (its a bad practice but wanted to find someway to make it work) but it doesn't throw any events. Can you please help me to find where I am going wrong ?
tinyMCE has an insert image button, but how to handle its functionality
pls give some code
I have upvoted the code written by #pavanastechie, but I ended up rewriting it quite a lot. Here's a version that is far shorter, which might have value to some people
tinymce.init({
toolbar : "imageupload",
setup: function(editor) {
var inp = $('<input id="tinymce-uploader" type="file" name="pic" accept="image/*" style="display:none">');
$(editor.getElement()).parent().append(inp);
inp.on("change",function(){
var input = inp.get(0);
var file = input.files[0];
var fr = new FileReader();
fr.onload = function() {
var img = new Image();
img.src = fr.result;
editor.insertContent('<img src="'+img.src+'"/>');
inp.val('');
}
fr.readAsDataURL(file);
});
editor.addButton( 'imageupload', {
text:"IMAGE",
icon: false,
onclick: function(e) {
inp.trigger('click');
}
});
}
});
NOTE: this relies on jquery, and won't work without it. Also, it assumes that the browser supports window.FileReader, and doesn't check for it.
I used pavanastechie's and Chris Lear's solutions, which worked perfectly for me, and wanted to share a complete example built on theirs that uploads the image to the server and embeds the image using the URL provided back by the server:
tinymce.init({
toolbar: 'imageupload',
setup: function(editor) {
initImageUpload(editor);
}
});
function initImageUpload(editor) {
// create input and insert in the DOM
var inp = $('<input id="tinymce-uploader" type="file" name="pic" accept="image/*" style="display:none">');
$(editor.getElement()).parent().append(inp);
// add the image upload button to the editor toolbar
editor.addButton('imageupload', {
text: '',
icon: 'image',
onclick: function(e) { // when toolbar button is clicked, open file select modal
inp.trigger('click');
}
});
// when a file is selected, upload it to the server
inp.on("change", function(e){
uploadFile($(this), editor);
});
}
function uploadFile(inp, editor) {
var input = inp.get(0);
var data = new FormData();
data.append('image[file]', input.files[0]);
$.ajax({
url: '/admin/images',
type: 'POST',
data: data,
processData: false, // Don't process the files
contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function(data, textStatus, jqXHR) {
editor.insertContent('<img class="content-img" src="' + data.url + '"/>');
},
error: function(jqXHR, textStatus, errorThrown) {
if(jqXHR.responseText) {
errors = JSON.parse(jqXHR.responseText).errors
alert('Error uploading image: ' + errors.join(", ") + '. Make sure the file is an image and has extension jpg/jpeg/png.');
}
}
});
}
!!!!ENJOY!!! here is the solution to load directly from local computer
JSFIDDLE DEMO
<textarea name="content"></textarea>
<title>Local image loading in to tinymce</title>
<br/>
<b>Image size should be lessthan 500kb</b>
JAVA SCRIPT CODE
`
tinymce.init({
selector: "textarea",
toolbar: "mybutton",
setup: function(editor) {
editor.addButton('mybutton', {
text:"IMAGE",
icon: false,
onclick: function(e) {
console.log($(e.target));
if($(e.target).prop("tagName") == 'BUTTON'){
console.log($(e.target).parent().parent().find('input').attr('id'));
if($(e.target).parent().parent().find('input').attr('id') != 'tinymce-uploader') {
$(e.target).parent().parent().append('<input id="tinymce-uploader" type="file" name="pic" accept="image/*" style="display:none">');
}
$('#tinymce-uploader').trigger('click');
$('#tinymce-uploader').change(function(){
var input, file, fr, img;
if (typeof window.FileReader !== 'function') {
write("The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('tinymce-uploader');
if (!input) {
write("Um, couldn't find the imgfile element.");
} else if (!input.files) {
write("This browser doesn't seem to support the `files` property of file inputs.");
} else if (!input.files[0]) {
write("Please select a file before clicking 'Load'");
} else {
file = input.files[0];
fr = new FileReader();
fr.onload = createImage;
fr.readAsDataURL(file);
}
function createImage() {
img = new Image();
img.src = fr.result;
editor.insertContent('<img src="'+img.src+'"/>');
}
});
}
if($(e.target).prop("tagName") == 'DIV'){
if($(e.target).parent().find('input').attr('id') != 'tinymce-uploader') {
console.log($(e.target).parent().find('input').attr('id'));
$(e.target).parent().append('<input id="tinymce-uploader" type="file" name="pic" accept="image/*" style="display:none">');
}
$('#tinymce-uploader').trigger('click');
$('#tinymce-uploader').change(function(){
var input, file, fr, img;
if (typeof window.FileReader !== 'function') {
write("The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('tinymce-uploader');
if (!input) {
write("Um, couldn't find the imgfile element.");
} else if (!input.files) {
write("This browser doesn't seem to support the `files` property of file inputs.");
} else if (!input.files[0]) {
write("Please select a file before clicking 'Load'");
} else {
file = input.files[0];
fr = new FileReader();
fr.onload = createImage;
fr.readAsDataURL(file);
}
function createImage() {
img = new Image();
img.src = fr.result;
editor.insertContent('<img src="'+img.src+'"/>');
}
});
}
if($(e.target).prop("tagName") == 'I'){
console.log($(e.target).parent().parent().parent().find('input').attr('id')); if($(e.target).parent().parent().parent().find('input').attr('id') != 'tinymce-uploader') { $(e.target).parent().parent().parent().append('<input id="tinymce-uploader" type="file" name="pic" accept="image/*" style="display:none">');
}
$('#tinymce-uploader').trigger('click');
$('#tinymce-uploader').change(function(){
var input, file, fr, img;
if (typeof window.FileReader !== 'function') {
write("The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('tinymce-uploader');
if (!input) {
write("Um, couldn't find the imgfile element.");
} else if (!input.files) {
write("This browser doesn't seem to support the `files` property of file inputs.");
} else if (!input.files[0]) {
write("Please select a file before clicking 'Load'");
} else {
file = input.files[0];
fr = new FileReader();
fr.onload = createImage;
fr.readAsDataURL(file);
}
function createImage() {
img = new Image();
img.src = fr.result;
editor.insertContent('<img src="'+img.src+'"/>');
}
});
}
}
});
}
});
`
Din't try iManager but found tinyFCK good and easy to configure which gives CKEditor's filemanager integrated with TinyMCE
1.Download TinyFCK
2.replace filemanger folder in tinyFCK with filemanager folder of ur CKEditor
3.code :
-
tinyMCE.init({
theme : "advanced",
file_browser_callback : "fileBrowserCallBack",
});
function fileBrowserCallBack(field_name, url, type, win) {
var connector = "../../filemanager/browser.html?Connector=connectors/php/connector.php";
var enableAutoTypeSelection = true;
var cType;
tinyfck_field = field_name;
tinyfck = win;
switch (type) {
case "image":
cType = "Image";
break;
case "flash":
cType = "Flash";
break;
case "file":
cType = "File";
break;
}
if (enableAutoTypeSelection && cType) {
connector += "?Type=" + cType;
}
window.open(connector, "tinyfck", "modal,width=600,height=400");
}
I know this post is old, but maybe this will help someone trying to find a open source file manager for tinymce:
https://github.com/2b3ez/FileManager4TinyMCE
This worked great for me.
Based on #Chris Lear's answer, I have re-modified the script so that it supports multiple file uploads to server, and removed the data image for preview after content is posted and before table is updated with a little php script
tinymce.init({
selector: 'textarea',
setup: function(editor) {
var n = 0;
var form = $('#form_id'); // your form id
editor.addButton( 'imageupload', {
text:"IMAGE",
icon: false,
onclick: function(e) {
$(form).append('<input id="tinymce-uploader_'+n+'" class="tinymce-uploader" type="file" name="pic['+n+']" mutliple accept="image/*" style="display: none;">');
$('#tinymce-uploader_'+n).trigger('click');
n++;
$('.tinymce-uploader').on("change",function(){
var input = $(this).get(0);
var file = input.files[0];
var filename = file.name;
var fr = new FileReader();
fr.onload = function() {
var img = new Image();
img.src = fr.result;
editor.insertContent('<img data-name="'+filename+'" src="'+img.src+'"/>');
}
fr.readAsDataURL(file);
});
}
});
},
And on php side inside the upload php file:
function data2src($content, $img_path ='') {
preg_match('/data\-name="([^"]+)/i',$content, $data_name);
$tmp = preg_replace('/src=["]data([^"]+)["]/i', '', $content);
$content = preg_replace('/data\-name\=\"/i', 'src="'.$img_path, $tmp);
return $content;
}
I know it is an old question. However, I think this answer may help somebody who wants to upload multiple images by using tinyMCE 5.xx.
Based on #Chris Lear's and #stephen.hanson's answer, I modify some code to support multiple images uploading. Here is my code. Hope it could help somebody.
tinymce.init({
toolbar: 'imageupload',
setup: function(editor) {
initImageUpload(editor);
}
});
function initImageUpload(editor) {
// create input and insert in the DOM
var inp = $(`<input id='tinymce-uploader' type='file' name='pic' accept='image/*' style='display:none' multiple>`);
$(editor.getElement()).parent().append(inp);
// add the image upload button to the editor toolbar
editor.addButton('imageupload', {
text:'IMAGE',
onAction: function(_) {
// when toolbar button is clicked, open file select modal
inp.trigger('click');
}
});
// when a file is selected, upload it to the server
inp.on('change',function(){
for(let i=0;i<inp[0].files.length;i++){
let file = inp[0].files[i];
let data = new FormData();
data.append('multipartFile',file);
axios.post('/upload/image/url',
data,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(res => {
if (res.status = 200) {
editor.insertContent('<img class="content-img" src="' + data.url + '"/>');
// clear data to avoid uploading same data not working in the second time
inp.val('');
}
})
}
It works for image upload.Is this possible for file upload ? I want to add a custom file upload option from local into tinyMCE and want to show it by url .
Code is something like below which not working:
ed.addButton('mybutton2', {
text:"File",
icon: false,
onclick: function(e) {
console.log($(e.target));
if($(e.target).prop("tagName") == 'BUTTON'){
console.log($(e.target).parent().parent().find('input').attr('id'));
if($(e.target).parent().parent().find('input').attr('id') !=
'tinymce-uploader') {
$(e.target).parent().parent().append('<input id="tinymce-
uploader" type="file" name="pic" accept="*" height="100" weidth="100"
style="display:none">');
}
$('#tinymce-uploader').trigger('click');
$('#tinymce-uploader').change(function(){
var input, file, fr, img;
if (typeof window.FileReader !== 'function') {
write("The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('tinymce-uploader');
// var URL = document.my_form.my_field.value;
alert(input.files[0]);
if (!input) {
write("Um, couldn't find the imgfile element.");
} else if (!input.files) {
write("This browser doesn't seem to support the `files`
property of file inputs.");
} else if (!input.files[0]) {
write("Please select a file before clicking 'Load'");
alert( input.files[0]);
} else {
file = input.files[0];
fr = new FileReader();
fr.onload = createFile;
fr.readAsDataURL(file);
// alert(fr.result);
}
function createFile() {
//what should I write here?
ed.insertContent('<a href="'+img.src+'">download
file_name</a>');
}
});
}
}
});