JavaScript loop inside tinymce button - javascript

My JavaScript loop is not working properly inside a tinymce button.
I set a variable n which is the array size that I get from my html input.
var n = $('#total').val();
Then, I create the array of tinymce buttons: var menuItems = [];
In my tinymce editor init, I create the buttons:
editor.on('init', function (e) {
for (var i=1; i<=n; i++){
var obj = {
text: 'Item ' + i,
onclick: function() {
var msg = ' <strong>#item' + i + '#</strong> ';
editor.insertContent(msg);
}
}
menuItems.push(obj);
}
});
Last step is add the menuItems to the tinymce buttons:
editor.addButton('myButton', {
type: 'menubutton',
text: 'Items',
icon: false,
menu: menuItems
});
The buttons are displaying correct with the correct label. I have the buttons:
Item 1
Item 2
Item 3
However, doesn't matter which button I click, the text displayed in the editor is item3. It always get the last button text.
Does anyone know why it is happening?
Thanks

Use let instead of var since let would keep its lexical block scope where var would not:
editor.on('init', function(e) {
for (let i = 1; i <= n; i++) { // <-- use let here
var obj = {
text: 'Item ' + i,
onclick: function() {
var msg = ' <strong>#item' + i + '#</strong> ';
editor.insertContent(msg);
}
}
menuItems.push(obj);
}
});
Here is the documentation on let

Related

w2ui version 2, how can I get sellected cell name onContextMenuClick

