cropperjs works but shows duplicated images - cropperjs

I am using cropperjs to crop an image. My cropping function goes like this:
function GestionCropEventPhoto(CtrlID) {
$('#' + CtrlID + '_event_img').cropper({
aspectRatio: 1,
autoCropArea: 1,
crop: function (e) {
var json = [
'{"x":' + e.x,
'"y":' + e.y,
'"height":' + e.height,
'"width":' + e.width,
'"rotate":' + e.rotate + '}'
].join();
}
});
var Values = {}
Values["eventid"] = $('#' + CtrlID + '_PEventID_HF').val();
$('#' + CtrlID + '_fileupload', this.el).fileupload({
url: gestionPath + "/App_Dynamic/WS_Gestion.asmx/UploadedEventPhoto",
autoUpload: true,
type: 'POST',
dataType: 'json',
submit: function (e, data) {
data.formData = Values;
},
start: function (e) {
$('#' + CtrlID + '_fileupload_P').css('width', '0%');
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#' + CtrlID + '_fileupload_P').css('width', progress + '%');
},
done: function (e, data) {
if (data.jqXHR.responseText || data.result) {
var JSONjQueryObject = (data.jqXHR.responseText) ? jQuery.parseJSON(data.jqXHR.responseText) : data.result;
if (JSONjQueryObject.Value._IsError) {
ShowErrorMessage('DONE:' + JSONjQueryObject.Value._errorMSG);
} else {
$('#' + CtrlID + '_event_img').cropper.('replace', JSONjQueryObject.Value._name)
}
}
},
fail: function (e, data) {
ShowErrorMessage('Error: ' + data.jqXHR.responseText);
}
});
Now, I believe the last 'else' in the 'done' section where i'm using cropper('replace', ...) is what creates the issue. Can you guys help me ?

I found the solution!
cropper.js wasn't included as a stylesheet in my Site.Master.

Related

Show and Hide Bootstrap Modal for displaying Loading Image

I have a modal with a GIF image that i used for Loadin instead of using spinners. However there are times that the modal_loading is not hiding after calling the hide_loading function.
<script>
function show_loading(title="", message=""){
$('#loading_title').html('');
$('#loading_message').html('');
if(title != ""){
$('#loading_title').html("<h5 style='padding:7px;font-weight:bold'>"+ title + "</h5>");
}
if(message != ""){
$('#loading_message').html("<p style='padding:7px'>" + message + "</p>");
}
$('#modal_loading').modal('show');
}
function hide_loading(){
$('#modal_loading').on('shown.bs.modal', function (e) {
$("#modal_loading").modal('hide');
})
}
</script>
Here is my code.
function fetch_data(page, sort_type, sort_by) {
show_loading('Populating Table');
var filter = $('#form_filter').serialize();
$.ajax({
url: "/lrmis-learning_resources/get_ajax_data?sortby=" + sort_by + "&page=" + page + "&sorttype=" + sort_type + "&" + filter,
success: function(data) {
$('#my_table').html(data);
clear_icon();
if (sort_type == "desc") {
$('#' + sort_by + '_icon').html('<span class="fa fa-caret-down"></span>');
} else {
$('#' + sort_by + '_icon').html('<span class="fa fa-caret-up"></span>');
}
hide_loading();
}
});
}

JQGrid with Multiselect widget for multi filter and persisting the filter and sort value into cookie

I have requirement to be able to persist the filtered grid view for a session. I have done something like this. I am storing the filter value into cookie. But not being able to get the desired result.
modifySearchingFilter = function (separator) {
var i, l, rules, rule, parts, j, group, str, iCol, cmi, cm = this.p.colModel,
filters = this.p.postData.filters === undefined ? null : $.parseJSON(this.p.postData.filters);
console.log(document.cookie);
if(( filters===null) &&(document.cookie.length != 0)) {
var tempcookiearray = document.cookie.split(';');
if (tempcookiearray.length > 1) {
var temp = tempcookiearray[0];
var secondtemp = temp.split('=');
if (secondtemp[1] !== 'null') {
filters = secondtemp[1];
filters = $.parseJSON(filters);
}
}
}
if (filters && filters.rules !== undefined && filters.rules.length>0) {
var temp = filters.rules;
rules = filters.rules;
for (i = 0; i < rules.length; i++) {
rule = rules[i];
iCol = getColumnIndexByName.call(this, rule.field);
cmi = cm[iCol];
if (iCol >= 0 &&
((cmi.searchoptions === undefined || cmi.searchoptions.sopt === undefined)
&& (rule.op === myDefaultSearch)) ||
(typeof (cmi.searchoptions) === "object" &&
$.isArray(cmi.searchoptions.sopt) &&
cmi.searchoptions.sopt[0] === rule.op)) {
// make modifications only for the "contains" operation
parts = rule.data.split(separator);
if (parts.length > 1) {
if (filters.groups === undefined) {
filters.groups = [];
}
group = {
groupOp: "OR",
groups: [],
rules: []
};
filters.groups.push(group);
for (j = 0, l = parts.length; j < l; j++) {
str = parts[j];
if (str) {
// skip empty "", which exist in case of two separaters of once
group.rules.push({
data: parts[j],
op: rule.op,
field: rule.field
});
}
}
rules.splice(i, 1);
i--; // to skip i++
}
}
}
}
this.p.postData.filters = JSON.stringify(filters);
document.cookie = "cookie=" + this.p.postData.filters;
};
$.ajax({
method: "GET"
, url: "/Test/_vti_bin/ListData.svc/ProductList?$expand=Invoice"
, contentType: "application/json; charset=utf-8"
, dataType: "json"
, success: function (data, status) {
ParseData(data.d);
}
, error: function () {
//alert("WAT?!");
}
});
var ParseData = function (d) {
var newData = {
totalPages: 1
, currentPage: 1
, totalRows: d.results.length
, data: d.results
};
BuildTable(newData);
};
var BuildTable = function (d) {
$("#jqGrid").jqGrid({
data: d.data,
datatype: 'local',
colModel: [
{ label: "Title", name: 'Title' },
{ label: "Number", name: 'Number', align: 'center', key: true },
{ label: "Date", name: 'Date', align: 'center' },
{ label: "Descritption", name: 'Description', formatter: testformat },
{ label: "Category", name: 'Category'}
],
loadonce: true,
viewrecords: true,
autowidth: true,
shrinkToFit: false,
sortable: true,
sortname:"Title",
rowNum: '999',
rownumbers:true
});
setSearchSelect('Title');
setSearchSelect('Number');
setSearchSelect('EndDate');
setSearchSelect('Description');
setSearchSelect('Category');
function testformat(cellvalue, options, rowObject) {
return "<a href='http://www.google.com' target='_blank'>" + cellvalue + "</a>"
};
// activate the filterToolbar
$('#jqGrid').jqGrid('filterToolbar', {
stringResult: true,
searchOnEnter: true,
// defaultSearch: myDefaultSearch,
beforeClear: function () {
$(this.grid.hDiv).find(".ui-search-toolbar button.ui-multiselect").each(function () {
$(this).prev("select[multiple]").multiselect("refresh");
}).css({
width: "98%",
marginTop: "1px",
marginBottom: "1px",
paddingTop: "3px"
});
}
}).trigger('reloadGrid');
$('#jqGrid').jqGrid('setGridParam', {
beforeRequest: function () {
modifySearchingFilter.call(this, ",");
}
});
$('#jqGrid').jqGrid('setGridParam', {
loadComplete: function () {
$('.ui-jqgrid .ui-jqgrid-htable th').css('background-color', '#DCD796');
$('.ui-jqgrid tr.jqgrow:odd').css('background-color', '#FFFCED');
$('.ui-jqgrid .ui-jqgrid-bdiv').css('height', '500px');
$('.ui-multiselect-checkboxes LI').css('font-size', '1.2em');
}
}).trigger('reloadGrid');
};
enter code here

Typeahead not working for cyrillic

I'm using Typeahead version 0.10.5. It's working for english words but it's not working for each word written in cyrrilic. Some words written in cyrillic are shown, but others aren't. What is this due to?
I'm using it like this:
$('#edicode').typeahead({
source: function(query, process){
CallAPI("GET", "/companies/get/" + query + "/like", function (data) {
var sourcedata = new Array();
var jsonData = JSON.parse(data);
var count = 0;
$.each(jsonData, function(jsonId) {
sourcedata.push(jsonData[jsonId].CODE + ' / ' + jsonData[jsonId].NAME);
selectedItems[jsonData[jsonId].CODE] = JSON.stringify(jsonData[jsonId]);
count++;
});
if(count <= 0)
{
$('#company_name').val('');
$('#company_name').prop('readonly', false);
}
console.log(sourcedata);
return process(sourcedata);
});
},
updater: function (item) {
var info = item.split(" / ");
var company = jQuery.parseJSON(selectedItems[info[0]]);
$('#EDICode').val(company.CODE);
return company.CODE + '/ ' + company.NAME ;
},
name: 'Company',
displayKey: 'value',
minLength: 2,
maxItem: 15,
accent: true,
hint: true
}).blur(function(){
});
Took 1 hour to find:
open bootstrap-typeahead.js (not minified)
find:
matcher: function (item) {
return ~item.toLowerCase().indexOf(this.query.toLowerCase());
},
change to:
matcher: function (item) {
var x=item.toLowerCase().indexOf(this.query.toLowerCase());;
if(x==-1)
x=0;
return ~x
},

fs.writefile only execute in last function in node js

My program has three functions shown below,
var userId = req.userId;
var appId = req.body.appId;
var main = 'temp/' + userId + '/templates/' + appId + '/css/main.css';
var color = req.body.color;
var font = req.body.font;
var fontSize = req.body.fontSize;
replaceThemecolor(color);
replaceFont(font);
replaceFontSize(fontSize);
function replaceThemecolor(color) {
fs.readFile(main, 'utf-8', function (err, data) {
var regex =/(\.made-easy-themeColor\s*{[^}]*color\s*:\s*)([^\n;}]+)([\s*;}])/;
var result = data.replace(regex, "$1" + color + "$3");
console.log(color);
fs.writeFile(main, result, 'utf-8', function (err) {
if (err) return console.log(err);
});
});
}
function replaceFont(font) {
fs.readFile(main, 'utf-8', function (err, data) {
var regex =/(\.made-easy-themeFont\s*{[^}]*font-family\s*:\s*)([^\n;}]+)([\s*;}])/;
var result = data.replace(regex, "$1" + font + "$3");
console.log(font);
fs.writeFile(main, result, 'utf-8', function (err) {
if (err) return console.log(err);
});
console.log(result);
})
}
function replaceFontSize(fontSize) {
fs.readFile(main, 'utf-8', function (err, data) {
var regex =/(\.made-easy-themeFontSize\s*{[^}]*font-size\s*:\s*)([^\n;}]+)([\s*;}])/;
var result1 = data.replace(regex, "$1" + fontSize + "em" + "$3");
console.log(fontSize);
fs.writeFile(main, result1, 'utf-8', function (err) {
if (err) return console.log(err);
});
});
}
In here only the last function executes all the time, when I execute them seperately they work well, but the problem arise when all the funtions execute at once. Is it a problem with fs.writeFile function? I want to execute three of this functions together, is there a way to do this? All the functions here work well when they execute seperately.
Your file functions are async. You cannot run them at the same time because they will conflict and one will overwrite the changes of the other. You must run one, then when it finishes, run the other.
Or, even better, only read the file once, the process the data with all your changes, then write it once.
If you were going to run them sequentially, then you would need to pass a callback to each of your functions that is called when it is done so then you know when to start the next function.
But, I think a better solution is to pass an array of replace instructions and just process all of them on one read and write of the file. I will work on a code example for that.
Here's a way to do all the updates in one read/write of the file and uses promises to know when the operation is done:
function updateFile(filename, replacements) {
return new Promise(function(resolve, reject) {
fs.readFile(filename, 'utf-8', function(err, data) {
if (err) {
reject(err);
} else {
// now cycle through and do all the replacements
for (var i = 0; i < replacements.length; i++) {
data = data.replace(replacements[i].regex, replacements[i].replacer);
}
fs.writeFile(filename, data, 'utf-8', function(err) {
if (err) {
reject(err);
} else {
resolve();
}
});
}
});
});
}
updateFile(main, [{regex: /(\.made-easy-themeColor\s*{[^}]*color\s*:\s*)([^\n;}]+)([\s*;}])/, replacer: "$1" + color + "$3"},
{regex: /(\.made-easy-themeFont\s*{[^}]*font-family\s*:\s*)([^\n;}]+)([\s*;}])/, replacer: "$1" + font + "$3"},
{regex: /(\.made-easy-themeFontSize\s*{[^}]*font-size\s*:\s*)([^\n;}]+)([\s*;}])/, replacer: "$1" + fontSize + "em$3"}]).then(function() {
// update done successfully
}, function(err) {
// error
});
With some more work, you could probably abstract out just the keywords from the regular expressions too so you only need to pass in the keywords, but I'll leave that to another time.
And here's a simplified version:
function updateFile(filename, replacements) {
return new Promise(function(resolve, reject) {
fs.readFile(filename, 'utf-8', function(err, data) {
var regex, replaceStr;
if (err) {
reject(err);
} else {
// now cycle through and do all the replacements
for (var i = 0; i < replacements.length; i++) {
regex = new Regex("(\\" + replacements[i].rule + "\\s*{[^}]*" + replacements[i].target + "\\s*:\\s*)([^\\n;}]+)([\\s*;}])");
replaceStr = "$1" + replacements[i].replacer + "$3";
data = data.replace(regex, replaceStr);
}
fs.writeFile(filename, data, 'utf-8', function(err) {
if (err) {
reject(err);
} else {
resolve();
}
});
}
});
});
}
updateFile(main, [
{rule: ".made-easy-themeColor", target: "color", replacer: color},
{rule: ".made-easy-themeFont", target: "font-family", replacer: font},
{rule: ".made-easy-themeFontSize", target: "font-size", replacer: fontSize + "em"}
], function() {
// update done successfully
}, function(err) {
// error
});
And, you don't have to use the promise at all if you don't want to know when it's all done or be able to return errors (which I wouldn't recommend, but the code is simpler).
function updateFile(filename, replacements) {
fs.readFile(filename, 'utf-8', function(err, data) {
var regex, replaceStr;
if (err) { return; }
// now cycle through and do all the replacements
for (var i = 0; i < replacements.length; i++) {
regex = new Regex("(\\" + replacements[i].rule + "\\s*{[^}]*" + replacements[i].target + "\\s*:\\s*)([^\\n;}]+)([\\s*;}])");
replaceStr = "$1" + replacements[i].replacer + "$3";
data = data.replace(regex, replaceStr);
}
fs.writeFile(filename, data, 'utf-8');
});
}
updateFile(main, [
{rule: ".made-easy-themeColor", target: "color", replacer: color},
{rule: ".made-easy-themeFont", target: "font-family", replacer: font},
{rule: ".made-easy-themeFontSize", target: "font-size", replacer: fontSize + "em"}
], function() {
// update done successfully
}, function(err) {
// error
});
Notice how easy it would be to add more replacements. You simply add one more line to the array you pass updateFile().
Node.js is inherently asynchronous. As such, you're doing three read operations in quick succession, and then trying to write to a file that's already file locked, or at the very least, when it was read, did not contain the write changes. I'd use something more like async's series or waterfall methods to solve this.
var async = require("async");
var userId = req.userId;
var appId = req.body.appId;
var main = 'temp/' + userId + '/templates/' + appId + '/css/main.css';
var color = req.body.color;
var font = req.body.font;
var fontSize = req.body.fontSize;
async.series({
replaceThemecolor: function(callback) {
fs.readFile(main, 'utf-8', function(err, data) {
var regex = /(\.made-easy-themeColor\s*{[^}]*color\s*:\s*)([^\n;}]+)([\s*;}])/;
var result = data.replace(regex, "$1" + color + "$3");
console.log(color);
fs.writeFile(main, result, 'utf-8', function(err) {
callback(err);
});
});
},
replaceFont: function(callback) {
fs.readFile(main, 'utf-8', function(err, data) {
var regex = /(\.made-easy-themeFont\s*{[^}]*font-family\s*:\s*)([^\n;}]+)([\s*;}])/;
var result = data.replace(regex, "$1" + font + "$3");
console.log(font);
fs.writeFile(main, result, 'utf-8', function(err) {
callback(err);
});
})
},
replaceFontSize: function(callback) {
fs.readFile(main, 'utf-8', function(err, data) {
var regex = /(\.made-easy-themeFontSize\s*{[^}]*font-size\s*:\s*)([^\n;}]+)([\s*;}])/;
var result1 = data.replace(regex, "$1" + fontSize + "em" + "$3");
console.log(fontSize);
fs.writeFile(main, result1, 'utf-8', function(err) {
callback(err);
});
});
}
}, function(err, results) {
// results is empty, but now the operation is done.
});

Alternative to 'options' in backbone.js 1.1.2

From my view menuitemdetails.js i'am calling options in app.js - itemDetails
My menuitemdetails.js
var MenuItemDetails = Backbone.View.extend({
render: function () {
var markup = '<div>' +
'<h1>' + this.options.name + '</h1>' +
'<p><span class="label">' + this.options.category + '</span></p>' +
'<img src="photos/' + this.options.imagepath + '" class="img-polaroid" />' +
'</div>';
this.$el.html(markup);
return this;
}
});
My app.js
var AppRouter = Backbone.Router.extend({
routes: {
"": "list",
"menu-items/new": "itemForm",
"menu-items/:item": "itemDetails"
},
list: function () {
$('#app').html('List screen');
},
itemDetails: function (item) {
var view = new MenuItemDetails(
{
name: item,
category: 'Entree',
imagepath: 'garden-salad.jpg'
}
);
$('#app').html(view.render().el);
},
itemForm: function () {
$('#app').html('New item form');
}
});
var app = new AppRouter();
$(function () {
Backbone.history.start();
});
Looking forward for an alternative of 'options' because from my view it is not working in backbone.js 1.1.2