On the slickgrid view I have to add the button to do file upload. I have added that button using a custom formater. But I couldnt add the onchange event handler to capture the file. Could anyone have any idea of how we can add the onchange listener to the cell.?
In the formatter display just the name of the file or something like that. To achieve your goal you need to write custom editor which implements isValueChanged method. You can modify this or any other editor taken from:
https://github.com/mleibman/SlickGrid/blob/master/slick.editors.js
function myCustomEditor(args) {
var $input;
var defaultValue;
var scope = this;
this.init = function () {
$input = $("<INPUT type=text class='editor-text' />")
.appendTo(args.container)
.bind("keydown.nav", function (e) {
if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
e.stopImmediatePropagation();
}
})
.focus()
.select();
};
this.destroy = function () {
$input.remove();
};
this.focus = function () {
$input.focus();
};
this.getValue = function () {
return $input.val();
};
this.setValue = function (val) {
$input.val(val);
};
this.loadValue = function (item) {
defaultValue = item[args.column.field] || "";
$input.val(defaultValue);
$input[0].defaultValue = defaultValue;
$input.select();
};
this.serializeValue = function () {
return $input.val();
};
this.applyValue = function (item, state) {
item[args.column.field] = state;
};
this.isValueChanged = function () {
return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
};
this.validate = function () {
if (args.column.validator) {
var validationResults = args.column.validator($input.val());
if (!validationResults.valid) {
return validationResults;
}
}
return {
valid: true,
msg: null
};
};
this.init();
}
the editor can be then assigned in your columns object:
var columns = [
{id: "title", name: "Title", field: "title", width: 70, minWidth: 50, cssClass: "cell-title", sortable: true, editor: myCustomEditor},
];
Related
when I make this test, I got the following error: "Error: Syntax error, unrecognized expression: unsupported pseudo: invalid".
I don't know what is the problem on my code. Can someone show me ? Thank you !
jest.disableAutomock();
jest.unmock('../resources/assets/js/testcomponents/InputText.js');
jest.dontMock('react-bootstrap');
_ = require('lodash');
$ = require('jquery');
var React = require('react'),
InputText = require('../resources/assets/js/testcomponents/InputText.js').InputTextEditable,
TestUtils = require('react-addons-test-utils'),
ReactDOM = require('react-dom');
describe('InputText', function () {
var InputElement = TestUtils.renderIntoDocument(
<InputText
area={false}
//evts={{onChange: handleChange}}
attributes={{
label:'Test Input Isole',
name:'InputTextArea',
value: '',
wrapperClassName: 'col-md-4',
labelClassName: 'col-md-2',
groupClassName: 'row'
}}
//ref="InputField"
editable={true}/>);
var DomElement = ReactDOM.findDOMNode(InputElement);
//var inputV = ReactDOM.findDOMNode(InputElement.refs.InputField);
var input = DomElement.getElementsByTagName('input')[0];
it('updates input value on key press', function () {
TestUtils.Simulate.change(
DomElement.getElementsByTagName('input')[0],
{target: {value: 'a'}}
);
expect(input.getAttribute('value')).toEqual('a');
});
EDIT : This is my component
var InputText = React.createClass({
mixins: [MixinInputValue],
propTypes: {
attributes: React.PropTypes.object,
evts: React.PropTypes.object,
gestMod: React.PropTypes.bool,
area: React.PropTypes.bool,
validator: React.PropTypes.func
},
getDefaultProps: function () {
return {
attributes: {},
evts: {},
gestMod: true,
area: false,
validator: function (val, props, state) {
if (val.length == 0 && typeof(props.attributes.required) != 'undefined' && props.attributes.required) {
return {isValid: false, style: 'default', tooltip: ''};
}
else if (val.length == 0) {
return {isValid: true, style: 'default', tooltip: ''};
}
else {
return {isValid: true, style: 'success', tooltip: ''};
}
}
};
},
render: function () {
console.log('passerender');
var attrs = this.generateAttributes();
var type = this.props.area ? "textarea" : "text";
return (
<Input
className={this.props.menuClassName}
type={type}
{...attrs}
{...this.props.evts}
className={this.props.menuClassName}
onChange = {this.handleChange}
onBlur = {this.handleBlur}
value={this.state.value}
ref = "InputField"
hasFeedback
/>
);
}
});
2ND EDIT=
Ok I guess the issue came from this file
getStateAttributes: function (val, DOM) {
var attrs = {};
attrs = _.extend((this.props.gestMod ? {'data-gest-mod': this.props.gestMod} : {}), attrs);
var validation = this.props.validator(val, this.props, this.state, DOM);
var html5Validity = true;
if (DOM !== undefined) {
console.log("petit message", DOM.outerHTML);
var temp = $(DOM.outerHTML);
temp.find('div');
html5Validity = DOM.querySelectorAll(':invalid').length == 0;
// html5Validity = temp.find(':invalid').length == 0;
}
attrs = _.extend({'data-valid': validation.isValid && html5Validity}, attrs);
// 4. AJOUT DU STYLE REACTB
var style = {'bsStyle': (!Validator.matches(validation.style, 'success|warning|error', 'i') ? undefined : validation.style)};
if (!html5Validity) {
style = {'bsStyle': 'error'};
}
if (validation.tooltip.length > 0) {
style.help = validation.tooltip;
}
attrs = _.extend(style, attrs);
return attrs;
},
This code was the problem:
var html5Validity = true;
if (DOM !== undefined) {
console.log("petit message", DOM.outerHTML);
var temp = $(DOM.outerHTML);
temp.find('div');
html5Validity = DOM.querySelectorAll(':invalid').length == 0;
// html5Validity = temp.find(':invalid').length == 0;
}
attrs = _.extend({'data-valid': validation.isValid && html5Validity}, attrs);
I put a try/catch on this to solve my problem and its work ! :
var html5Validity = true;
if (DOM !== undefined) {
try {
html5Validity = $(DOM).find(':invalid').length == 0;
console.log('pass');
} catch (e) {
console.log('catch');
html5Validity = true;
}
}
attrs = _.extend({'data-valid': validation.isValid && html5Validity}, attrs);
In input of function is an object who has this structure:
{
tag: 'a', //type of html object
content: "blabal", //inner content
attr: {
href: "vk.com",
id: 'someId'
},
events: {
click: 'alert(this.href)',
focus: 'this.className="active"'
},
style: {
width:"100px"
}
}
It describes an HTML element. It has to return an HTML element with specified properties. How to parse it? I have something like this:
elemen={
tag:'a',
content:"blabal",
attr:{
href:"vk.com",
id:'someId'
},
events:{
click:'alert(this.href)',
focus:'this.className="active"'
},
style:{
width:"100px"
}
};
console.log(elemen.tag);
var node = document.createElement(elemen.tag);
node.innerHTML= elemen.content;
for(var prop in elemen.events){
var fun =new Function(elemen.events[prop]);
console.log(fun);
node.bind(prop, fun);
// divv.bind(prop, fun);
}
Use addEventListener to register events on Element and .bind(thisArg) to have specified argument as this-context
var elemen = {
tag: 'a',
content: "blabal",
attr: {
href: "vk.com",
id: 'someId'
},
events: {
click: 'alert(this.href)',
focus: 'this.className="active"'
}
};
var node = document.createElement(elemen.tag);
node.innerHTML = elemen.content;
for (var attr in elemen.attr) {
node.setAttribute(attr, elemen.attr[attr]);
}
for (var prop in elemen.events) {
node.addEventListener(prop, new Function(elemen.events[prop]).bind(node));
}
document.body.appendChild(node);
.active {
color: red;
}
Using only javascript
var _createElem = document.createElement(""+_elem.tag+"");
_createElem.innerHTML = _elem.content;
//set attributes
for(var keys in _elem.attr){
_createElem.setAttribute(''+keys+'',_elem.attr[keys])
}
//set style
for(var keys in _elem.style){
_createElem.setAttribute(''+keys+'',_elem.style[keys])
}
//set events
for(var keys in _elem.events){
_createElem.setAttribute('on'+keys,_elem.events[keys])
}
document.getElementById("demoDiv").appendChild(_createElem)
Note: The elem has got both onclick & href , you may need to return true/false as per your requirement
Use the following function:
const objectToHTML = function(obj) {
const element = document.createElement(obj.tag)
element.innerHTML = obj.content
for (const name in obj.attr) {
const value = obj.attr[name]
element.setAttribute(name, value)
}
for (const name in obj.events) {
const listener = new Function(obj.events[name]).bind(element)
element.addEventListener(name, listener)
}
for (const property in obj.style) {
const value = obj.style[property]
element.style[property] = value
}
return element
}
To create an event listener from string, you have to convert it to function using the Function constructor, bind context to it using Function.prototype.bind() (otherwise the function would be executed with window as context), and finally, use element.addEventListener().
The rest is rather obvious.
You can use this function like that:
const element = objectToHTML({
tag: 'a',
content: "blabal",
attr: {
href: "vk.com",
id: 'someId'
},
events: {
click: 'alert(this.href)',
focus: 'this.className="active"'
},
style: {
width: "100px"
}
})
document.body.appendChild(element)
See demo:
const objectToHTML = function(obj) {
const element = document.createElement(obj.tag)
element.innerHTML = obj.content
for (const name in obj.attr) {
const value = obj.attr[name]
element.setAttribute(name, value)
}
for (const name in obj.events) {
const listener = new Function(obj.events[name]).bind(element)
element.addEventListener(name, listener)
}
for (const property in obj.style) {
const value = obj.style[property]
element.style[property] = value
}
return element
}
const element = objectToHTML({
tag: 'a',
content: "blabal",
attr: {
href: "vk.com",
id: 'someId'
},
events: {
click: 'alert(this.href)',
focus: 'this.className="active"'
},
style: {
width: "100px"
}
})
document.body.appendChild(element)
I recommend this form, is more adaptable.
window.onload = function() {
function init_() {
function action__(type, element, convert, a) {
if (type == "function") {
if (convert.create[a] != null) {
try {
var new_ = convert.create[a](element[a]);
} catch (rrr) {
rrr = (rrr.toString());
if (rrr.indexOf('2 arguments') != -1 && Object.keys(element[a]).length != 0) {
for (v in element[a]) {
convert.create[v] = element[a][v];
var new_ = convert.create;
}
};
}
convert['create'] = new_;
}
};
if (type == "object") {
for (f in element[a]) {
convert.create[a][f] = element[a][f];
}
}
if (type == "string" && a != "events") {
convert.create[a] = (element[a]);
} else if (type == "string" && a == "events") {
for (ev in element[a]) {
var type = convert.detectType(convert.create, ev);
if (type == "function") {
convert.create.addEventListener(ev, new Function(element[a][ev]));
}
};
};
return convert.create;
};
function createElement(elements) {
var finished = [];
if (typeof elements.tagName == "undefined" && !elements.length) {
elements = [elements];
}
for (r = 0; r < elements.length; r++) {
var element = elements[r];
if (element) {
var convert = {
create: document,
detectType: function(element, attribute) {
var type = "string";
if (typeof element[attribute] != "undefined") {
type = typeof element[attribute];
};
return type;
},
add: function(new_) {
if (new_ && new_ != "undefined") {
this.create = new_;
}
}
};
for (a in element) {
var type = convert.detectType(convert.create, a);
var returner = action__(type, element, convert, a);
convert.add(returner);
}
finished.push(convert.create);
};
}
return (finished);
};
var minifi_function = init_.toString();
var elements = [{
createElement: 'a',
innerHTML: "blabal",
setAttribute: {
href: "vk.com",
id: 'someId',
style: "height:200px;"
},
events: {
click: 'alert(this.href)',
focus: 'this.className="active"'
},
style: {
width: "100px"
}
}, {
createElement: 'div',
innerHTML: "see my content",
setAttribute: {
['data-link']: "vk.com",
id: 'someId2',
style: "height:200px;background:red;"
},
events: {
click: 'prompt("Copy",' + minifi_function + ')',
focus: 'this.className="activediv"'
},
style: {
width: "100px"
}
}];
var elementos = createElement(elements);
console.log(elementos);
for (p = 0; p < elementos.length; p++) {
document.body.appendChild(elementos[p]);
}
}
init_();
}
We use jQuery DataTables plug in across our app and it works pretty well. However we're encountering an error when we try load up the plug in with mock data (services aren't ready yet) in a modal on the page. We get the following errors ( the 2nd one happens after you click the link again to open the modal)
TypeError: d[i] is undefined
TypeError: b.nTableWrapper is null
The code looks correct, so I can't figure it out. Anyone with experience on this error ? We built the table map to correspond with the sample data nodes - and we've also tried maps with current working ones to no avail. (They are separated by purpose).
I've added the HTML in the fiddle. But basically it's just a simple table with the ID - the other datatables across the site work just fine with the same structure. Just stumped.
var sampleData = [{
"approvable": true,
"id": 4938,
"order_number": "3948948392893",
"order_template": "AJHSFJKHAS-SDJAS",
"size": "45mb",
"size_sort": 4500,
"ad_type": "testadtype",
"production_status": "yep!"
}
];
var makeCampaignApproveModal = function () {
var $approveParams;
var $approveComments = $('#approveComments');
var $approveCampaignForm = $('#approveCampaignForm');
var $campaignApprove = $('#campaignApprove');
var $approveCampaignHeader = $campaignApprove.children('h3');
var $ratingStars = $('#ratingStars');
var $ratingStar = $('.ratingStar');
var $ratingApproveCampaign = $('#ratingApproveCampaign');
var $ratingCancelCampaign = $('#ratingCancelCampaign');
var init = function () {
makeCampaignBulkOrders(sampleData);
//bindings
$ratingStar.mouseover(function (e) {
var $this = $(this);
$this.prevAll().addClass('active');
$this.nextAll().addClass('inactive');
});
$ratingStar.mouseout(function (e) {
var $this = $(this);
$this.prevAll().removeClass('active');
$this.nextAll().removeClass('inactive');
});
$ratingStar.on("click", function (e) {
e.preventDefault();
var $this = $(this);
//style prevs
$this.addClass('selected');
$this.prevAll().addClass('selected');
$this.nextAll().removeClass('selected');
$ratingStars.data('rating', $this.attr('rel'));
});
$ratingApproveCampaign.on("click", function (e) {
e.preventDefault();
var approveHandler = Portal.Details.synchronousRatingHandler;
utils.makeProxyCall((actionQueryPath + '/proof/approve'), approveHandler, Portal.Details.proofReturnE);
callInProgress();
return false;
});
$ratingCancelCampaign.on("click", function (e) {
e.preventDefault();
$campaignApprove.modality('close');
});
$campaignApprove.addClass('initted');
}; //init
if (!$campaignApprove.hasClass('initted')) {
init();
}
aep.utils.setupForm($approveCampaignForm, true, false);
$ratingStars.data();
$ratingApproveCampaign.text($l(2019));
$approveCampaignHeader.html($l(2018) + '<span class="actionModalObjectNumber"></span>');
updateModalHeader($campaignApprove);
var curRating = actionDetails['rating'];
$ratingStar.each(function () {
var $this = $(this);
if ($this.attr('rel') <= curRating) {
$this.addClass('selected');
} else {
$this.removeClass('selected');
}
});
$ratingStars.data('rating', curRating);
$campaignApprove.modality(modalConfig);
};
var makeCampaignBulkOrders = function (coData) {
var $campaignBulkOrders = $('#campaignBulkOrders');
var $campaignBulkOrdersTable = $('#bulk-ords-table');
var DTConfig = {
'bDestroy': true,
'bAutoWidth': true,
'iDisplayLength': -1,
'bPaginate': false,
'sScrollY': '200px',
'bScrollCollapse': true,
'oLanguage': {
'sSearch': $l(1024)
}
};
var coData = sampleData || [];
var coMap = getTableMapBulkOrders();
var cDTConfig = DTConfig;
cDTConfig['aaData'] = coData;
cDTConfig['aaColumns'] = coMap;
cDTConfig['aaSorting'] = [[1, 'desc']];
cDTConfig['sScrollY'] = '';
cDTConfig['bScrollCollapse'] = false;
$campaignBulkOrders.find('.tableLoading').hide();
$campaignBulkOrdersTable.dataTable(cDTConfig).fnDraw();
cDTConfig['aaSorting'] = [];
};
var getTableMapBulkOrders = function () {
return [{
oid: 'approvable',
'sTitle': '',
'mDataProp': function (source, type, val) {
if (type == "display") {
return '<input type="checkbox" class="campaign-order-approval" rel="' + source.id + '" />';
}
return source.id;
},
'sClass': 'checkbox'
},
{
oid: 'order_number',
'sClass': 'order_number',
'mDataProp': function (source, type, val) {
var ordNumber = '<a class="detailsLink" href="/portal/details/#orders/' + source.id + '">' + source.order_number + '</a>';
if (type == 'display') {
return ordNumber;
}
return source['order_number'];
},
'sTitle': $l(2089),
'sClass': 'orderNumber'
},
{
oid: 'order_template',
'mDataProp': 'order_template',
'sTitle': $l(2048),
'sClass': 'order_template'
}, {
oid: 'fileSize',
'mDataProp': function (source, type, val) {
if (type == "sort") {
return source['size_sort'];
}
return source['size'];
},
'sTitle': $l(2099),
"sType": "numeric",
'sClass': 'file_size'
},
{
oid: 'ad_type',
'mDataProp': 'ad_type',
'sTitle': $l(2045),
'sClass': 'ad_type'
}, {
oid: 'production_status',
'mDataProp': 'production_status',
'sTitle': $l(2097),
'sClass': 'production_status'
}
];
};
jsfiddle is over here
i have phpbb 3.1 forum.
i have a- jquery.collapse.js.
i want that the defult will be collapsed insted of open.
wheat parameter do i need to change to do it?
and can o make it that in default only 1 is open and not close?
the default will be the 1st category to be open, and when i open the next one, the open one will close automatically.
the code-
(function($, exports) {
// Constructor
function Collapse (el, options) {
options = options || {};
var _this = this,
query = options.query || "> :even";
$.extend(_this, {
$el: el,
options : options,
sections: [],
isAccordion : options.accordion || false,
db : options.persist ? jQueryCollapseStorage(el.get(0).id) : false
});
// Figure out what sections are open if storage is used
_this.states = _this.db ? _this.db.read() : [];
// For every pair of elements in given
// element, create a section
_this.$el.find(query).each(function() {
new jQueryCollapseSection($(this), _this);
});
// Capute ALL the clicks!
(function(scope) {
_this.$el.on("click", "[data-collapse-summary] " + (scope.options.clickQuery || ""),
$.proxy(_this.handleClick, scope));
_this.$el.bind("toggle close open",
$.proxy(_this.handleEvent, scope));
}(_this));
}
Collapse.prototype = {
handleClick: function(e, state) {
e.preventDefault();
state = state || "toggle";
var sections = this.sections,
l = sections.length;
while(l--) {
if($.contains(sections[l].$summary[0], e.target)) {
sections[l][state]();
break;
}
}
},
handleEvent: function(e) {
if(e.target == this.$el.get(0)) return this[e.type]();
this.handleClick(e, e.type);
},
open: function(eq) {
this._change("open", eq);
},
close: function(eq) {
this._change("close", eq);
},
toggle: function(eq) {
this._change("toggle", eq);
},
_change: function(action, eq) {
if(isFinite(eq)) return this.sections[eq][action]();
$.each(this.sections, function(i, section) {
section[action]();
});
}
};
// Section constructor
function Section($el, parent) {
if(!parent.options.clickQuery) $el.wrapInner('<a href="#"/>');
$.extend(this, {
isOpen : false,
$summary : $el.attr("data-collapse-summary",""),
$details : $el.next(),
options: parent.options,
parent: parent
});
parent.sections.push(this);
// Check current state of section
var state = parent.states[this._index()];
if(state === 0) {
this.close(true);
}
else if(this.$summary.is(".open") || state === 1) {
this.open(true);
} else {
this.close(true);
}
}
Section.prototype = {
toggle : function() {
this.isOpen ? this.close() : this.open();
},
close: function(bypass) {
this._changeState("close", bypass);
},
open: function(bypass) {
var _this = this;
if(_this.options.accordion && !bypass) {
$.each(_this.parent.sections, function(i, section) {
section.close();
});
}
_this._changeState("open", bypass);
},
_index: function() {
return $.inArray(this, this.parent.sections);
},
_changeState: function(state, bypass) {
var _this = this;
_this.isOpen = state == "open";
if($.isFunction(_this.options[state]) && !bypass) {
_this.options[state].apply(_this.$details);
} else {
_this.$details[_this.isOpen ? "show" : "hide"]();
}
_this.$summary.toggleClass("open", state !== "close");
_this.$details.attr("aria-hidden", state === "close");
_this.$summary.attr("aria-expanded", state === "open");
_this.$summary.trigger(state === "open" ? "opened" : "closed", _this);
if(_this.parent.db) {
_this.parent.db.write(_this._index(), _this.isOpen);
}
}
};
// Expose in jQuery API
$.fn.extend({
collapse: function(options, scan) {
var nodes = (scan) ? $("body").find("[data-collapse]") : $(this);
return nodes.each(function() {
var settings = (scan) ? {} : options,
values = $(this).attr("data-collapse") || "";
$.each(values.split(" "), function(i,v) {
if(v) settings[v] = true;
});
new Collapse($(this), settings);
});
}
});
//jQuery DOM Ready
$(function() {
$.fn.collapse(false, true);
});
// Expose constructor to
// global namespace
exports.jQueryCollapse = Collapse;
exports.jQueryCollapseSection = Section;
})(window.jQuery, window);
the forum- limodim.com/1
thank you.
I have this code (also shown below) that is giving me an error in IE8 but is fine in Chrome and PhantomJS.
The error is "Object doesn't support this property or method knockout-2.2.1.debug.js, line 2319 character 35", which is called from currentPage(pages[pages.indexOf(current) + steps]);
I have no clue why it's not working, so any help would be greatly appreciated!
var Page = (function () {
function Page(index, name, canNavigateToPage, navigatedToThisPage) {
this.index = index;
this.name = name;
this.canNavigateToPage = canNavigateToPage;
this.navigatedToThisPage = navigatedToThisPage;
}
Page.prototype.navigateToPage = function () {
if (this.canNavigateToPage()) {
this.navigatedToThisPage(this);
}
};
return Page;
})();
var AccountSearchParameters = (function () {
function AccountSearchParameters() {
this.reference = ko.observable();
this.scheme = ko.observable();
this.lastName = ko.observable();
this.sufficientInputToSearchForAccount = ko.computed(function () {
return this.reference() && this.scheme() && this.lastName();
}, this);
}
return AccountSearchParameters;
})();
function viewModel() {
var self = this,
currentPage = ko.observable(),
accountSearchParameters = new AccountSearchParameters(),
forwardPageProgressionGuards = {
'1': function canMoveToPage2() {
return accountSearchParameters.sufficientInputToSearchForAccount();
},
'2': function canMoveToPage3() {
return true;
},
'3': function canMoveToPage4() {
return true;
}
},
canMoveToNextPage = function (currentlyOnPage) {
function disallowPageMovementNotExplicitlyDefined() {
return false;
}
return (forwardPageProgressionGuards[currentlyOnPage] || disallowPageMovementNotExplicitlyDefined)();
},
canMoveToPreviousPage = function (currentlyOnPage) {
return currentlyOnPage > 1;
},
pages = [
new Page(1, 'Customer details', function () {
return true;
}, function (page) {
currentPage(page);
}),
new Page(2, 'Bank details', forwardPageProgressionGuards['1'], currentPage),
new Page(3, 'Payment details', forwardPageProgressionGuards['2'], currentPage),
new Page(4, 'Confirmation', function () {
return true;
}, currentPage)],
pageNavigator = function (canNavigate, steps) {
current = currentPage();
console.log(canNavigate(current.index));
if (canNavigate(current.index)) {
currentPage(pages[pages.indexOf(current) + steps]);
}
};
currentPage(pages[0]);
self.page = ko.computed(function () {
return currentPage();
});
self.accountSearchParameters = accountSearchParameters;
self.nextPage = function () {
pageNavigator(canMoveToNextPage, 1);
};
self.previousPage = function () {
pageNavigator(canMoveToPreviousPage, -1);
};
self.canMoveToNext = ko.computed(function () {
return canMoveToNextPage(currentPage().index);
});
return self;
}
$(function () {
ko.applyBindings(viewModel());
});
indexOf in IE8 does not supported, use $.inArray