Added tinyMCE as inline editor. Have a next probllem : first time this is work good - show with custom style (as I setup), works correctly but when I click cancel and then start edit again I have empty editor - without text in edit area. so this is a code:
UPD : cm.Node - wrapper for docuement.createElement and el.setAttribute, cm.getByAttr('attr', 'attr_val', el) - get elemnt by attr from el. req - wrapper for AJAX, cm.merge - like array_merge in PHP
var EditBlock = function(){
var my = this;
var o = cm.merge({
'id' : '',
'act' : '',
'val' : '',
'nobr' : false,
'text' : false,
'onSaved' : function(){},
'onSave' : function(){},
'params' : {'iconsPath' : 'interface/common/images/stdc/nicEditorIcons.gif'}
}, arguments[0]);
var prefix = 'tinyMCE_' + Math.random() + '_';
var node = cm.getEl(o.id);
var txtArea = cm.addClass(cm.Node('textarea', {'id' : prefix + o.id, 'style': ('width:' + node.offsetWidth + 'px')}), prefix + o.id);
var saveBtn = cm.Node('input', {'type':'button', 'value':'Save'});
var cancelBtn = cm.Node('input', {'type':'button', 'value':'Cancel'});
var container = cm.Node('div', txtArea, cm.Node('div', saveBtn, cancelBtn));
var plainText = function(node){
var str = '';
var childs = node.childNodes;
for(var i = 0, ln = childs.length; i < ln; i++){
if(childs[i].nodeType == 3)
str += childs[i].nodeValue;
else if(childs[i].childNodes.length)
str += plainText(childs[i]);
}
return str;
}
var init = function(){
node.onclick = my.edit;
cancelBtn.onclick = my.close;
saveBtn.onclick = function(){
my.save();
my.close();
}
}
my.save = function(){
var tmp = cm.Node('div', tinyMCE.get(prefix + o.id).getContent());
var content = o.text? plainText(tmp) : tmp.innerHTML;
o.onSave(content);
node.innerHTML = content;
req({
'act' : o.act,
'data' : 'data[content]=' + escape(content) + (o.val? '&data[val]=' + o.val : ''), 'handler' : function(){o.onSaved(content)}
});
}
my.close = function(){
tinyMCE.init({
'editor_deselector' : prefix + o.id
});
container.parentNode.removeChild(container);
node.style.display = 'block';
}
my.edit = function(){
txtArea.value = node.innerHTML;
node.style.display = 'none';
node.parentNode.insertBefore(container, node);
var styles = '';
var styleRef = cm.getByAttr('rel', 'stylesheet');
for(var i = 0, ln = styleRef.length; i < ln; i++){
styles += (i > 0? ',' : '') + styleRef[i].href;
}
tinyMCE.init({
'height' : '100%',
'content_css' : styles + ',/sdtc-new/nc/interface/common/css/mce-editor.css',
'mode' : "specific_textareas",
'editor_selector' : prefix + o.id
});
}
init();
}
use this like :
new EditBlock({'onSave' : function(content){
page.content = content;
viewDepartment(page);
}, 'id':'depContent', 'act' : '/departments/setContent/', 'val' : page.id, 'params' : {buttonList : ['fontSize','bold','italic','underline','strikeThrough','html']}});
So ... again about problem. When first time start to edit that all works fine when click save - all works too (still exists some bugs but after saving I can click and start edit again) but when click cancel that editor is hide but when I click to edit again I have a empty edit area. I see to console and find that after canceling when I start editing again then I create new edit but old not destroy - only hidden.
I try to usetynyMCE.Editor class methods like hide and show and setContent and was a some result - after canceling I could edit egain but edit area was without styles and buttons.
Please help. If would be quaestion by code - I pleasure to answer.
Thanks.
Don't use hide() and show() here. You should shut down tinymce correctly in order to be able to reinitialize a tinymce editor with the same id as the first one.
To shut down an edtor instance use:
tinymce.execCommand('mceRemoveControl',true,'editor_id');
To reinitialize use
tinymce.execCommand('mceAddControl',true,'editor_id');
Please note!
These have since changed, you may have better luck with (for newer versions, 4+ I think):
try mceRemoveEditor and mceAddEditor instead...as in:
tinymce.execCommand('mceRemoveEditor',true,'editor_id');
tinymce.execCommand('mceAddEditor',true,'editor_id');
Related
I am receiving a JavaScript error due to the ASP.net bundle functionality, the JS code works fine before it gets minified but not after.
The issue Is have a isSelected variable that contains a boolean. But when the code gets minified it shortens this variable name to i. But in the $.each method I create an inline function with two parameters one being i.
It seems the minification logic failed to realize that renaming the variable to i would conflict with the code in my inline function.
Is this a bug with the ASP.net bundling system? If not how am I recommended to solve this, I am concerned that although I could just rename the parameter name that this bug could crop up in other parts of my web application.
Original JS code
function ItemManagerUpdateUi(instance) {
var selectedValue = instance.ItemCombo.GetValue();
var selectedItem = ItemManagerGetSelectedItem(instance);
var isSelected = selectedValue != null;
var isNewSelected = selectedValue == -1;
var applyText = isNewSelected ? "Add" : "Apply";
var text = isNewSelected ? "" : instance.ItemCombo.GetText();
var highestSortOrder = 0;
$.each(instance.Items, function (i, e) {
if (e.SortOrder > highestSortOrder)
highestSortOrder = e.SortOrder;
});
var sortOrder = isNewSelected || !isSelected ? highestSortOrder + 1 : selectedItem.SortOrder;
$('#' + instance.EditPanelId).toggle(isSelected);
$('#' + instance.ApplyButtonId).val(applyText);
$('#' + instance.DeleteButtonId).toggle(!isNewSelected);
var labelWidth = $(instance.ItemCombo.GetMainElement()).closest('.rbox-clearfix').find('.labelStyle').width() + 15;
$('#' + instance.ButtonPanelId).css('margin-left', labelWidth + 'px');
instance.TextControl.SetText(text);
instance.SortOrderControl.SetNumber(sortOrder);
$.each(instance.CustomFields, function (i, e) {
var value = isNewSelected || !isSelected ? null : selectedItem[e.DataName];
var dxControl = eval(e.ControlName);
dxControl.SetValue(value);
dxControl.SetIsValid(true);
});
if (!isNewSelected)
$(instance.ItemCombo.GetMainElement()).find('.dms-combo-main-input').removeClass('newActivityItem');
instance.TextControl.SetIsValid(true);
}
JS code after minification
function ItemManagerUpdateUi(n) {
var u = n.ItemCombo.GetValue(),
f = ItemManagerGetSelectedItem(n),
i = u != null,
t = u == -1,
s = t ? "Add" : "Apply",
h = t ? "" : n.ItemCombo.GetText(),
r = 0,
e,
o;
$.each(n.Items, function(n, t) {
t.SortOrder > r && (r = t.SortOrder)
});
e = t || !i ? r + 1 : f.SortOrder;
$("#" + n.EditPanelId).toggle(i);
$("#" + n.ApplyButtonId).val(s);
$("#" + n.DeleteButtonId).toggle(!t);
o = $(n.ItemCombo.GetMainElement()).closest(".rbox-clearfix").find(".labelStyle").width() + 15;
$("#" + n.ButtonPanelId).css("margin-left", o + "px");
n.TextControl.SetText(h);
n.SortOrderControl.SetNumber(e);
console.log(i);
$.each(n.CustomFields, function(i, e) {
console.log(i);
var value = t || !i ? null : f[e.DataName]
, dxControl = eval(e.ControlName);
dxControl.SetValue(value);
dxControl.SetIsValid(!0)
});
t || $(n.ItemCombo.GetMainElement()).find(".dms-combo-main-input").removeClass("newActivityItem");
n.TextControl.SetIsValid(!0)
}
EDIT
After more research it seems removing the eval line of code fixes the issue. For the time being I changed my code to not use eval although this still seems like a bug in the bundle process, for some reason you have these strange behaviour when using eval
function OnDragStartElement(e) {
//this.style.opacity = '0.4';
srcElementParent = this;
e.dataTransfer.effectAllowed = 'move';
var elementCount = formElements.length > 0 ? Math.max.apply(Math, formElements.map(function (o) { return o.ID; })) : 0;
var elementText = $(this).children()[0].innerHTML;
var elementType = $($(this).children()[1])[0].value;
var elementID = (elementCount + 1);
var draggedElement = elementText + ': ' + elementText + elementID
//debugger;
e.dataTransfer.setData("dragedElement", draggedElement);
e.dataTransfer.setData('draggedElementType', elementType);
e.dataTransfer.setData('draggedElementID', elementID);
isElementNotPlaced = true;
isdragDivElement = false;
}
An error is thrown:
Unexpected call to method or property access.
The error I see is on the line:
e.dataTransfer.setData("dragedElement", draggedElement);
The same code works fine on Chrome & Firefox.
Does anyone have a solution for this?
Refere this link.
Drag & Drop HTML 5 jQuery: e.dataTransfer.setData() with JSON
no need to set data for each
e.dataTransfer.setData("dragedElement", draggedElement);
e.dataTransfer.setData('draggedElementType', elementType);
e.dataTransfer.setData('draggedElementID', elementID);
instead of this we can pass single json object as text.
I'm trying to add an "onclick" event with their respective function from js JQuery to an interactive table td I'm doing in another .php file, the problem is not executed in the place where I want to do it but if the same instruction is executed correctly within an AJAX request a few lines below, will show you the code:
This instruction is giving me the problem:
$(td).attr("onclick","agregar_pensum_etapa2 (this,'"+subject+"','"+level+"','"+stage+"');");
And this, the function I want to run with the "onclick"
function agregar_pensum_etapa2(td,subject,level,stage){
$(document).ready(function(){
// Capture variables.
var id_periodo = $("#id_periodo").val();
var id_asignatura = subject;
var id_nivel = level;
var id_etapa = stage;
var id_mencion = null;
if (level> 3) {
id_mencion = 0;
}
// Modifiable column.
var tr = $(td).parent();
var index_td = $(td).index();
// First field
var valor_anterior = $(td).text();
$(td).html("<img src =" images / save_64.png 'width = '16' height = '16 '> & nbsp; & nbsp; & nbsp;' + '<input value = "' + valor_anterior + '" type = "text" style = "width: 40px; border: 1px solid #aaa;" onkeypress = "return soloNumeros (event);" maxlength = "2"> ');
$(td).removeAttr("onclick");
$(td).find("input").focus();
// Second field
var valor_anterior_cs = $(tr).find("td:eq("+(index_td+1)+")").text();
var checked_cs = "";
if (valor_anterior_cs === "X"){checked_cs = "checked"}
$ (tr) .find ("td: eq (" + (index_td + 1) + ")") html ("<input type = 'checkbox'" + checked_cs + ">").
// Third field
var valor_anterior_hum = $(tr).find("td:eq("+(index_td+2)+")").text();
var checked_hum = "";
if(valor_anterior_hum === "X") {checked_hum = "checked"}
$(tr).find("td:eq("+(index_td+2)+")").html("<input type = 'checkbox'"+checked_hum+">");
/ ************************************************* *********** /
$(td).find("img").click(function(){
var hora_asignatura = $(td).find("input").val();
var mencion_cs = "NO";
if($(tr).find("td:eq("+(index_td+1)+")").find("input").is ("checked")){mencion_cs = "YES";}
var mencion_hum = "NO";
if($(tr).find("td:eq("+(index_td+2)+")").find("input").is("checked")){mencion_hum = "YES";}
if(hora_asignatura === ""){
if(valor_anterior != ''){
$(td).html(valor_anterior);
$(tr).find("td:eq("+index_td+1)+")").text(valor_anterior_cs);
$(tr).find("td:eq("+(index_td+2)+")").text(valor_anterior_hum);
}else{
$(td).html("");
$(tr).find("td:eq("+(index_td+1)+")").text("");
$(tr).find("td:eq("+(index_td+2)+")").text("");
}
\\// --> HERE IS NOT WORKING <-- \\//
$(td).attr("onclick","agregar_pensum_etapa2(this,'"+subject +"','"+level+"','"+stage+"');");
}else if(hora_asignatura == "0"){
if(valor_anterior! = ''){
$(td).html(valor_anterior);
$(tr).find("td:eq("+(index_td+1)+")").text (valor_anterior_cs);
$(tr).find("td:eq("+(index_td+2)+")").text (valor_anterior_hum);
}else{
$(td).html("<img src =" images / diagonal.png 'height = '16' style = 'width: 15px ">");
$(tr).find("td:eq("+(index_td+1)+")").text("");
$(tr).find("td:eq("+(index_td+2)+")").text("");
}
\\// --> HERE IS NOT WORKING <-- \\//
$(td).attr("onclick","agregar_pensum_etapa2(this,'"+subject+"','"+level+ "','"+stage+"');");
}else{
$.ajax({
async: true,
cache: false,
dataType: "html"
type: 'POST'
url: "../Controlador/CtrlPensum.php"
data: {
id_periodo: id_periodo,
id_asignatura: id_asignatura,
id_nivel: id_nivel,
id_etapa: id_etapa,
hora_asignatura: hora_asignatura,
mencion_cs: mencion_cs,
mencion_hum: mencion_hum,
id_mencion: id_mencion,
record: "register"
},
success: function (response) {
//alert (response);
if($.trim(answer) === "1") {
$(td).html(hora_asignatura);
var marcar_cs_x = "";
if(mencion_cs === "SI"){marcar_cs_x = "X";}
var marcar_hum_x = "";
if(mencion_hum === "SI"){marcar_hum_x = "X";}
$(tr).find("td:eq("+(index_td+1)+")").html (marcar_cs_x).
$(tr).find("td:eq("+(index_td+2)+")").html (marcar_hum_x).
\\// --> HERE IT WORKS <-- \\//
$(td).attr("onclick", "agregar_pensum_etapa2 (this,'"+subject+"','"+level+"','"+stage+"');");
cargarTablaResumen ();
} Else {
alert ("Error SQL statement is not executed." + response);
}
//tr.fadeOut(500).fadeIn(500);
},
beforeSend: function () {}
Error: function (objXMLHttpRequest) {}
});
}
});
});
}
I try this:
$(td).click(function(){
$(td).attr("onclick","agregar_pensum_etapa2 (this,'"+subject+"','"+level+ "','"+stage+"');");
});
And in the html it prints correctly but does not work, like he was not the "onclick" there. And the function if it works, I put the onclick to that function when I load the page and if it works, but when I click the td and give back to click to restore does not restore the onclick.
Instead of setting the onclick attribute, why not do use .click() again with closures? So your code would be something like...
$(td).click(function(){
var td = this;
$(td).click(function () {
agregar_pensum_etapa2(td,subject,level,stage);
});
});
Do you write
$(Document)
Instead of $(document) with small letter "d".
I can only get the CSS styled image to load. The browser does not display imgB. The source code also only shows imgA. I just want to call the backgroundImage value of the Object at the time of the specific loop
My HTML.
<div onclick="displayCards()">Display Cards</div>
My Javascript Objects contain properties for these DIV elements. The different cards each have a unique image imgB. I created an array for the Objects so I can loop through them with a for loop.
var card_troop = { title : "troop" , type : "Unit" , image : "url(troop.png)" } ;
var card_base = { title : "base" , type : "Structure" , image : "url(base.png)" } ;
var card_wood = { title : "wood" , type : "Resource" , image : "url(wood.png)" } ;
var list = [
card_troop ,
card_base ,
card_wood
] ;
The DIV elements are created by my displayCards() function, that are appended to the body of my HTML document.
function displayCards()
{
card = document.createElement("div") ;
var card_id = document.createAttribute("id") ;
card_id.value = list[x].title ;
card.setAttributeNode(card_id) ;
var card_class = document.createAttribute("class") ;
switch (list[x].type) // Card Theme Comparison
{
case "Unit" :
card_class.value = "unit" ;
break ;
case "Structure" :
card_class.value = "structure" ;
break ;
case "Resource" :
card_class.value = "resource" ;
break ;
}
card.setAttributeNode(card_class) ;
var imgA = card.style.backgroundImage ;
var imgB = list[x].image ;
card.style.backgroundImage = imgA + " , " + imgB ;
}
Using the switch Comparison, switch (list[x].type), defined by the Object Property type:, each DIV will have one of three CSS backgroundImage values.
div.unit { background-image:url( theme_unit.png ) ; }
div.structure { background-image:url( theme_structure.png ) ; }
div.resource { background-image:url( theme_resource.png) ; }
Another function builder() calls displayCards() and appends the Object card.
function builder()
{
for ( x = 0 ; x < 9 ; x++ )
{
displayCards() ;
document.body.appendChild(card) ;
}
}
I believe my problem lies here. Since the DIV is still not appended.
To note:imgA is a higher index than imgB and has transparency to allow imgB to be seen.
var imgA = card.style.backgroundImage ;
var imgB = list[x].image ;
card.style.backgroundImage = imgA + " , " + imgB ;
I am a minimalist coder and this is the shortest I could come up with. I do not want to have to repeat URL's more than once. My list of Objects is going to get much longer than three.
NO JQUERY
var card_troop = { title : "troop" , type : "Unit" , image : "url(troop.png)" } ;
var card_base = { title : "base" , type : "Structure" , image : "url(base.png)" } ;
var card_wood = { title : "wood" , type : "Resource" , image : "url(wood.png)" } ;
var list = [
card_troop,
card_base,
card_wood
];
function buildCard(card) {
var elem = document.createElement('div'),
elemCloned,
computedBackgroundUrl,
backgroundUrl;
elem.id = card.title;
elem.className = card.type.toLowerCase();
// Clone element and temporary append to body
elemCloned = elem.cloneNode();
elemCloned.style.display = 'none';
document.body.appendChild(elemCloned);
computedBackgroundUrl = window.getComputedStyle(elemCloned)['background-image'];
if (computedBackgroundUrl) {
var match = computedBackgroundUrl.match(/^url\((.*)\)/);
if (match) {
backgroundUrl = match[1];
}
}
// remove element after retrieved background-image value
elemCloned.parentNode.removeChild(elemCloned);
elemCloned = null;
elem.style.backgroundImage = (backgroundUrl ? 'url(' + backgroundUrl + '), ' : '') + card.image;
computedBackgroundUrl = null;
backgroundUrl = null;
return elem;
}
function displayCards() {
var body = document.body;
for (var i = 0, len = list.length; i < len; i++) {
body.appendChild( buildCard(list[i]) );
}
}
Never got efficient in js but your js solution should be the js parallel.
add/remove the class on the div and swap background images according to class in css. I'm assuming this would require less js as a bonus.
hope this helps.
You should work through this approach. Replace "backgroundimage" and "foregroundimage" with the appropriated URLs (of course).
Afterwards you can call the method showCard with a switch. showCard(true) shows the card's front. showCard(false) shows the card's back.
var card = function(title, type, image) {
this.title = title;
this.type = type;
this.image = image;
this.background = "url('backgroundimage')";
};
card.prototype.showCard = function(turn) {
if (turn) {
var ele = document.createElement("div");
ele.appendChild(document.createTextNode(this.title));
ele.appendChild(document.createTextNode(this.type));
ele.style.backgroundImage = this.image;
document.body.appendChild(ele);
} else {
var ele = document.createElement("div");
ele.style.backgroundImage = this.background;
document.body.appendChild(ele);
}
};
function displayCards() {
var card_troop = new card("TroopTitle", "TroopType", "url('foregroundimage')");
card_troop.showCard(true);
var card_troop_2 = new card("Troop2Title", "TroopType", "url('foregroundimage2')");
card_troop_2.showCard(false);
};
div {
min-width: 50px;
height: 120px;
border: solid;
float: left;
}
<input type="button" onclick="displayCards()" value="Display Cards" />
is there a way to pass data to render
The following code is what I'm currently using:
render:function() {
var background =
var highlight = this.model.get('highlight');
$(this.el).find('div').each(function(index,element) {
if(index < highlight) {
$(element).css({'background': 'url("assets/img/alphabet/ok/ok.png"), url('+background+')'});
$(element).attr('id', 'ok');
} else {
$(element).removeAttr('id');
}
})
}
maybe like this pic:
... you can do something like this:
this.background : [],
//...
initialize : function(){
//...
this.background.push(string.charAt(i));
//...
},
render : function(){
//...
var background = this.background[index];
//...
}
but, maybe also for loop inside your initialize can stay inside render, because it render the view (with .append()).
EDIT NOTE:
I repeat, the possibilities to move around the loop in the initialization function in the render function.
I try to change your backbone view structure:
var WordView = Backbone.View.extend({
initialize : function(){
this.listenTo(this.model,"remove",this.remove);
},
render : function(){
var $Div,
string = this.model.get('string'), //use _string (string can cause some issue in IE)
highlight = this.model.get("highlight"),
letter_width = 36,
letter_heigth = 35,
word_width = string.length * letter_width;
if(this.model.get("x") + word_width > $(window).width()) this.model.set({x:$(window).width() - word_width});
$(this.el).css({
position:"absolute",
top : this.model.get("y"),
left : this.model.get("x")
});
var background,char;
for(var i; i < string.length; i++){
char = string.charAt(i);
background = "url('"+char+"') no-repeat";
$Div.removeAttr("id"); //seems useless
if(i < highlight){
background = "url('assets/img/alphabet/ok/ok.png'),url('"+char+"')";
$Div.id("ok"); //maybe is better $Div.class("ok");
}
$Div = $("<div>").clone();
$Div.css({
width : letter_width,
heigth : letter_height,
float: "left",
"background" : background
}).appendTo($(this.el));
}
}
});