Cropper.js aspect ratio buttons not working. Whenever I tried to upload an image and try to press the 16:9 button then my images will be invisible and not cropped and reinitiate. after that when I again select the image at that time I will see effect of my button.
https://fengyuanchen.github.io/jquery-cropper/
Cropper-init.js
$(function () {
'use strict';
var console = window.console || { log: function () {} };
var $image = $('#image');
var $download = $('#download');
var $dataX = $('#dataX');
var $dataY = $('#dataY');
var $dataHeight = $('#dataHeight');
var $dataWidth = $('#dataWidth');
var $dataRotate = $('#dataRotate');
var $dataScaleX = $('#dataScaleX');
var $dataScaleY = $('#dataScaleY');
var options = {
aspectRatio: 16 / 9,
preview: '.img-preview',
crop: function (e) {
$dataX.val(Math.round(e.x));
$dataY.val(Math.round(e.y));
$dataHeight.val(Math.round(e.height));
$dataWidth.val(Math.round(e.width));
$dataRotate.val(e.rotate);
$dataScaleX.val(e.scaleX);
$dataScaleY.val(e.scaleY);
}
};
// Tooltip
$('[data-toggle="tooltip"]').tooltip();
// Cropper
$image.on({
'build.cropper': function (e) {
// console.log(e.type);
},
'built.cropper': function (e) {
// console.log(e.type);
},
'cropstart.cropper': function (e) {
// console.log(e.type, e.action);
},
'cropmove.cropper': function (e) {
// console.log(e.type, e.action);
},
'cropend.cropper': function (e) {
// console.log(e.type, e.action);
},
'crop.cropper': function (e) {
// console.log(e.type, e.x, e.y, e.width, e.height, e.rotate, e.scaleX, e.scaleY);
$('#img_btn').prop("disabled", false);
},
'zoom.cropper': function (e) {
// console.log(e.type, e.ratio);
}
}).cropper(options);
// Buttons
if (!$.isFunction(document.createElement('canvas').getContext)) {
$('button[data-method="getCroppedCanvas"]').prop('disabled', true);
}
if (typeof document.createElement('cropper').style.transition === 'undefined') {
$('button[data-method="rotate"]').prop('disabled', true);
$('button[data-method="scale"]').prop('disabled', true);
}
// Download
// if (typeof $download[0].download === 'undefined') {
// $download.addClass('disabled');
// }
// Options
$('.docs-toggles').on('change', 'input', function () {
var $this = $(this);
var name = $this.attr('name');
var type = $this.prop('type');
var cropBoxData;
var canvasData;
if (!$image.data('cropper')) {
return;
}
if (type === 'checkbox') {
options[name] = $this.prop('checked');
cropBoxData = $image.cropper('getCropBoxData');
canvasData = $image.cropper('getCanvasData');
options.built = function () {
$image.cropper('setCropBoxData', cropBoxData);
$image.cropper('setCanvasData', canvasData);
};
} else if (type === 'radio') {
options[name] = $this.val();
}
$image.cropper('destroy').cropper(options);
});
// Methods
$('.docs-buttons').on('click', '[data-method]', function () {
var $this = $(this);
var data = $this.data();
var $target;
var result;
if ($this.prop('disabled') || $this.hasClass('disabled')) {
return;
}
if ($image.data('cropper') && data.method) {
data = $.extend({}, data); // Clone a new one
if (typeof data.target !== 'undefined') {
$target = $(data.target);
if (typeof data.option === 'undefined') {
try {
data.option = JSON.parse($target.val());
} catch (e) {
// console.log(e.message);
}
}
}
if (data.method === 'rotate') {
$image.cropper('clear');
}
result = $image.cropper(data.method, data.option, data.secondOption);
if (data.method === 'rotate') {
$image.cropper('crop');
}
switch (data.method) {
case 'scaleX':
case 'scaleY':
$(this).data('option', -data.option);
break;
case 'getCroppedCanvas':
if (result) {
// Bootstrap's Modal
$('#getCroppedCanvasModal').modal().find('.modal-body').html(result);
if (!$download.hasClass('disabled')) {
$download.attr('href', result.toDataURL('image/jpeg'));
}
}
break;
}
if ($.isPlainObject(result) && $target) {
try {
$target.val(JSON.stringify(result));
} catch (e) {
// console.log(e.message);
}
}
}
});
// Keyboard
$(document.body).on('keydown', function (e) {
if (!$image.data('cropper') || this.scrollTop > 300) {
return;
}
switch (e.which) {
case 37:
e.preventDefault();
$image.cropper('move', -1, 0);
break;
case 38:
e.preventDefault();
$image.cropper('move', 0, -1);
break;
case 39:
e.preventDefault();
$image.cropper('move', 1, 0);
break;
case 40:
e.preventDefault();
$image.cropper('move', 0, 1);
break;
}
});
// Import image
var $inputImage = $('.input-image');
var URL = window.URL || window.webkitURL;
var blobURL;
if (URL) {
$inputImage.change(function () {
var files = this.files;
var file;
if (!$image.data('cropper')) {
return;
}
if (files && files.length) {
file = files[0];
if (/^image\/\w+$/.test(file.type)) {
blobURL = URL.createObjectURL(file);
$image.one('built.cropper', function () {
// Revoke when load complete
URL.revokeObjectURL(blobURL);
}).cropper('reset').cropper('replace', blobURL);
} else {
$inputImage.val('');
$('#formUploadImage').bootstrapValidator('revalidateField', 'inputImage');
$('#image').cropper('destroy').cropper({
aspectRatio: 1 / 1,
viewMode: 1
});
window.alert('Please choose an image file.');
}
}
});
} else {
$inputImage.prop('disabled', true).parent().addClass('disabled');
}
});
HTML
<input type="file" id="inputImage" name="inputImage" accept=".jpg,.jpeg,.png" class="form-control input-image" />
<div class="docs-toggles btn-group btn-group-justified" data-toggle="buttons">
<label class="btn btn-default btn-outline active">
<input type="radio" class="sr-only" id="aspectRatio0" name="aspectRatio" value="1.7777777777777777">
<span class="docs-tooltip" data-toggle="tooltip" title="aspectRatio: 16 / 9"> 16:9 </span> </label>
<label class="btn btn-default btn-outline">
<input type="radio" class="sr-only" id="aspectRatio1" name="aspectRatio" value="1.3333333333333333">
<span class="docs-tooltip" data-toggle="tooltip" title="aspectRatio: 4 / 3"> 4:3 </span> </label>
<label class="btn btn-default btn-outline">
<input type="radio" class="sr-only" id="aspectRatio2" name="aspectRatio" value="1">
<span class="docs-tooltip" data-toggle="tooltip" title="aspectRatio: 1 / 1"> 1:1 </span> </label>
<label class="btn btn-default btn-outline">
<input type="radio" class="sr-only" id="aspectRatio3" name="aspectRatio" value="0.6666666666666666">
<span class="docs-tooltip" data-toggle="tooltip" title="aspectRatio: 2 / 3"> 2:3 </span> </label>
</div>
Related
scripts.js
/* Dore Theme Select & Initializer Script
Table of Contents
01. Css Loading Util
02. Theme Selector And Initializer
*/
/* 01. Css Loading Util */
function loadStyle(href, callback) {
for (var i = 0; i < document.styleSheets.length; i++) {
if (document.styleSheets[i].href == href) {
return;
}
}
var head = document.getElementsByTagName("head")[0];
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = href;
if (callback) {
link.onload = function() {
callback();
};
}
var mainCss = $(head).find('[href$="main.css"]');
if (mainCss.length !== 0) {
mainCss[0].before(link);
} else {
head.appendChild(link);
}
}
/* 02. Theme Selector, Layout Direction And Initializer */
(function($) {
if ($().dropzone) {
Dropzone.autoDiscover = false;
}
var themeColorsDom = '<div class="theme-colors"><div class="p-4"><p class="text-muted mb-2">Light Theme</p><div class="d-flex flex-row justify-content-between mb-4"></div><p class="text-muted mb-2">Dark Theme</p><div class="d-flex flex-row justify-content-between"></div></div><div class="p-4"><p class="text-muted mb-2">Border Radius</p><div class="custom-control custom-radio custom-control-inline"><input type="radio" id="roundedRadio" name="radiusRadio" class="custom-control-input radius-radio" data-radius="rounded"><label class="custom-control-label" for="roundedRadio">Rounded</label></div><div class="custom-control custom-radio custom-control-inline"><input type="radio" id="flatRadio" name="radiusRadio" class="custom-control-input radius-radio" data-radius="flat"><label class="custom-control-label" for="flatRadio">Flat</label></div></div><div class="p-4"><p class="text-muted mb-2">Direction</p><div class="custom-control custom-radio custom-control-inline"><input type="radio" id="ltrRadio" name="directionRadio" class="custom-control-input direction-radio" data-direction="ltr"><label class="custom-control-label" for="ltrRadio">Ltr</label></div><div class="custom-control custom-radio custom-control-inline"><input type="radio" id="rtlRadio" name="directionRadio" class="custom-control-input direction-radio" data-direction="rtl"><label class="custom-control-label" for="rtlRadio">Rtl</label></div></div> <i class="simple-icon-magic-wand"></i> </div>';
$("body").append(themeColorsDom);
/* Default Theme Color, Border Radius and Direction */
var theme = "dore.light.blue.min.css";
var direction = "ltr";
var radius = "rounded";
if (typeof Storage !== "undefined") {
if (localStorage.getItem("dore-theme")) {
theme = localStorage.getItem("dore-theme");
} else {
localStorage.setItem("dore-theme", theme);
}
if (localStorage.getItem("dore-direction")) {
direction = localStorage.getItem("dore-direction");
} else {
localStorage.setItem("dore-direction", direction);
}
if (localStorage.getItem("dore-radius")) {
radius = localStorage.getItem("dore-radius");
} else {
localStorage.setItem("dore-radius", radius);
}
}
$(".theme-color[data-theme='" + theme + "']").addClass("active");
$(".direction-radio[data-direction='" + direction + "']").attr("checked", true);
$(".radius-radio[data-radius='" + radius + "']").attr("checked", true);
$("#switchDark").attr("checked", theme.indexOf("dark") > 0 ? true : false);
loadStyle("assets/template/css/" + theme, onStyleComplete);
function onStyleComplete() {
setTimeout(onStyleCompleteDelayed, 300);
}
function onStyleCompleteDelayed() {
$("body").addClass(direction);
$("html").attr("dir", direction);
$("body").addClass(radius);
$("body").dore();
}
$("body").on("click", ".theme-color", function(event) {
event.preventDefault();
var dataTheme = $(this).data("theme");
if (typeof Storage !== "undefined") {
localStorage.setItem("dore-theme", dataTheme);
window.location.reload();
}
});
$("input[name='directionRadio']").on("change", function(event) {
var direction = $(event.currentTarget).data("direction");
if (typeof Storage !== "undefined") {
localStorage.setItem("dore-direction", direction);
window.location.reload();
}
});
$("input[name='radiusRadio']").on("change", function(event) {
var radius = $(event.currentTarget).data("radius");
if (typeof Storage !== "undefined") {
localStorage.setItem("dore-radius", radius);
window.location.reload();
}
});
$("#switchDark").on("change", function(event) {
var mode = $(event.currentTarget)[0].checked ? "dark" : "light";
if (mode == "dark") {
theme = theme.replace("light", "dark");
} else if (mode == "light") {
theme = theme.replace("dark", "light");
}
if (typeof Storage !== "undefined") {
localStorage.setItem("dore-theme", theme);
window.location.reload();
}
});
$(".theme-button").on("click", function(event) {
event.preventDefault();
$(this)
.parents(".theme-colors")
.toggleClass("shown");
});
$(document).on("click", function(event) {
if (!(
$(event.target)
.parents()
.hasClass("theme-colors") ||
$(event.target)
.parents()
.hasClass("theme-button") ||
$(event.target).hasClass("theme-button") ||
$(event.target).hasClass("theme-colors")
)) {
if ($(".theme-colors").hasClass("shown")) {
$(".theme-colors").removeClass("shown");
}
}
});
})(jQuery);
error in
mainCss[0].before(link);
when I try to access the link http://localhost/tenderpp/tender
not error, but when I try to access this link http://localhost/tenderpp/tender/new_tender
in console error
GET http://localhost/tenderpp/tender/assets/template/css/dore.light.blue.min.css net::ERR_ABORTED 404 (Not Found)
controller CI3
<?php
defined('BASEPATH') or exit(' No Direct Script');
class Tender extends CI_Controller
{
public function index()
{
$this->load->view('template/header');
$this->load->view('template/sidebar/sidebar_admin');
$this->load->view('admin/v_new_tender');
$this->load->view('template/footer');
}
public function new_tender()
{
$this->load->view('template/header');
$this->load->view('template/sidebar/sidebar_admin');
$this->load->view('admin/v_new_tender');
$this->load->view('template/footer');
}
}
my css,js, etc in assets/template/
my template
https://themeforest.net/item/dore-jquery-bootstrap-4-admin-dashboard/22604108?gclid=Cj0KCQjw5-WRBhCKARIsAAId9Fnl2o3491NpxQtlG0i49_d9Q3X16U4U4UTw3qRHslZncfDb_XlNLoAaAu_5EALw_wcB
I have a page where there are many datepickers in an array. The datepicker ng-repeat is inside a nested ng-repeat. The issue is when in click on one datepicker, all other datepickers open at the same time.
HTML:
//
<div data-ng-repeat="skill in skillset" ng-model="skill.length">
<div class="col-sm-3">
<input type="hidden" ng-model="skill.pk" ng-value="{{skill.pk}}"/>
<ol class="form-control nya-bs-select textbox" name="Skill Set" title="Skill" data-live-search="true" validType="select"
disabled="isProfile" ng-model="skill.skillId" ng-selected="{{skill.skillId}}">
<li nya-bs-option="skillSet in skillSets | orderBy: 'skillSet' track by skillSet.pk" data-value="skillSet.pk">
<a>
{{skillSet.code}}
<span class="glyphicon glyphicon-ok check-mark"></span>
</a>
</li>
</ol>
</div>
<div class="col-sm-2">
<select class="dropdown" ng-model="skill.isPrimary" ng-options="skillset.value as skillset.name for skillset in register.skillsets"></select>
</div>
<div ng-repeat="dt in dates" class="col-sm-2">
<input id="datePickerItem_{{$index}}" type="text" class="datepicker" uib-datepicker-popup="shortDate"
ng-value="skill.sinceLastUsed" ng-model="skill.sinceLastUsed" is-open="dt.opened" ng-click="open($event,dt)"
placeholder="Last Used Date" name="lastuseddate" validType="date" datepicker-options="{minMode: 'month'}" datepicker-mode="'month'"/>
</div>
<div class="col-sm-2">
<span uib-rating ng-model="skill.rating" max="5" min="1" enable-reset="false"></span>
</div>
<div class="col-sm-3">
<button type="button" class="fa fa-minus-circle remove" ng-click="deleteSkill($index)" ng-show="skillset.length>1" data-toggle="tooltip"
data-placement="bottom" title="Delete Skill"></button>
<button type="button" class="fa fa-floppy-o remove" ng-click="saveSkill($index)" data-toggle="tooltip" data-placement="bottom" title="Save Skill"></button>
<button type="button" class="fa fa-plus-circle remove" ng-show="$last" ng-click="addNewSkill($index)"
data-toggle="tooltip" data-placement="bottom" title="Save and Add New Skill"></button><br /><br />
</div>
</div>
</div>
Javascript:
(function (angular) {
var SkillSetController = function ($scope, $controller, $filter, commonAPIservice, candidateCommonServices) {
//Initialization
var _this = this;
_this.title = "Skillset";
_this.service = commonAPIservice;
_this.CandidateCommonServices = candidateCommonServices;
$scope.skillset = [];
$scope.dates = [];
//Button Tooltips
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
});
//Function to load Skills Autocomplete
var loadSkillSets = function () {
var url = 'http://localhost:8080/api/skillset';
_this.service.loadRecords(url)
.then(function (response) {
$scope.skillSets = response.data.skillSets;
});
};
//Function to load Candidate Skill Sets
var loadCandidateSkillSets = function () {
var candidateId = _this.CandidateCommonServices.getCandidateId();
if (candidateId > 0) {
var url = 'http://localhost:8080/api/CandidateSkillSet/GetCandidateSkillSet/' + candidateId;
_this.service.loadRecords(url)
.then(function (response) {
var skillSetLength = response.data.length;
if (skillSetLength > 0) {
$scope.skillset = response.data;
$scope.dates = [{}];
angular.forEach($scope.skillset, function (value, key) {
var sinceLastUsed = new Date($scope.skillset[key].sinceLastUsed);
$scope.skillset[key].sinceLastUsed = ((sinceLastUsed.getMonth() + 1) + "/" + sinceLastUsed.getDate() + "/" + sinceLastUsed.getFullYear());
});
}
else {
$scope.skillset = [$scope.candidateSkillSetForm];
$scope.dates = [{}];
}
});
}
};
//Function to save and add new Skill
$scope.addNewSkill = function (recordIndex) {
var skillset = $scope.skillset[recordIndex];
if (skillset.pk >= 0 )
$scope.skillset.push({});
else {
if (!skillset.skillId || !skillset.rating || !skillset.sinceLastUsed || typeof skillset.isPrimary == 'undefined') {
perfUtils.getInstance().successMsg('All Fields are mandatory');
return;
}
var candidateId = _this.CandidateCommonServices.getCandidateId();
if (candidateId > 0) {
var skillset = $scope.skillset[recordIndex];
skillset.candidateId = candidateId;
_this.service.add('http://localhost:8080/api/CandidateSkillSet/AddCandidateSkillSet/', skillset)
.then(function (response) {
perfUtils.getInstance().successMsg(_this.title + ' added Successfully!');
});
}
$scope.skillset.push({});
}
};
//Function to Save skill
$scope.saveSkill = function (recordIndex) {
var skillset = $scope.skillset[recordIndex];
if (!skillset.skillId || !skillset.rating || !skillset.sinceLastUsed || typeof skillset.isPrimary == 'undefined') {
perfUtils.getInstance().successMsg('All Fields are mandatory');
return;
}
var candidateId = _this.CandidateCommonServices.getCandidateId();
if (candidateId > 0) {
if (skillset.pk > 0) {
alert("Updated Successfully");
}
else
{
skillset.candidateId = candidateId;
_this.service.add('http://localhost:8080/api/CandidateSkillSet/AddCandidateSkillSet/', skillset)
.then(function (response) {
loadCandidateSkillSets();
perfUtils.getInstance().successMsg(_this.title + ' added Successfully!');
});
}
}
};
//Function to Delete Skill
$scope.deleteSkill = function (recordIndex) {
var candidateId = _this.CandidateCommonServices.getCandidateId();
var skillset = $scope.skillset[recordIndex];
if (candidateId > 0 && typeof skillset.isPrimary != 'undefined') {
_this.service.updateDel('http://localhost:8080/api/CandidateSkillSet/DeleteCandidateSkillSet/',skillset)
.then(function (response) {
$scope.skillset.splice(recordIndex, 1);
perfUtils.getInstance().successMsg(_this.title + ' deleted Successfully!');
});
}
else
$scope.skillset.splice(recordIndex, 1);
};
**//Function to open Datepicker
$scope.open = function ($event, dt) {
$event.preventDefault();
$event.stopPropagation();
dt.opened = true;
};**
//Load Skill Type Dropdown
$scope.register = {};
$scope.register.skillsets = [{
value: true,
name: "Primary"
}, {
value: false,
name: "Secondary"
}];
//Star Rating Directive
$scope.ratingStates = { stateOn: 'glyphicon-star', stateOff: 'glyphicon-star-empty' };
//Functions during page load
loadCandidateSkillSets();
loadSkillSets();
};
SkillSetController.$inject = ['$scope', '$controller','$filter', 'commonAPIservice', 'candidateCommonServices'];
mainApp.controller('skillSetController', SkillSetController);
})(angular);
I got the answer. In HTML, set:
id="datePickerItem_{{$parent.$index}}_{{$index}}
is-open="opened[$parent.$index]
ng-click="open($event, $parent.$index)
Javascript:
$scope.opened = [];
$scope.open = function ($event, index) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened[index] = true;
};
I think datepicker id's are same that's why they all are opening try to change id's something like
id="datePickerItem_{{$parent.$index}}_{{$index}}"
I tried different approach but still can't find the solution.
I need to upload an image with my form with fields (title, description, and 2 image).
My system uses csrf of CodeIgniter. And I use this simple third party file uploader (http://jasny.github.io/bootstrap) fileinput.js
var Fileinput = function (element, options) {
this.$element = $(element)
this.$input = this.$element.find(':file')
if (this.$input.length === 0) return
this.name = this.$input.attr('name') || options.name
this.$hidden = this.$element.find('input[type=hidden][name="' + this.name + '"]')
if (this.$hidden.length === 0) {
this.$hidden = $('<input type="hidden">').insertBefore(this.$input)
}
this.$preview = this.$element.find('.fileinput-preview')
var height = this.$preview.css('height')
if (this.$preview.css('display') !== 'inline' && height !== '0px' && height !== 'none') {
this.$preview.css('line-height', height)
}
this.original = {
exists: this.$element.hasClass('fileinput-exists'),
preview: this.$preview.html(),
hiddenVal: this.$hidden.val()
}
this.listen()
}
Fileinput.prototype.listen = function() {
this.$input.on('change.bs.fileinput', $.proxy(this.change, this))
$(this.$input[0].form).on('reset.bs.fileinput', $.proxy(this.reset, this))
this.$element.find('[data-trigger="fileinput"]').on('click.bs.fileinput', $.proxy(this.trigger, this))
this.$element.find('[data-dismiss="fileinput"]').on('click.bs.fileinput', $.proxy(this.clear, this))
},
Fileinput.prototype.change = function(e) {
var files = e.target.files === undefined ? (e.target && e.target.value ? [{ name: e.target.value.replace(/^.+\\/, '')}] : []) : e.target.files
e.stopPropagation()
if (files.length === 0) {
this.clear()
return
}
this.$hidden.val('')
this.$hidden.attr('name', '')
this.$input.attr('name', this.name)
var file = files[0]
if (this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match(/^image\/(gif|png|jpeg)$/) : file.name.match(/\.(gif|png|jpe?g)$/i)) && typeof FileReader !== "undefined") {
var reader = new FileReader()
var preview = this.$preview
var element = this.$element
reader.onload = function(re) {
var $img = $('<img>')
$img[0].src = re.target.result
files[0].result = re.target.result
element.find('.fileinput-filename').text(file.name)
// if parent has max-height, using `(max-)height: 100%` on child doesn't take padding and border into account
if (preview.css('max-height') != 'none') $img.css('max-height', parseInt(preview.css('max-height'), 10) - parseInt(preview.css('padding-top'), 10) - parseInt(preview.css('padding-bottom'), 10) - parseInt(preview.css('border-top'), 10) - parseInt(preview.css('border-bottom'), 10))
preview.html($img)
element.addClass('fileinput-exists').removeClass('fileinput-new')
element.trigger('change.bs.fileinput', files)
}
reader.readAsDataURL(file)
} else {
this.$element.find('.fileinput-filename').text(file.name)
this.$preview.text(file.name)
this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
this.$element.trigger('change.bs.fileinput')
}
},
Fileinput.prototype.clear = function(e) {
if (e) e.preventDefault()
this.$hidden.val('')
this.$hidden.attr('name', this.name)
this.$input.attr('name', '')
//ie8+ doesn't support changing the value of input with type=file so clone instead
this.$input.val('')
this.$preview.html('')
this.$element.find('.fileinput-filename').text('')
this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
if (e !== undefined) {
this.$input.trigger('change')
this.$element.trigger('clear.bs.fileinput')
}
},
Fileinput.prototype.reset = function() {
this.clear()
this.$hidden.val(this.original.hiddenVal)
this.$preview.html(this.original.preview)
this.$element.find('.fileinput-filename').text('')
if (this.original.exists) this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
else this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
this.$element.trigger('reset.bs.fileinput')
},
Fileinput.prototype.trigger = function(e) {
this.$input.trigger('click')
e.preventDefault()
}
// FILEUPLOAD PLUGIN DEFINITION
// ===========================
var old = $.fn.fileinput
$.fn.fileinput = function (options) {
return this.each(function () {
var $this = $(this),
data = $this.data('bs.fileinput')
if (!data) $this.data('bs.fileinput', (data = new Fileinput(this, options)))
if (typeof options == 'string') data[options]()
})
}
$.fn.fileinput.Constructor = Fileinput
// FILEINPUT NO CONFLICT
// ====================
$.fn.fileinput.noConflict = function () {
$.fn.fileinput = old
return this
}
// FILEUPLOAD DATA-API
// ==================
$(document).on('click.fileinput.data-api', '[data-provides="fileinput"]', function (e) {
var $this = $(this)
if ($this.data('bs.fileinput')) return
$this.fileinput($this.data())
var $target = $(e.target).closest('[data-dismiss="fileinput"],[data-trigger="fileinput"]');
if ($target.length > 0) {
e.preventDefault()
$target.trigger('click.bs.fileinput')
}
});
Now here is my form:
<form id="default_form" onsubmit="return false;" data-method="websites" enctype="multipart/form-data" data-toastr-position="top-right" data-success="Sent! Thank you!" class="validate" novalidate="novalidate">
<input type="hidden" name="{$my_csrf_name}" id="csrf" value="{$my_csrf_value}" />
<input type="text" class="form-control required" value="" name="d[DEF_TITLE]" id="MY_TITLE">
<textarea class="form-control required" rows="3" name="d[MY_DESC]" id="MY_DESC"></textarea>
<div class="fileinput fileinput-new" data-provides="fileinput">
<div class="fileinput-new thumbnail" style="min-width: 160px; min-height: 100px; max-width: 200px; max-height: 150px; line-height: 10px;"> <img src="{$_homeurl}space/perm/img/favicon/{$set_data.MY_FAVICON}" alt="{$homeurl}space/perm/img/favicon/{$set_data.MY_FAVICON}" data-src="{$homeurl}space/perm/img/favicon/{$set_data.MY_FAVICON}" > </div>
<div class="fileinput-preview fileinput-exists thumbnail" style="max-width: 200px; max-height: 150px;"></div>
<div>
<span class="btn btn-default btn-file" class="upload-image">
<span class="fileinput-new">Select Favicon image</span>
<span class="fileinput-exists">Change</span>
<input type="file" id="MY_FAVICON" name="d[MY_FAVICON]"></span>
Remove
</div>
</div>
<button id="submit_form" data-fid="default_form" class="btn btn-3d btn-primary btn-xlg btn-block margin-top-30" type="submit">
SUBMIT
</button>
</form>
Now upon clicking the "Select Favicon image" here is my js code event:
var csrf_val = $('#csrf').val();
var csfrData = {};
csfrData['csrf_name'] = csrf_val;
sendFile(this.files[0]);
function sendFile(file) {
$(function() {
$.ajaxSetup({
data: csfrData
});
});
$.ajax({
method: 'post',
url: _admin_url + _curr_mod+'/procedure/uload-image',
data: file,
success: function() {
alert('upload is ok!');
},
processData: false
});
}
upon select of image the JavaScript will process to upload the image in PHP controller/model. As I try to look into the Firebug the post has this values:
ÿØÿà�JFIF������ÿÛ��
Then in the response tab found in the CodeIgniter was this (this might be because of the csrf is not included in the post data):
An Error Was Encountered
The action you have requested is not allowed.
and for the php will just use this code (still not sure how will I handle it in php):
$_FILES['file']
I don't know how to upload an image using an uploader (that has preview of the file) and with csrf in CodeIgniter.
The process is this, upon select of image, an ajax will upload it to the server (temporary folder), and will return a new filename (encryption enabled upon upload in php)
folks! I'm trying to implement an audio recorder within my website. I've just got to make the recorded file to be saved to a subfolder in my website (/speaking_audios). The main problem is that every recording savings I tested are being done with the same name: audio.wav. For example, I save a recent recording and there in the subfolder there appears a file named audio.wav, past three minutes I save another recording, just that this last one overwrites the first file I saved (as it is the same name).
recorder.php
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>FlashWavRecorder demo</title>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js'></script>
<script type="text/javascript" src="js/swfobject.js"></script>
<script type="text/javascript" src="js/recorder.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<h1>FlashWavRecorder</h1>
<p><strong>Upload requires php, i.e. example will not work on github.com</strong></p>
<div id="recorder-audio" class="control_panel idle">
<button class="record_button" onclick="FWRecorder.record('audio', 'audio.wav');" title="Record">
<img src="images/record.png" alt="Record"/>
</button>
<button class="stop_recording_button" onclick="FWRecorder.stopRecording('audio');" title="Stop Recording">
<img src="images/stop.png" alt="Stop Recording"/>
</button>
<button class="play_button" onclick="FWRecorder.playBack('audio');" title="Play">
<img src="images/play.png" alt="Play"/>
</button>
<button class="pause_playing_button" onclick="FWRecorder.pausePlayBack('audio');" title="Pause Playing">
<img src="images/pause.png" alt="Pause Playing"/>
</button>
<button class="stop_playing_button" onclick="FWRecorder.stopPlayBack();" title="Stop Playing">
<img src="images/stop.png" alt="Stop Playing"/>
</button>
<div class="level"></div>
</div>
<div id="recorder-audio2" class="control_panel idle">
<button class="record_button" onclick="FWRecorder.record('audio2', 'audio2.wav');" title="Record">
<img src="images/record.png" alt="Record"/>
</button>
<button class="stop_recording_button" onclick="FWRecorder.stopRecording('audio2');" title="Stop Recording">
<img src="images/stop.png" alt="Stop Recording"/>
</button>
<button class="play_button" onclick="FWRecorder.playBack('audio2');" title="Play">
<img src="images/play.png" alt="Play"/>
</button>
<button class="pause_playing_button" onclick="FWRecorder.pausePlayBack('audio2');" title="Pause Playing">
<img src="images/pause.png" alt="Pause Playing"/>
</button>
<button class="stop_playing_button" onclick="FWRecorder.stopPlayBack();" title="Stop Playing">
<img src="images/stop.png" alt="Stop Playing"/>
</button>
<div class="level"></div>
</div>
<div class="details">
<button class="show_level" onclick="FWRecorder.observeLevel();">Show Level</button>
<button class="hide_level" onclick="FWRecorder.stopObservingLevel();" style="display: none;">Hide Level</button>
<span id="save_button">
<span id="flashcontent">
<p>Your browser must have JavaScript enabled and the Adobe Flash Player installed.</p>
</span>
</span>
<div><button class="show_settings" onclick="microphonePermission()">Microphone permission</button></div>
<div id="status">
Recorder Status...
</div>
<div>Duration: <span id="duration"></span></div>
<div>Activity Level: <span id="activity_level"></span></div>
<div>Upload status: <span id="upload_status"></span></div>
</div>
<form id="uploadForm" name="uploadForm" action="upload.php">
<input name="authenticity_token" value="xxxxx" type="hidden">
<input name="upload_file[parent_id]" value="1" type="hidden">
<input name="format" value="json" type="hidden">
</form>
<h4>Configure Microphone</h4>
<form class="mic_config" onsubmit="return false;">
<ul>
<li>
<label for="rate">Rate</label>
<select id="rate" name="rate">
<option value="44" selected>44,100 Hz</option>
<option value="22">22,050 Hz</option>
<option value="11">11,025 Hz</option>
<option value="8">8,000 Hz</option>
<option value="5">5,512 Hz</option>
</select>
</li>
<li>
<label for="gain">Gain</label>
<select id="gain" name="gain">
</select>
</li>
<li>
<label for="silenceLevel">Silence Level</label>
<select id="silenceLevel" name="silenceLevel">
</select>
</li>
<li>
<label for="silenceTimeout">Silence Timeout</label>
<input id="silenceTimeout" name="silenceTimeout" value="2000"/>
</li>
<li>
<input id="useEchoSuppression" name="useEchoSuppression" type="checkbox"/>
<label for="useEchoSuppression">Use Echo Suppression</label>
</li>
<li>
<input id="loopBack" name="loopBack" type="checkbox"/>
<label for="loopBack">Loop Back</label>
</li>
<li>
<button onclick="configureMicrophone();">Configure</button>
</li>
</ul>
</form>
</div>
</body>
</html>
upload.php
<?php
$save_folder = dirname(__FILE__) . "/speaking_audios";
if(! file_exists($save_folder)) {
if(! mkdir($save_folder)) {
die("failed to create save folder $save_folder");
}
}
function valid_wav_file($file) {
$handle = fopen($file, 'r');
$header = fread($handle, 4);
list($chunk_size) = array_values(unpack('V', fread($handle, 4)));
$format = fread($handle, 4);
fclose($handle);
return $header == 'RIFF' && $format == 'WAVE' && $chunk_size == (filesize($file) - 8);
}
$key = 'filename';
$tmp_name = $_FILES["upload_file"]["tmp_name"][$key];
$upload_name = $_FILES["upload_file"]["name"][$key];
$type = $_FILES["upload_file"]["type"][$key];
$filename = "$save_folder/$upload_name";
$saved = 0;
if($type == 'audio/wav' && preg_match('/^[a-zA-Z0-9_\-]+\.wav$/', $upload_name) && valid_wav_file($tmp_name)) {
$saved = move_uploaded_file($tmp_name, $filename) ? 1 : 0;
}
if($_POST['format'] == 'json') {
header('Content-type: application/json');
print "{\"saved\": $saved}";
} else {
print $saved ? "Saved" : 'Not saved';
}
exit;
?>
js/main.js
$(function () {
var $uploadStatus = $('#upload_status'),
$showLevelButton = $('.show_level'),
$hideLevelButton = $('.hide_level'),
$level = $('.control_panel .level');
var CLASS_CONTROLS = "control_panel";
var CLASS_RECORDING = "recording";
var CLASS_PLAYBACK_READY = "playback_ready";
var CLASS_PLAYING = "playing";
var CLASS_PLAYBACK_PAUSED = "playback_paused";
// Embedding flash object ---------------------------------------------------------------------------------------------
setUpFormOptions();
var appWidth = 24;
var appHeight = 24;
var flashvars = {'upload_image': 'images/upload.png'};
var params = {};
var attributes = {'id': "recorderApp", 'name': "recorderApp"};
swfobject.embedSWF("recorder.swf", "flashcontent", appWidth, appHeight, "11.0.0", "", flashvars, params, attributes);
// Handling FWR events ------------------------------------------------------------------------------------------------
window.fwr_event_handler = function fwr_event_handler() {
$('#status').text("Last recorder event: " + arguments[0]);
var name, $controls;
switch (arguments[0]) {
case "ready":
var width = parseInt(arguments[1]);
var height = parseInt(arguments[2]);
FWRecorder.uploadFormId = "#uploadForm";
FWRecorder.uploadFieldName = "upload_file[filename]";
FWRecorder.connect("recorderApp", 0);
FWRecorder.recorderOriginalWidth = width;
FWRecorder.recorderOriginalHeight = height;
$('.save_button').css({'width': width, 'height': height});
break;
case "no_microphone_found":
break;
case "microphone_user_request":
recorderEl().addClass("floating");
FWRecorder.showPermissionWindow();
break;
case "microphone_connected":
FWRecorder.isReady = true;
$uploadStatus.css({'color': '#000'});
break;
case "permission_panel_closed":
FWRecorder.defaultSize();
recorderEl().removeClass("floating");
break;
case "microphone_activity":
$('#activity_level').text(arguments[1]);
break;
case "recording":
name = arguments[1];
$controls = controlsEl(name);
FWRecorder.hide();
setControlsClass($controls, CLASS_RECORDING);
break;
case "recording_stopped":
name = arguments[1];
$controls = controlsEl(name);
var duration = arguments[2];
FWRecorder.show();
setControlsClass($controls, CLASS_PLAYBACK_READY);
$('#duration').text(duration.toFixed(4) + " seconds");
break;
case "microphone_level":
$level.css({width: arguments[1] * 50 + '%'});
break;
case "observing_level":
$showLevelButton.hide();
$hideLevelButton.show();
break;
case "observing_level_stopped":
$showLevelButton.show();
$hideLevelButton.hide();
$level.css({width: 0});
break;
case "playing":
name = arguments[1];
$controls = controlsEl(name);
setControlsClass($controls, CLASS_PLAYING);
break;
case "playback_started":
name = arguments[1];
var latency = arguments[2];
break;
case "stopped":
name = arguments[1];
$controls = controlsEl(name);
setControlsClass($controls, CLASS_PLAYBACK_READY);
break;
case "playing_paused":
name = arguments[1];
$controls = controlsEl(name);
setControlsClass($controls, CLASS_PLAYBACK_PAUSED);
break;
case "save_pressed":
FWRecorder.updateForm();
break;
case "saving":
name = arguments[1];
break;
case "saved":
name = arguments[1];
var data = $.parseJSON(arguments[2]);
if (data.saved) {
$('#upload_status').css({'color': '#0F0'}).text(name + " was saved");
} else {
$('#upload_status').css({'color': '#F00'}).text(name + " was not saved");
}
break;
case "save_failed":
name = arguments[1];
var errorMessage = arguments[2];
$uploadStatus.css({'color': '#F00'}).text(name + " failed: " + errorMessage);
break;
case "save_progress":
name = arguments[1];
var bytesLoaded = arguments[2];
var bytesTotal = arguments[3];
$uploadStatus.css({'color': '#000'}).text(name + " progress: " + bytesLoaded + " / " + bytesTotal);
break;
}
};
// Helper functions ---------------------------------------------------------------------------------------------------
function setUpFormOptions() {
var gain = $('#gain')[0];
var silenceLevel = $('#silenceLevel')[0];
for (var i = 0; i <= 100; i++) {
gain.options[gain.options.length] = new Option(100 - i);
silenceLevel.options[silenceLevel.options.length] = new Option(i);
}
}
function setControlsClass($controls, className) {
$controls.attr('class', CLASS_CONTROLS + ' ' + className);
}
function controlsEl(name) {
return $('#recorder-' + name);
}
function recorderEl() {
return $('#recorderApp');
}
// Button actions -----------------------------------------------------------------------------------------------------
window.microphonePermission = function () {
recorderEl().addClass("floating");
FWRecorder.showPermissionWindow({permanent: true});
};
window.configureMicrophone = function () {
if (!FWRecorder.isReady) {
return;
}
FWRecorder.configure($('#rate').val(), $('#gain').val(), $('#silenceLevel').val(), $('#silenceTimeout').val());
FWRecorder.setUseEchoSuppression($('#useEchoSuppression').is(":checked"));
FWRecorder.setLoopBack($('#loopBack').is(":checked"));
};
});
js/recorder.js
(function(global) {
var Recorder;
var RECORDED_AUDIO_TYPE = "audio/wav";
Recorder = {
recorder: null,
recorderOriginalWidth: 0,
recorderOriginalHeight: 0,
uploadFormId: null,
uploadFieldName: null,
isReady: false,
connect: function(name, attempts) {
if(navigator.appName.indexOf("Microsoft") != -1) {
Recorder.recorder = window[name];
} else {
Recorder.recorder = document[name];
}
if(attempts >= 40) {
return;
}
// flash app needs time to load and initialize
if(Recorder.recorder && Recorder.recorder.init) {
Recorder.recorderOriginalWidth = Recorder.recorder.width;
Recorder.recorderOriginalHeight = Recorder.recorder.height;
if(Recorder.uploadFormId && $) {
var frm = $(Recorder.uploadFormId);
Recorder.recorder.init(frm.attr('action').toString(), Recorder.uploadFieldName, frm.serializeArray());
}
return;
}
setTimeout(function() {Recorder.connect(name, attempts+1);}, 100);
},
playBack: function(name) {
// TODO: Rename to `playback`
Recorder.recorder.playBack(name);
},
pausePlayBack: function(name) {
// TODO: Rename to `pausePlayback`
Recorder.recorder.pausePlayBack(name);
},
playBackFrom: function(name, time) {
// TODO: Rename to `playbackFrom`
Recorder.recorder.playBackFrom(name, time);
},
record: function(name, filename) {
Recorder.recorder.record(name, filename);
},
stopRecording: function() {
Recorder.recorder.stopRecording();
},
stopPlayBack: function() {
// TODO: Rename to `stopPlayback`
Recorder.recorder.stopPlayBack();
},
observeLevel: function() {
Recorder.recorder.observeLevel();
},
stopObservingLevel: function() {
Recorder.recorder.stopObservingLevel();
},
observeSamples: function() {
Recorder.recorder.observeSamples();
},
stopObservingSamples: function() {
Recorder.recorder.stopObservingSamples();
},
resize: function(width, height) {
Recorder.recorder.width = width + "px";
Recorder.recorder.height = height + "px";
},
defaultSize: function() {
Recorder.resize(Recorder.recorderOriginalWidth, Recorder.recorderOriginalHeight);
},
show: function() {
Recorder.recorder.show();
},
hide: function() {
Recorder.recorder.hide();
},
duration: function(name) {
// TODO: rename to `getDuration`
return Recorder.recorder.duration(name || Recorder.uploadFieldName);
},
getBase64: function(name) {
var data = Recorder.recorder.getBase64(name);
return 'data:' + RECORDED_AUDIO_TYPE + ';base64,' + data;
},
getBlob: function(name) {
var base64Data = Recorder.getBase64(name).split(',')[1];
return base64toBlob(base64Data, RECORDED_AUDIO_TYPE);
},
getCurrentTime: function(name) {
return Recorder.recorder.getCurrentTime(name);
},
isMicrophoneAccessible: function() {
return Recorder.recorder.isMicrophoneAccessible();
},
updateForm: function() {
var frm = $(Recorder.uploadFormId);
Recorder.recorder.update(frm.serializeArray());
},
showPermissionWindow: function(options) {
Recorder.resize(240, 160);
// need to wait until app is resized before displaying permissions screen
var permissionCommand = function() {
if (options && options.permanent) {
Recorder.recorder.permitPermanently();
} else {
Recorder.recorder.permit();
}
};
setTimeout(permissionCommand, 1);
},
configure: function(rate, gain, silenceLevel, silenceTimeout) {
rate = parseInt(rate || 22);
gain = parseInt(gain || 100);
silenceLevel = parseInt(silenceLevel || 0);
silenceTimeout = parseInt(silenceTimeout || 4000);
switch(rate) {
case 44:
case 22:
case 11:
case 8:
case 5:
break;
default:
throw("invalid rate " + rate);
}
if(gain < 0 || gain > 100) {
throw("invalid gain " + gain);
}
if(silenceLevel < 0 || silenceLevel > 100) {
throw("invalid silenceLevel " + silenceLevel);
}
if(silenceTimeout < -1) {
throw("invalid silenceTimeout " + silenceTimeout);
}
Recorder.recorder.configure(rate, gain, silenceLevel, silenceTimeout);
},
setUseEchoSuppression: function(val) {
if(typeof(val) != 'boolean') {
throw("invalid value for setting echo suppression, val: " + val);
}
Recorder.recorder.setUseEchoSuppression(val);
},
setLoopBack: function(val) {
if(typeof(val) != 'boolean') {
throw("invalid value for setting loop back, val: " + val);
}
Recorder.recorder.setLoopBack(val);
}
};
function base64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return new Blob(byteArrays, {type: contentType});
}
global.FWRecorder = Recorder;
})(this);
I couldn't expose all the files above, cause there was no more space left. Well, I just want to individualize each saved file. It can be that way: username.randomidcode or something like that.
I am trying to implement an audio recorder within my website. What I want is to make the user save the recorded file directly to the database and/or to a subfolder in my website (called /speaking_audios). There follows the main files: recorder.php, sync.html, upload.php, js/main.js, js/swfobject.js, js/recorder.js, recorder.swf (I don't know what it is for).
recorder.php
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>FlashWavRecorder demo</title>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js'></script>
<script type="text/javascript" src="js/swfobject.js"></script>
<script type="text/javascript" src="js/recorder.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<h1>FlashWavRecorder</h1>
<p><strong>Upload requires php, i.e. example will not work on github.com</strong></p>
<div id="recorder-audio" class="control_panel idle">
<button class="record_button" onclick="FWRecorder.record('audio', 'audio.wav');" title="Record">
<img src="images/record.png" alt="Record"/>
</button>
<button class="stop_recording_button" onclick="FWRecorder.stopRecording('audio');" title="Stop Recording">
<img src="images/stop.png" alt="Stop Recording"/>
</button>
<button class="play_button" onclick="FWRecorder.playBack('audio');" title="Play">
<img src="images/play.png" alt="Play"/>
</button>
<button class="pause_playing_button" onclick="FWRecorder.pausePlayBack('audio');" title="Pause Playing">
<img src="images/pause.png" alt="Pause Playing"/>
</button>
<button class="stop_playing_button" onclick="FWRecorder.stopPlayBack();" title="Stop Playing">
<img src="images/stop.png" alt="Stop Playing"/>
</button>
<div class="level"></div>
</div>
<div id="recorder-audio2" class="control_panel idle">
<button class="record_button" onclick="FWRecorder.record('audio2', 'audio2.wav');" title="Record">
<img src="images/record.png" alt="Record"/>
</button>
<button class="stop_recording_button" onclick="FWRecorder.stopRecording('audio2');" title="Stop Recording">
<img src="images/stop.png" alt="Stop Recording"/>
</button>
<button class="play_button" onclick="FWRecorder.playBack('audio2');" title="Play">
<img src="images/play.png" alt="Play"/>
</button>
<button class="pause_playing_button" onclick="FWRecorder.pausePlayBack('audio2');" title="Pause Playing">
<img src="images/pause.png" alt="Pause Playing"/>
</button>
<button class="stop_playing_button" onclick="FWRecorder.stopPlayBack();" title="Stop Playing">
<img src="images/stop.png" alt="Stop Playing"/>
</button>
<div class="level"></div>
</div>
<div class="details">
<button class="show_level" onclick="FWRecorder.observeLevel();">Show Level</button>
<button class="hide_level" onclick="FWRecorder.stopObservingLevel();" style="display: none;">Hide Level</button>
<span id="save_button">
<span id="flashcontent">
<p>Your browser must have JavaScript enabled and the Adobe Flash Player installed.</p>
</span>
</span>
<div><button class="show_settings" onclick="microphonePermission()">Microphone permission</button></div>
<div id="status">
Recorder Status...
</div>
<div>Duration: <span id="duration"></span></div>
<div>Activity Level: <span id="activity_level"></span></div>
<div>Upload status: <span id="upload_status"></span></div>
</div>
<form id="uploadForm" name="uploadForm" action="upload.php">
<input name="authenticity_token" value="xxxxx" type="hidden">
<input name="upload_file[parent_id]" value="1" type="hidden">
<input name="format" value="json" type="hidden">
</form>
<h4>Configure Microphone</h4>
<form class="mic_config" onsubmit="return false;">
<ul>
<li>
<label for="rate">Rate</label>
<select id="rate" name="rate">
<option value="44" selected>44,100 Hz</option>
<option value="22">22,050 Hz</option>
<option value="11">11,025 Hz</option>
<option value="8">8,000 Hz</option>
<option value="5">5,512 Hz</option>
</select>
</li>
<li>
<label for="gain">Gain</label>
<select id="gain" name="gain">
</select>
</li>
<li>
<label for="silenceLevel">Silence Level</label>
<select id="silenceLevel" name="silenceLevel">
</select>
</li>
<li>
<label for="silenceTimeout">Silence Timeout</label>
<input id="silenceTimeout" name="silenceTimeout" value="2000"/>
</li>
<li>
<input id="useEchoSuppression" name="useEchoSuppression" type="checkbox"/>
<label for="useEchoSuppression">Use Echo Suppression</label>
</li>
<li>
<input id="loopBack" name="loopBack" type="checkbox"/>
<label for="loopBack">Loop Back</label>
</li>
<li>
<button onclick="configureMicrophone();">Configure</button>
</li>
</ul>
</form>
</div>
</body>
</html>
upload.php
<?php
$save_folder = dirname(__FILE__) . "/speaking_audios";
if(! file_exists($save_folder)) {
if(! mkdir($save_folder)) {
die("failed to create save folder $save_folder");
}
}
function valid_wav_file($file) {
$handle = fopen($file, 'r');
$header = fread($handle, 4);
list($chunk_size) = array_values(unpack('V', fread($handle, 4)));
$format = fread($handle, 4);
fclose($handle);
return $header == 'RIFF' && $format == 'WAVE' && $chunk_size == (filesize($file) - 8);
}
$key = 'filename';
$tmp_name = $_FILES["upload_file"]["tmp_name"][$key];
$upload_name = $_FILES["upload_file"]["name"][$key];
$type = $_FILES["upload_file"]["type"][$key];
$filename = "$save_folder/$upload_name";
$saved = 0;
if($type == 'audio/wav' && preg_match('/^[a-zA-Z0-9_\-]+\.wav$/', $upload_name) && valid_wav_file($tmp_name)) {
$saved = move_uploaded_file($tmp_name, $filename) ? 1 : 0;
}
if($_POST['format'] == 'json') {
header('Content-type: application/json');
print "{\"saved\": $saved}";
} else {
print $saved ? "Saved" : 'Not saved';
}
exit;
?>
js/main.js
$(function () {
var $uploadStatus = $('#upload_status'),
$showLevelButton = $('.show_level'),
$hideLevelButton = $('.hide_level'),
$level = $('.control_panel .level');
var CLASS_CONTROLS = "control_panel";
var CLASS_RECORDING = "recording";
var CLASS_PLAYBACK_READY = "playback_ready";
var CLASS_PLAYING = "playing";
var CLASS_PLAYBACK_PAUSED = "playback_paused";
// Embedding flash object ---------------------------------------------------------------------------------------------
setUpFormOptions();
var appWidth = 24;
var appHeight = 24;
var flashvars = {'upload_image': 'images/upload.png'};
var params = {};
var attributes = {'id': "recorderApp", 'name': "recorderApp"};
swfobject.embedSWF("recorder.swf", "flashcontent", appWidth, appHeight, "11.0.0", "", flashvars, params, attributes);
// Handling FWR events ------------------------------------------------------------------------------------------------
window.fwr_event_handler = function fwr_event_handler() {
$('#status').text("Last recorder event: " + arguments[0]);
var name, $controls;
switch (arguments[0]) {
case "ready":
var width = parseInt(arguments[1]);
var height = parseInt(arguments[2]);
FWRecorder.uploadFormId = "#uploadForm";
FWRecorder.uploadFieldName = "upload_file[filename]";
FWRecorder.connect("recorderApp", 0);
FWRecorder.recorderOriginalWidth = width;
FWRecorder.recorderOriginalHeight = height;
$('.save_button').css({'width': width, 'height': height});
break;
case "no_microphone_found":
break;
case "microphone_user_request":
recorderEl().addClass("floating");
FWRecorder.showPermissionWindow();
break;
case "microphone_connected":
FWRecorder.isReady = true;
$uploadStatus.css({'color': '#000'});
break;
case "permission_panel_closed":
FWRecorder.defaultSize();
recorderEl().removeClass("floating");
break;
case "microphone_activity":
$('#activity_level').text(arguments[1]);
break;
case "recording":
name = arguments[1];
$controls = controlsEl(name);
FWRecorder.hide();
setControlsClass($controls, CLASS_RECORDING);
break;
case "recording_stopped":
name = arguments[1];
$controls = controlsEl(name);
var duration = arguments[2];
FWRecorder.show();
setControlsClass($controls, CLASS_PLAYBACK_READY);
$('#duration').text(duration.toFixed(4) + " seconds");
break;
case "microphone_level":
$level.css({width: arguments[1] * 50 + '%'});
break;
case "observing_level":
$showLevelButton.hide();
$hideLevelButton.show();
break;
case "observing_level_stopped":
$showLevelButton.show();
$hideLevelButton.hide();
$level.css({width: 0});
break;
case "playing":
name = arguments[1];
$controls = controlsEl(name);
setControlsClass($controls, CLASS_PLAYING);
break;
case "playback_started":
name = arguments[1];
var latency = arguments[2];
break;
case "stopped":
name = arguments[1];
$controls = controlsEl(name);
setControlsClass($controls, CLASS_PLAYBACK_READY);
break;
case "playing_paused":
name = arguments[1];
$controls = controlsEl(name);
setControlsClass($controls, CLASS_PLAYBACK_PAUSED);
break;
case "save_pressed":
FWRecorder.updateForm();
break;
case "saving":
name = arguments[1];
break;
case "saved":
name = arguments[1];
var data = $.parseJSON(arguments[2]);
if (data.saved) {
$('#upload_status').css({'color': '#0F0'}).text(name + " was saved");
} else {
$('#upload_status').css({'color': '#F00'}).text(name + " was not saved");
}
break;
case "save_failed":
name = arguments[1];
var errorMessage = arguments[2];
$uploadStatus.css({'color': '#F00'}).text(name + " failed: " + errorMessage);
break;
case "save_progress":
name = arguments[1];
var bytesLoaded = arguments[2];
var bytesTotal = arguments[3];
$uploadStatus.css({'color': '#000'}).text(name + " progress: " + bytesLoaded + " / " + bytesTotal);
break;
}
};
// Helper functions ---------------------------------------------------------------------------------------------------
function setUpFormOptions() {
var gain = $('#gain')[0];
var silenceLevel = $('#silenceLevel')[0];
for (var i = 0; i <= 100; i++) {
gain.options[gain.options.length] = new Option(100 - i);
silenceLevel.options[silenceLevel.options.length] = new Option(i);
}
}
function setControlsClass($controls, className) {
$controls.attr('class', CLASS_CONTROLS + ' ' + className);
}
function controlsEl(name) {
return $('#recorder-' + name);
}
function recorderEl() {
return $('#recorderApp');
}
// Button actions -----------------------------------------------------------------------------------------------------
window.microphonePermission = function () {
recorderEl().addClass("floating");
FWRecorder.showPermissionWindow({permanent: true});
};
window.configureMicrophone = function () {
if (!FWRecorder.isReady) {
return;
}
FWRecorder.configure($('#rate').val(), $('#gain').val(), $('#silenceLevel').val(), $('#silenceTimeout').val());
FWRecorder.setUseEchoSuppression($('#useEchoSuppression').is(":checked"));
FWRecorder.setLoopBack($('#loopBack').is(":checked"));
};
});
js/recorder.js
(function(global) {
var Recorder;
var RECORDED_AUDIO_TYPE = "audio/wav";
Recorder = {
recorder: null,
recorderOriginalWidth: 0,
recorderOriginalHeight: 0,
uploadFormId: null,
uploadFieldName: null,
isReady: false,
connect: function(name, attempts) {
if(navigator.appName.indexOf("Microsoft") != -1) {
Recorder.recorder = window[name];
} else {
Recorder.recorder = document[name];
}
if(attempts >= 40) {
return;
}
// flash app needs time to load and initialize
if(Recorder.recorder && Recorder.recorder.init) {
Recorder.recorderOriginalWidth = Recorder.recorder.width;
Recorder.recorderOriginalHeight = Recorder.recorder.height;
if(Recorder.uploadFormId && $) {
var frm = $(Recorder.uploadFormId);
Recorder.recorder.init(frm.attr('action').toString(), Recorder.uploadFieldName, frm.serializeArray());
}
return;
}
setTimeout(function() {Recorder.connect(name, attempts+1);}, 100);
},
playBack: function(name) {
// TODO: Rename to `playback`
Recorder.recorder.playBack(name);
},
pausePlayBack: function(name) {
// TODO: Rename to `pausePlayback`
Recorder.recorder.pausePlayBack(name);
},
playBackFrom: function(name, time) {
// TODO: Rename to `playbackFrom`
Recorder.recorder.playBackFrom(name, time);
},
record: function(name, filename) {
Recorder.recorder.record(name, filename);
},
stopRecording: function() {
Recorder.recorder.stopRecording();
},
stopPlayBack: function() {
// TODO: Rename to `stopPlayback`
Recorder.recorder.stopPlayBack();
},
observeLevel: function() {
Recorder.recorder.observeLevel();
},
stopObservingLevel: function() {
Recorder.recorder.stopObservingLevel();
},
observeSamples: function() {
Recorder.recorder.observeSamples();
},
stopObservingSamples: function() {
Recorder.recorder.stopObservingSamples();
},
resize: function(width, height) {
Recorder.recorder.width = width + "px";
Recorder.recorder.height = height + "px";
},
defaultSize: function() {
Recorder.resize(Recorder.recorderOriginalWidth, Recorder.recorderOriginalHeight);
},
show: function() {
Recorder.recorder.show();
},
hide: function() {
Recorder.recorder.hide();
},
duration: function(name) {
// TODO: rename to `getDuration`
return Recorder.recorder.duration(name || Recorder.uploadFieldName);
},
getBase64: function(name) {
var data = Recorder.recorder.getBase64(name);
return 'data:' + RECORDED_AUDIO_TYPE + ';base64,' + data;
},
getBlob: function(name) {
var base64Data = Recorder.getBase64(name).split(',')[1];
return base64toBlob(base64Data, RECORDED_AUDIO_TYPE);
},
getCurrentTime: function(name) {
return Recorder.recorder.getCurrentTime(name);
},
isMicrophoneAccessible: function() {
return Recorder.recorder.isMicrophoneAccessible();
},
updateForm: function() {
var frm = $(Recorder.uploadFormId);
Recorder.recorder.update(frm.serializeArray());
},
showPermissionWindow: function(options) {
Recorder.resize(240, 160);
// need to wait until app is resized before displaying permissions screen
var permissionCommand = function() {
if (options && options.permanent) {
Recorder.recorder.permitPermanently();
} else {
Recorder.recorder.permit();
}
};
setTimeout(permissionCommand, 1);
},
configure: function(rate, gain, silenceLevel, silenceTimeout) {
rate = parseInt(rate || 22);
gain = parseInt(gain || 100);
silenceLevel = parseInt(silenceLevel || 0);
silenceTimeout = parseInt(silenceTimeout || 4000);
switch(rate) {
case 44:
case 22:
case 11:
case 8:
case 5:
break;
default:
throw("invalid rate " + rate);
}
if(gain < 0 || gain > 100) {
throw("invalid gain " + gain);
}
if(silenceLevel < 0 || silenceLevel > 100) {
throw("invalid silenceLevel " + silenceLevel);
}
if(silenceTimeout < -1) {
throw("invalid silenceTimeout " + silenceTimeout);
}
Recorder.recorder.configure(rate, gain, silenceLevel, silenceTimeout);
},
setUseEchoSuppression: function(val) {
if(typeof(val) != 'boolean') {
throw("invalid value for setting echo suppression, val: " + val);
}
Recorder.recorder.setUseEchoSuppression(val);
},
setLoopBack: function(val) {
if(typeof(val) != 'boolean') {
throw("invalid value for setting loop back, val: " + val);
}
Recorder.recorder.setLoopBack(val);
}
};
function base64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return new Blob(byteArrays, {type: contentType});
}
global.FWRecorder = Recorder;
})(this);
Well, I just want you to concentrate on the upload.php file and see what I'm doing wrong.
When dealing with files, a valid enctype and a POST method is required.
Therefore, you need to change this form:
<form id="uploadForm" name="uploadForm" action="upload.php">
To this:
<form enctype="multipart/form-data" method="post" id="uploadForm" name="uploadForm" action="upload.php">
and check for errors and making sure the folder you're uploading to, has the right permissions.
References:
http://php.net/manual/en/features.file-upload.post-method.php
http://php.net/manual/en/function.error-reporting.php