I'm using w2ui version 2 and I have
let row = '';
let cell = '';
let grid = new w2grid({
name: 'grid'
...
...
,onClick: function (event) {
event.onComplete = function () {
row = event.detail.recid;
cell = event.detail.column;
console.log("onClick cell : " + cell );
}
}
...
...
}
in my code and it is working fine, but the code below is not working.
,onContextMenuClick: function (event) {
event.onComplete = function () {
row = event.detail.recid;
cell = event.detail.column;
console.log("onClick onContextMenuClick : " + cell);
}
}
boot is the part of same grid code.
How can I get selected cell onContextMenuClick. So I can add some specific Context Menu events to my w2ui grid.
I did try looping all sub objects of event
const keys = Object.keys(event);
for (let i = 0; i < keys.length; i++) {
console.log("onContextMenuClick event : " + keys[i] + ': ' + event[keys[i]]);
}
so I can find is there any data about cell, no luck.
var sel = grid.getSelection()[0];
only returns recid not any thing about cell.
thanks

OnClick() event is not working in JavaScript for dynamic button in my code

I have added a dynamic buttons inside for loop on webpage using JavaScript and assigned a unique id to each button. I wants to assign onclick() event Listener to each button but this function is not being assigned to any of dynamic buttons. Kindly help me resolving this. Thank You.
myfunction()is working but myfunction1() has some problem. I cannot see onclick event in its dynamically HTML.
There are JS file. data.js contains arrays of objects and other contains function which access the data.
// function.js
function chargerArticles() {
var myShoppingCart = [];
var articles = document.getElementById("content");
for (var i = 0; i < catalogArray.length; i++) {
//Product div
var article = document.createElement("div");
article.setAttribute("class", "aa");
//Unique id
article.id = i + "-article";
//Product Name
var articleName = document.createElement("h4");
articleName.setAttribute("class", "aa-product-title");
var articleNameLink= document.createElement('a');
articleNameLink.setAttribute('href',"#");
articleNameLink.innerText = catalogArray[i].name;
articleName.appendChild(articleNameLink);
article.appendChild(articleName);
//Command Input Area
var zoneCmd = document.createElement("div");
var inputCmd = document.createElement("input");
//Button of add to cart
var button = document.createElement("BUTTON");
button.setAttribute("class", "Btn hvr-underline-btn");
button.innerHTML = " ADD";
//Button unique id
button.id = i + "-cmd";
//not working
button.addEventListener("click", myFunction1);
function myFunction1() {
var item = this.getAttribute("id");
var pos = item.substring(0, 1);
document.getElementById("1235").innerHTML = "Hello World";
addToCart(pos);
}
//working
document.getElementById("1234").addEventListener("click", myFunction);
function myFunction() {
document.getElementById("1234").innerHTML = "YOU CLICKED ME!";
}
zoneCmd.appendChild(button); //child 2
//zoneCmd child of article element
article.appendChild(zoneCmd);
//finally article as a child of articles
articles.appendChild(article);
}
}
function searchInCart(name) //T-Shirt
{
myShoppingCart = myCartArray;
var name1 = name;
var stop = 0;
for (var i = 0; i < myShoppingCart.length && stop == 0; i++) {
if (myShoppingCart[i].name == name1) {
stop = 1;
// console.log("Hello wooooorld!");
return true;
} else {
return false;
}
}
}
function addToCart(pos) {
if (searchInCart(catalogArray[pos].name)) {
alert("Already Exist!"); // display string message
} else {
var ident = pos + "-qte";
var quatity = document.getElementById("ident").value;
if (quatity > 0) {
var articleCmd = {}; //array of objects
articleCmd.name = catalogArray[pos].name;
articleCmd.price = catalogArray[pos].price;
articleCmd.qte = quatity;
articleCmd.priceTotal = articleCmd.price * articleCmd.qte;
myCartArray.push(articleCmd);
} else {
// alert
}
}
}
//data.js
// data.js
var catalogArray = [{
code: 100,
name: "T Shirt c100",
desc: "Lorem ipsum, or lipsum as it is sometimes known as",
price: 150,
image: "./images/img100.jpg"
},
{
code: 101,
name: "T Shirt c101",
desc: "Lorem ipsum, or lipsum as it is sometimes known as",
price: 250,
image: "./images/img101.jpg"
},
];
var myCartArray = [{
name: "T Shirt c100",
price: 150,
qte: 2,
TotalPrice: 150,
}
];
This issue occurred because you defined myfunction1 dynamically. In other words, this element wasn't defined during the initial rendering of the page.
You can fix it by using event delegation. Here is how:
Instead of defining the callback on the element, define it for all children of the PARENT element that have the matching css class. For example:
$( ".btnContainer .btn" ).on( "click", function( event ) {
event.preventDefault();
console.log("clicked");
});
where:
<div class='btnContainer'>
</div>
Now when you add buttons with (class name btn) dynamically as children of btnContainer, they will still get access to the click handler, because the event handler isn't bound to the element btn, but to it's parent, hence when the click event is fired, the parent delegates the event to all it's children with the matching class(es)!
Do not add a function in a loop
Delegate
Have a look here. There are MANY issues, I have addressed a few of them
You MAY want to do
button.setAttribute("data-code",item.code);
instead of
button.id = i + "-cmd";
// function.js
const content = document.getElementById("content");
content.addEventListener("click",function(e) {
const tgt = e.target, // the element clicked
id = tgt.id; // the ID of the element
if (id.indexOf("-cmd") !=-1) { // is that element one of our buttons?
// get the name of the article from the button - this could also be a data attibute
var pos = id.split("-")[1];
addToCart(pos);
}
})
function chargerArticles() {
const myShoppingCart = catalogArray.map(function(item, i) {
//Product div
var article = document.createElement("div");
article.setAttribute("class", "aa");
//Unique id
article.id = i + "-article";
// here would be a good place to add item.name or something
//Command Input Area
var zoneCmd = document.createElement("div");
var inputCmd = document.createElement("input");
//Button of add to cart
var button = document.createElement("BUTTON");
button.setAttribute("class", "Btn hvr-underline-btn");
button.innerHTML = " ADD";
//Button unique id
button.id = i + "-cmd";
zoneCmd.appendChild(button); //child 2
//zoneCmd child of article element
article.appendChild(zoneCmd);
//finally article as a child of articles
articles.appendChild(article);
content.appendChild(articles) // ???
})
}
function searchInCart(name) {
return myCartArray.filter(function(x) {
return x.name === name
})[0];
}

JQuery click eventhandler: register event on dynamically added element

I would like to dynamically build a page from 2 hashes (in my example c and d).
var c = {
cluster_1 : { list_datasets: [ "a", "b", "c"]},
cluster_2 : { list_datasets: [ "b", "c"]},
};
var d = {
a : { title: "A", content: "aaaaaaaaaaaaaa"},
b : { title: "B", content: "bbbbbbbbbbbbbb"},
c : { title: "C", content: "cccccccccccccc"},
};
so that I first get the list of clusters, and then by clicking on the cluster, I get the list of their respective content. This works fine until here.
But now if I want to go a step further end by clicking on each dataset, I would like to have the dataset description. The jquery selection operation $('#a') is empty and nothing is shown. Here a little standalone example that shows the problem
Thanks a lot for you help or any information on that topic.
Kind regards
Antoine
Since these elements are created dynamically, you have to use delegate event handler like
$(document).on('click', '#'+key, function(event){
$("aside").html(value.content);
});
JSFiddle
Your problem is that you call second each
$.each(d, function(key, value){ ..
when there are no elements printed on the page.
Elements get printed only when you click on any of clusters. So you should wrap second each with a function e.g.
function getValues(){
$.each(d, function(key, value){
$('#' + key).each(function(){
console.log(value.content);
});
});
};
and call it at the end of click function
$('#' + cluster).click(function( event ) {
var content_list = "<ul>";
for (var i = 0; i < value.list_datasets.length; i++) {
var dsName = datasetName = value.list_datasets[i];
if(d.hasOwnProperty( datasetName ) ) {
var datasetName = d[datasetName].title;
}
content_list = content_list + "<li><a id='" + dsName + "' href='#foo'>" + datasetName + "</a></li>";
}
content_list = content_list + "</ul>";
$("section").html(content_list);
getValues();
});

JqGrid, how to center delete box?

in My Jqgrid i have a column with delete links, everything works perfect, except that delete confirmation box pops up at top left corner all the time. i want to have the confirmation box in center of the jqgrid, not in top left corner.
{ name: 'act', index: 'act', width: 150, align: 'center', sortable: false}],
gridComplete: function () {
var rows = jQuery("#list").jqGrid('getGridParam','selrow');
var ids = jQuery("#list").jqGrid('getDataIDs');
var gr = jQuery('#list'); gr.setGridHeight("auto", true);
for (var i = 0; i < ids.length; i++) {
var cl = ids[i];
be = "<a href='#' style='height:25px;width:120px;' type='button' value='Slet' onclick=\"jQuery('#list').jqGrid('delGridRow','" + cl + "',{reloadAfterSubmit:false, url:'#Url.Action("deleteRow")'}); return false;\">Slet </>";
jQuery("#list").jqGrid('setRowData', ids[i], { act: be });
}
},
UPDATE
be = "<a href='#' style='height:25px;width:120px;' type='button' value='Slet' onclick=\"jQuery('#list').jqGrid('delGridRow','" + cl + "', myDelParameters); return false;\">Slet </>";
code for my Global variable:
myDelParameters = {reloadAfterSubmit:false, url:'#Url.Action("deleteRow")', beforeShowForm: function(form) {
// "editmodlist"
var dlgDiv = jQuery("#list").jqGrid("#delmodlist" + grid[0].id);
var parentDiv = dlgDiv.parent(); // div#gbox_list
var dlgWidth = dlgDiv.width();
var parentWidth = parentDiv.width();
var dlgHeight = dlgDiv.height();
var parentHeight = parentDiv.height();
// TODO: change parentWidth and parentHeight in case of the grid
// is larger as the browser window
dlgDiv[0].style.top = Math.round((parentHeight-dlgHeight)/2) + "px";
dlgDiv[0].style.left = Math.round((parentWidth-dlgWidth)/2) + "px";
}};
You set already some parameters of the delGridRow method (see {reloadAfterSubmit:false, url:... in your code).
My suggestion that you use afterShowForm in the list of delGridRow parameters. The implementation of the afterShowForm could be like in the old answer, but with the usage of "#delmodlist" ("#delmod" + grid[0].id, where var grid = $("#list")) instead of $("#editmod" + grid[0].id).
Another more short form of the implementation could be with respect of jQuery UI Position:
afterShowForm = function ($form) {
$form.closest('div.ui-jqdialog').position({
my: "center",
of: $("#list").closest('div.ui-jqgrid')
});
}
In the demo I use such function for all Add/Edit and Delete forms.
UPDATED: It seems to me that you have implementation problems. I made one more demo which you can easy modify to what you want. I don't set any editurl, so if you press "Delete" button the error will be displayed. Moreover the HTML fragment which you try to place in the 'act' column is a combination of <a> and <button> settings. Because I don't know what you wanted I placed just <a> in the 'act' column. I hope now you can easy modify my demo to make your program working.
Here is the schema of the code from my demo which you can use:
<script type="text/javascript">
//<![CDATA[
var myDelParameters = {
reloadAfterSubmit: false,
//url:'#Url.Action("deleteRow")',
afterShowForm: function ($form) {
'use strict';
$form.closest('div.ui-jqdialog').position({
my: "center",
of: $("#list").closest('div.ui-jqgrid')
});
}
};
$(document).ready(function () {
var grid = $("#list"),
centerForm = function ($form) {
$form.closest('div.ui-jqdialog').position({
my: "center",
of: grid.closest('div.ui-jqgrid')
});
},
getColumnIndexByName = function (mygrid, columnName) {
var cm = mygrid.jqGrid('getGridParam', 'colModel'), i = 0, l = cm.length;
for (; i < l; i += 1) {
if (cm[i].name === columnName) {
return i; // return the index
}
}
return -1;
};
grid.jqGrid({
colModel: [
...
{name: 'action', index: 'action', width: 70, align: 'center', sortable: false},
...
],
...
loadComplete: function () {
var iCol = getColumnIndexByName($(this), 'action'), iRow, row,
rows = this.rows,
cRows = rows.length;
for (iRow = 0; iRow < cRows; iRow += 1) {
row = rows[iRow];
if ($.inArray('jqgrow', row.className.split(' ')) > 0) {
$(row.cells[iCol]).html("<a href='#' style='height:25px;width:120px;' onclick=\"jQuery('#list').jqGrid('delGridRow','" +
row.id + "',myDelParameters); return false;\">Del</>");
}
}
});
});
//]]>
</script>
for centering the jqdialog and display near the row selected
.ui-jqdialog{position:fixed; left:415px;}
This is working perfect for my requirement.
Thank You

Insert HTML in NicEdit WYSIWYG

How can I insert text/code at the cursors place in a div created by NicEdit?
I've tried to read the documentation and create my own plugin, but I want it to work without the tool bar (Modal Window)
This is a quick solution and tested in firefox only. But it works and should be adaptable for IE and other browsers.
function insertAtCursor(editor, value){
var editor = nicEditors.findEditor(editor);
var range = editor.getRng();
var editorField = editor.selElm();
editorField.nodeValue = editorField.nodeValue.substring(0, range.startOffset) +
value +
editorField.nodeValue.substring(range.endOffset, editorField.nodeValue.length);
}
Insert Html Plugin
Don't know if this will help or not, but this is the plugin I created for inserting Html at the cursor position. The button opens a content pane and I just paste in the html I want and submit. Works for me!
var nicMyhtmlOptions = {
buttons : {
'html' : {name : 'Insert Html', type : 'nicMyhtmlButton'}
},iconFiles : {'html' : '/nicedit/html_add.gif'}
};
var nicMyhtmlButton=nicEditorAdvancedButton.extend({
addPane: function () {
this.addForm({
'': { type: 'title', txt: 'Insert Html' },
'code' : {type : 'content', 'value' : '', style : {width: '340px', height : '200px'}}
});
},
submit : function(e) {
var mycode = this.inputs['code'].value;
this.removePane();
this.ne.nicCommand('insertHTML', mycode );
}
});
nicEditors.registerPlugin(nicPlugin,nicMyhtmlOptions);
I used the html_add icon from Silk Icons, pasted onto a transparent 18 x 18 and saved as gif in the same folder as nicEditorIcons.gif.
It works for me when I use:
function neInsertHTML(value){
$('.nicEdit-main').focus(); // Without focus it wont work!
// Inserts into first instance, you can replace it by nicEditors.findEditor('ID');
myNicEditor.nicInstances[0].nicCommand('InsertHTML', value);
}
The way I solved this was to make the nicEdit Instance div droppable, using jQuery UI; but to also make all of the elements within the div droppable.
$('div.nicEdit-main').droppable({
activeClass: 'dropReady',
hoverClass: 'dropPending',
drop: function(event,ui) {
$(this).find('.cursor').removeClass('cursor');
},
over: function(event, ui) {
if($(this).find('.cursor').length == 0) {
var insertEl = $('<span class="cursor"/>').append($(ui.draggable).attr('value'));
$(this).append(insertEl);
}
},
out: function(event, ui) {
$(this).find('.cursor').remove();
},
greedy: true
});
$('div.nicEdit-main').find('*').droppable({
activeClass: 'dropReady',
hoverClass: 'dropPending',
drop: function(event,ui) {
$(this).find('.cursor').removeClass('cursor');
},
over: function(event, ui) {
var insertEl = $('<span class="cursor"/>').append($(ui.draggable).attr('value'));
$(this).append(insertEl);
},
out: function(event, ui) {
$(this).find('.cursor').remove();
},
greedy: true
});
Then make your code or text draggable:
$('.field').draggable({
appendTo: '.content', //This is just a higher level DOM element
revert: true,
cursor: 'pointer',
zIndex: 1500, // Make sure draggable drags above everything else
containment: 'DOM',
helper: 'clone' //Clone it while dragging (keep original intact)
});
Then finally make sure you set the value of the draggable element to what you want to insert, and/or modify the code below to insert the element (span) of your choice.
$sHTML .= "<div class='field' value='{{".$config[0]."}}'>".$config[1]."</div>";
A response to #Reto: This code works, I just needed to add some fix because it doesn't insert anything if text area is empty. Also it adds only plain text. Here is the code if anybody need it:
if(editorField.nodeValue==null){
editor.setContent('<strong>Your content</strong>');
}else{
editorField.nodeValue = editorField.nodeValue.substring(0, range.startOffset) +
'<strong>Your content</strong>' +
editorField.nodeValue.substring(range.endOffset, editorField.nodeValue.length);
editor.setContent(editorField.nodeValue);
}
Change follwoing in NicEdit.js File
Updated from Reto Aebersold Ans It will handle Null Node exception, if text area is empty
update: function (A) {
(this.options.command);
if (this.options.command == 'InsertBookmark') {
var editor = nicEditors.findEditor("cpMain_area2");
var range = editor.getRng();
var editorField = editor.selElm();
// alert(editorField.content);
if (editorField.nodeValue == null) {
// editorField.setContent('"' + A + '"')
var oldStr = A.replace("<<", "").replace(">>", "");
editorField.setContent("<<" + oldStr + ">>");
}
else {
// alert('Not Null');
// alert(editorField.nodeValue + ' ' + A);
editorField.nodeValue = editorField.nodeValue.substring(0, range.startOffset) + A + editorField.nodeValue.substring(range.endOffset, editorField.nodeValue.length);
}
}
else {
// alert(A);
/* END HERE */
this.ne.nicCommand(this.options.command, A);
}
This function work when nicEdit textarea is empty or cursor is in the blank or new line.
function addToCursorPosition(textareaId,value) {
var editor = nicEditors.findEditor(textareaId);
var range = editor.getRng();
var editorField = editor.selElm();
var start = range.startOffset;
var end = range.endOffset;
if (editorField.nodeValue != null) {
editorField.nodeValue = editorField.nodeValue.substring(0, start) +
value +
editorField.nodeValue.substring(end, editorField.nodeValue.length);
}
else {
var content = nicEditors.findEditor(textareaId).getContent().split("<br>");
var linesCount = 0;
var before = "";
var after = "";
for (var i = 0; i < content.length; i++) {
if (linesCount < start) {
before += content[i] + "<br>";
}
else {
after += content[i] + "<br>";
}
linesCount++;
if (content[i]!="") {
linesCount++;
}
}
nicEditors.findEditor(textareaId).setContent(before + value + after);
}
}

Categories