I'm setting up a file manager, when right clicking on folder it will popup context menu, before popup am disabling some menu item using ajax. But ajax call is not working when I right clicked on folder which arranged in datatable.
This is my code for popup menu item. Getting error when right clicking on folder which arranged in datatable.
webix.js?1.0.0:22356 Uncaught TypeError: Cannot read property 'row' of undefined"
actions: {
config: function () {
var t = this.config.templateName;
return {
view: "contextmenu",
width: 200,
padding: 0,
autofocus: !1,
css: "webix_fmanager_actions",
template: function (e, i) {
var s = t(e, i);
return "<span class='webix_icon fa-" + e.icon + "'></span>" + s
},
data: "actionsData"
}
},
oninit: function () {
this.getMenu().attachEvent("onBeforeShow", function (t) {
var e = this.getContext();
var folderid = e.id;
$.ajax({
url: "<?php echo base_url()?>/Directorylist/directory_activity",
type: "POST",
datatype: 'json',
async: false,
data: {'folderid':folderid},
success: function (data) {
var json = JSON.parse(data);
permission = [];
permission = json;
},
});
if (permission[0] == 1 && permission[1] == 0 && permission[2] == 0) {
$$(this).disableItem('copy');
$$(this).disableItem('cut');
$$(this).disableItem('paste');
$$(this).disableItem('create');
$$(this).disableItem('remove');
$$(this).disableItem('edit');
$$(this).disableItem('upload');
}
})
}
},
actionsData: {
config: function () {
return [{
id: "copy",
method: "markCopy",
icon: "copy",
value: copy
}, {
id: "cut",
method: "markCut",
icon: "cut",
value: cut
}, {
id: "paste",
method: "pasteFile",
icon: "paste",
value: paste
}, {
$template: "Separator"
}, {
id: "create",
method: "createFolder",
icon: "folder-o",
value: create
}, {
id: "remove",
method: "deleteFile",
icon: "times",
value: remove
}, {
id: "edit",
method: "editFile",
icon: "edit",
value: rename
}, {
id: "upload",
method: "uploadFile",
icon: "upload",
value: upload
}]
}
}
But when I removed these two lines and given direct value, it works fine.
var e = this.getContext();
var folderid = e.id;
above 2 lines removed and added
var folderid = '1';
You lost the scope of this after the second function.
Here's a time proven fix:
oninit: function () {
var self = this;
this.getMenu().attachEvent("onBeforeShow", function (t) {
var e = self.getContext();
var folderid = e.id;
See also: Javascript "this" scope
Or if you are using ES6 then you could use an arrow function:
oninit: function () {
this.getMenu().attachEvent("onBeforeShow", (t) => {
var e = this.getContext();
var folderid = e.id;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Related
How could I disallow a cell in my kendo grid to be 'blank' or 'empty' rather... How could I replace all blank or empties with a 0..
I have a save button grabbing the values from my kendo grid such as below: Everything works fine EXCEPT, it is completely omitting my empty cells.. I want to keep them, just have a 0 value on them...
Save button: want to keep the empties with simply a 0 or N/A..
$('.' + chs).on('click', '#saveChanges', function(e) {
which = $(frm).attr("class");
let dataSource = $("#grid").data("kendoGrid").dataSource,
data = dataSource.data(),
changedModels = [];
if(dataSource.hasChanges) { // only saves cells/row that have been edited/changed, need to keep this
for(var i = 0; i < data.length; i++) {
if(data[i].dirty) { changedModels.push(data[i].toJSON()) }
}
}
let ds = JSON.stringify(changedModels);
$.ajax({
type: "POST",
url: "saveGrid",
dataType: "json",
data: {
id: which,
data: ds
},
success: function(result) {
console.log('yy');
},
error: function(result) {
console.log('nn');
}
});
});
This is my kendo grid initialized:
let dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "/popGrid?id=" + which,
dataType: "json"
},
},
batch: true,
schema: {
data: "data",
model: {
id: id,
}
},
});
console.log(id);
$("#grid").kendoGrid({
dataSource: dataSource,
height: 600,
sortable: true,
autoBind: true,
nullable: true,
editable: {
createAt: "top"
},
change: function(e) {
let grid = $("#grid").data("kendoGrid");
let selectedItem = grid.dataItem(grid.select());
let val = selectedItem.id;
console.log(val);
},
selectable: "row",
toolbar: [
{ name: "create" },
{ name: "cancel" }
],
paging: false,
});
I can't understand if you want to POST empty fields as "0" or if you want to SHOW them in the grid as "0", when null or "empty".
But I guess you're talking about posting it as "0". In that case I think you have to do that before posting:
let fieldName = 'myCell';
if (data[i].dirty) {
if (!data[i].hasOwnProperty(fieldName) || // In case field is not present on data
!data[i][fieldName]) { // In case field value is null/undefined/0/false/empty string
data[i][fieldName] = 0;
}
changedModels.push(data[i].toJSON());
}
For multiple field check:
let fieldNames = ['fieldA', 'fieldB', ...],
checkFields = (item) => {
fieldNames.forEach(field => {
if (!item.hasOwnProperty(field) || // In case field is not present on data
!item[field]) { // In case field value is null/undefined/0/false/empty string
item[field] = 0;
}
});
};
Or you can do the same before data is bound to the grid with dataSource.schema.parse.
There are a some video links on the page for playing video by click:
<div class="play" id="27" data-width="850" data-height="470" data-fancybox-href="https://www.youtube.com/embed/zqO7epdsSic"></div>
When I click on link then callback beforeLoad: function () {} calls function getVideo(){} that return title in global variable. In callback this title is appointed by the current window FancyBox.
So, sometimes this title is not displayed. How I can improve this code and fix?
Code JS:
$(".play").fancybox({
type: 'iframe',
maxWidth: "90%",
padding: 0,
autoCenter: false,
scrolling: 'no',
fitToView: false,
beforeLoad: function () {
var id = $(this.element).attr("id");
var info = '?theme=dark&color=white&autohide=1&rel=0&iv_load_policy=3&modestbranding=1&enablejsapi=1&origin=http://whoismed.com&showinfo=0&autoplay=1';
this.href = this.href + info;
getVideo(id, this, function (response, th) {
th.title = th.title + response.template;
th.width = $(th.element).data("width");
th.height = $(th.element).data("height");
});
},
afterLoad: function () {
//changeURL(_videoInfo.info.VideoCode+'#'+_videoInfo.info.idVideo, _videoInfo.info.VideoName, _videoInfo.info);
},
helpers: {
overlay: {
locked: false
},
title: {
type: 'inside' // to append the html
}
}
});
Function GetVideo();
function getVideo(id, th, callback) {
var th = th;
$.ajax({
type: "POST",
dataType: "json",
data: {id: id},
url: '/comments/GetHash',
success: function (result) {
info = result.info[0];
hash = result.hash;
_videoInfo.info = info;
_videoInfo.template = parseTpl(userInfoVideo, {
'name': info.DetailToUsersName,
'id_user': info.idDetailToUsers,
'time': info.VideoTime,
'desc': info.VideoDescription,
'id': info.idVideo,
'title': info.VideoName,
'category': info.SpecializationName,
'category_id': info.idSpec,
'likes': result.statistic,
'form': result.formComment,
'comments': result.comments,
'user_photo': (info.DetailToUsersPhoto == null) ? '/public/images/notphoto.png' : '/' + info.DetailToUsersPhoto
});
callback(_videoInfo, th);
}
});
}
I have two functions that make two combobox with jqwidgets libraries. two functions are mostly like each other. I call them in $(document).ready(function (), but first function is work well and the second not even call. I put the codes those in one function, but the second part never run.
function f1() {
var url2 = "/autosuggest/JsonOrigins.aspx";
var source2 = {
datatype: "json",
datafields: [{
name: 'id'
}, {
name: 'name'
}],
url: url2,
async: false
};
var dataAdapter2 = new $.jqx.dataAdapter(source2);
// Create a jqxComboBox
$("#originsjqxWidget").jqxComboBox({
source: dataAdapter2,
multiSelect: true,
displayMember: "name",
valueMember: "id",
width: 145
});
$("#arrow").jqxButton({});
$("#arrow").click(function () {
$("#originsjqxWidget").jqxComboBox({
showArrow: false
});
});
$("#originsjqxWidget").on('change', function (event) {
var items = $("#originsjqxWidget").jqxComboBox('getSelectedItems');
var selectedItems = "Selected Items: ";
$.each(items, function (index) {
selectedItems += this.label;
if (items.length - 1 != index) {
selectedItems += ", ";
}
});
$("#log").text(selectedItems);
});
};
function f2() {
var url = "/autosuggest/JsonTag.aspx";
var source = {
datatype: "json",
datafields: [{
name: 'id'
}, {
name: 'name'
}],
url: url,
async: false
};
var dataAdapter = new $.jqx.dataAdapter(source);
$("#categoriesjqxWidget").jqxComboBox({
source: dataAdapter,
multiSelect: true,
displayMember: "name",
valueMember: "id",
width: 145
});
$("#arrow").jqxButton({});
$("#arrow").click(function () {
$("#jqxComboBox").jqxComboBox({
showArrow: false
});
});
$("#categoriesjqxWidget").on('change', function (event) {
var items = $("#categoriesjqxWidget").jqxComboBox('getSelectedItems');
var selectedItems = "Selected Items: ";
$.each(items, function (index) {
selectedItems += this.label;
if (items.length - 1 != index) {
selectedItems += ", ";
}
});
$("#log").text(selectedItems);
});
}
$(document).ready(function () {
f1();
f2();
});
Remove the ; after your first function.
try this
var source2 = {
datatype: "json";
datafields: [{
name: 'id'
}, {
name: 'name'
}],
url: url2,
async: false
};
I think you have an extra ; at the end of function f1
function f1(){
...
if (items.length - 1 != index) {
selectedItems += ", ";
}
});
$("#log").text(selectedItems);
});
};
I found some code on GitHub (https://github.com/RallyCommunity/TagCloud) for displaying a TagCloud in Rally. Conceptually it looks great but I cannot seem to get it to work and wondered if there were any Rally JavaScript experts out there who could take a quick look.
I modified it slightly as the URL for the Analytics was incorrect (according to the docs) and the API's were hard coded to depreciated versions so I updated those.
I'm not a JavaScript expert. When I run this it doesn't find any Tags against stories.
When I run this in Chrome debugging mode I can take the URL and execute it in my browser but it also does not come back with any Tags. It comes back with a full result response from Analytics, but has no tags and I know there are tags against stories in the selected project.
Any ideas from anyone?
<!DOCTYPE html>
<html>
<head>
<title>TagCloud</title>
<script type="text/javascript" src="/apps/2.0p/sdk.js"></script>
<script type="text/javascript">
Rally.onReady(function() {
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
layout: 'border',
items: [
{
title: 'Tag Cloud',
xtype: 'panel',
itemId: 'cloud',
region: 'west',
width: '30%',
collapsible: true,
bodyStyle: 'padding:15px',
listeners: { 'afterRender': function(el) { setTimeout(function() { el.setLoading(); }, 500);}} // needs a little delay
},
{
title: '<<< Select a tag from the Tag Cloud',
xtype: 'panel',
itemId: 'grid',
region: 'center',
width: '70%',
collapsible: false
}
],
tagMap : [],
maxFont : 24, // largest desired font size
minFont : 8, // and smallest
_renderTag : function renderHandler(tagLabel) {
tagLabel.getEl().on('click',this._tagSelected, this);
},
// does the actual building of the cloud from 'tagMap'
_buildCloud: function(app, response) {
//title: '<<< Select a tag from the Tag Cloud - Building',
var i, tag;
for (i=0;i<response.Results.length;i++) {
tag = response.Results[i];
if(typeof app.tagMap[tag.ObjectID] !== "undefined") {
app.tagMap[tag.ObjectID].Name = tag._refObjectName;
}
}
if(response.StartIndex+response.PageSize < response.TotalResultCount) {
app._queryForTagNames(response.StartIndex+response.PageSize, app, app._buildCloud);
} else {
if(app.tagMap.length === 0) {
tag = new Ext.form.Label({
id: 'tagNone',
text: ' No tagged Stories found '
});
app.down('#cloud').add(tag);
} else {
var minFrequency = Number.MAX_VALUE;
var maxFrequency = Number.MIN_VALUE;
var tuples = [];
for (var x in app.tagMap) {
if (app.tagMap.hasOwnProperty(x)) {
tuples.push([x, app.tagMap[x]]);
if(app.tagMap[x].count > maxFrequency) {
maxFrequency = app.tagMap[x].count;
}
if(app.tagMap[x].count < minFrequency) {
minFrequency = app.tagMap[x].count;
}
}
}
tuples.sort(function(a,b) { a = a[1]; b = b[1]; return a.Name > b.Name ? 1 : a.Name < b.Name ? -1 : 0 ;});
for (i = 0; i < tuples.length; i++) {
var ftsize = ((tuples[i][1].count-minFrequency)*(app.maxFont-app.minFont) / (maxFrequency-minFrequency)) + app.minFont;
tag = new Ext.form.Label({
id: 'tag'+tuples[i][0],
text: ' ' + tuples[i][1].Name + ' ',
overCls: 'link',
style:"font-size: "+ftsize+"pt;",
listeners: { scope: app, render: app._renderTag }
});
app.down('#cloud').add(tag);
}
}
app.getComponent('cloud').setLoading(false);
}
},
// collects the _queryForTags responses and calls _queryForTagNames when it has them all
_buildTagMap: function(app, response) {
for (var i=0;i<response.Results.length;i++) {
var ent = response.Results[i];
for (var j=0; j < ent.Tags.length; j++) {
var tag = ent.Tags[j];
var mapent = app.tagMap[tag];
if(typeof mapent === "undefined") {
mapent = { count: 1 };
} else {
mapent.count++;
}
app.tagMap[tag] = mapent;
}
}
if(response.StartIndex+response.PageSize < response.TotalResultCount) {
app._queryForTags(response.StartIndex+response.PageSize, app, app._buildTagMap);
} else {
app._queryForTagNames(0, app, app._buildCloud);
}
},
// get a list of the tags from the Lookback API, iterating if necessary (see _buildTagMap)
_queryForTags: function(start, app, callback) {
var params = {
find: "{'Tags':{'$exists':true}, '__At':'current', '_Type':'HierarchicalRequirement', '_ProjectHierarchy':"+ this.getContext().getProject().ObjectID +" }",
fields: "['Tags']",
pagesize: 20000,
start: start
};
Ext.Ajax.request({
url: 'https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/'+ this.context.getWorkspace().ObjectID + '/artifact/snapshot/query.js',
method: 'GET',
params: params,
withCredentials: true,
success: function(response){
var text = response.responseText;
var json = Ext.JSON.decode(text);
callback(app, json);
}
});
},
// once all the tags have been collected, get a list of the tag names from the WSAPI, iterating if necessary (see _buildCloud)
_queryForTagNames: function(start, app, callback) {
Ext.Ajax.request({
url: 'https://rally1.rallydev.com/slm/webservice/1.41/tag.js',
method: 'GET',
params: { fetch: "ObjectID", pagesize: 200, "start": start},
withCredentials: true,
success: function(response){
callback(app, Ext.JSON.decode(response.responseText).QueryResult);
}
});
},
_queryForStories: function(tagOid) {
Ext.create('Rally.data.WsapiDataStore', {
model: 'UserStory',
autoLoad: true,
fetch: ['Rank', 'FormattedID', 'Name', 'ScheduleState'],
filters: [{
property:'Tags',
operator: '=',
value: "tag/" + tagOid
}],
sorters: [{
property: 'Rank',
direction: 'ASC'
}],
listeners: {
load: this._onDataLoaded,
scope: this
}
});
},
_tagSelected: function(app, elem) {
this.getComponent('grid').setLoading();
this._queryForStories(elem.id.substring(3)); // cheesy, id is "tag"+tagOid, we need the oid
this.tagName = elem.innerText;
},
_onDataLoaded: function(store, data) {
var records = [], rankIndex = 1;
Ext.Array.each(data, function(record) {
records.push({
Ranking: rankIndex,
FormattedID: record.get('FormattedID'),
Name: record.get('Name'),
State: record.get('ScheduleState')
});
rankIndex++;
});
var customStore = Ext.create('Rally.data.custom.Store', {
data: records,
pageSize: 25
});
if(!this.grid) {
this.grid = this.down('#grid').add({
xtype: 'rallygrid',
store: customStore,
columnCfgs: [
{ text: 'Ranking', dataIndex: 'Ranking' },
{ text: 'ID', dataIndex: 'FormattedID' },
{ text: 'Name', dataIndex: 'Name', flex: 1 },
{ text: 'State', dataIndex: 'State' }
]
});
} else {
this.grid.reconfigure(customStore);
}
this.getComponent('grid').setTitle('Stories tagged: ' + this.tagName);
this.getComponent('grid').setLoading(false);
},
launch: function() {
this._queryForTags(0, this, this._buildTagMap);
}
});
Rally.launchApp('CustomApp', {
name: 'TagCloud'
});
});
</script>
<style type="text/css">
.app {
}
.link {
color: #066792;
cursor: pointer;
} </style>
</head>
<body></body>
</html>
The code was out-of-date with respect to the most-recent LBAPI changes - specifically the use of _Type vs _TypeHierarchy and of course, the url, as you'd already discovered. Please pick up the changes and give it a whirl.
I need to set an array of data after initializing select2. So I want to make something like this:
var select = $('#select').select2({});
select.data([
{id: 1, text: 'value1'},
{id: 1, text: 'value1'}
]);
But I get the following error:
Option 'data' is not allowed for Select2 when attached to a element.;
My HTML:
<select id="select" class="chzn-select"></select>
What should I use instead of a select element?
I need to set the source of items for search
In onload:
$.each(data, function(index, value) {
$('#selectId').append(
'<option value="' + data[index].id + '">' + data[index].value1 + '</option>'
);
});
Make an <input type="hidden"> element and bind select2 to that. Using .select2 on a regular select box doesn't let you play with the data, it just mostly gives you the UI and post-selection methods.
Source:
Select2 Documentation
Source: https://select2.org/programmatic-control/add-select-clear-items
Add item:
var data = {
id: 1,
text: 'Barn owl'
};
var newOption = new Option(data.text, data.id, false, false);
$('#mySelect2').append(newOption).trigger('change');
Clear items:
$('#mySelect2').val(null).trigger('change');
For v4 you'll have to destroy and reconstruct select2 with updated data. Check https://github.com/select2/select2/issues/2830
I've recently had the scenario where changing one select2 object alters the contents of a second (parent - child groupings effectively). I used an ajax call to retrieve a new set of Json data, which was then picked up by the second select2 object. I've included the code below:
$("#group").on('change', function () {
var uri = "/Url/RetrieveNewResults";
$.ajax({
url: uri,
data: {
format: 'json',
Id: $("#group :selected").val()
},
type: "POST",
success: function (data) {
$("#groupchild").html('');
$("#groupchild").select2({
data: data,
theme: 'bootstrap',
placeholder: "Select a Type"
});
},
error: function () {
console.log("Error")
}
});
});
I found that I had to include the $("#groupchild").html('') in order to clear out the previous set of data in the second select2. Hope this helps.
You can rerender and trigger the select2
render select2
$('.select2').select2({
placeholder: 'Slect value',
allowClear: true
});
after need to change the data data
let dataChange = [
{
id: 0,
text: 'enhancement'
},
{
id: 1,
text: 'bug'
},
{
id: 2,
text: 'duplicate'
},
{
id: 3,
text: 'invalid'
},
{
id: 4,
text: 'wontfix'
}
];
rerender the select2
$('.select2').select2('destroy');
$('.select2').empty();
$('.select2').select2({
placeholder: 'Slect value',
allowClear: true,
data: dataChange
});
trigger select2
$('.select2').trigger('change');
Hope this is the answer for you :3
Here's what I did.
1. Extend select2
Select2.prototype.setAjax = function (ajaxOptions)
{
// Set the new ajax properties
var oAjaxOpts = this.options.get('ajax');
if (oAjaxOpts != undefined && oAjaxOpts != null)
{
for (var sKey in ajaxOptions)
{
oAjaxOpts[sKey] = ajaxOptions[sKey];
}
}
var DataAdapter = this.options.get('dataAdapter');
this.dataAdapter = new DataAdapter(this.$element, this.options);
}
2. Initialize as usual (for example --- yours could be different)
jHtmlFrag.select2({
dropdownParent: $(oData.jDiv),
placeholder: "Select Option",
allowClear: true,
minimumInputLength: 2,
ajax: {
url: "",
method: "POST",
dataType: 'json',
delay: 250,
processResults: function (oResults, params)
{
let page = params.page || 1;
// console.log(oResults, (params.page * 10));
return {
results: oResults.data,
pagination: {
more: (page * 10) < oResults.recordsFiltered
}
};
}
}
}).val(null).trigger('change');
3. Set Ajax options dynamically when you feel like by calling the new extension func
jCombo.select2('setAjax', {
url: sUrl,
data: function (params)
{
let query = {
search: params.term,
type: params._type,
page: params.page || 1,
}
return query;
},
});