I have a web application that uses Ext-JS 2.2. In a certain component, we have an empty toolbar that we are trying to add a button to using
myPanel.getTopToolbar().insertButton(0, [...array of buttons...]);
However, in IE6/7 this fails because of lines 20241-20242 in ext-all-debug.js:
var td = document.createElement("td");
this.tr.insertBefore(td, this.tr.childNodes[index]);
Since "this.tr.childNodes([0])" does not yet exist in IE, this fails with "Invalid argument".
THE REAL QUESTION:
Can I, using CSS similar to the below add a child to every toolbar <tr> so that this.tr.childNodes[0] is found:
div.x-toolbar tr:after { content: " "; }
I totally realize this is a hack, but for legal reasons I cannot change any Javascript, not even to add an empty button ({}) to each toolbar. Major kudos to anyone that can figure this out.
What I've had to do in the past was include an empty toolbar in my element config:
tbar:[]
Then (and only after the element has completely rendered) use the .add() method for injecting buttons.
Order of events will get you every time. It takes a while to get a handle on it.
If all you are doing is adding to a empty panel
myPanel.getTopToolbar().add(buttons etc);
Or
myPanel.getTopToolbar().addButton(..);
Either should work. It looks like purpose of insertButton is for putting a button within a non-empty toolbar.
Did you look into adding the button after the panel has been rendered? Maybe something like:
myPanel.on('render', function() {
this.getTopToolbar().insertButton(0, [...array of buttons...]);
}, true);
I didn't think there was a CSS-only solution.
For the record, I ended up injecting javascript into the page that overrides the Ext.Toolbar prototype for the insertButton() function to check for the existance of "this.tr.childNodes([0])" and default to addButton() if it didn't exist.
Related
Im very new to this and have reviewed other posts similar to this question. However, I'm finding that those solutions don't work for me.
Background: I'm working in Wix's Velo platform for Javascript. (forgive me if that's not the right technical terminology here)
My goal: When my website home page loads, I want one of the text boxes on the page (#text45) to NOT be visible until 5 seconds have passed. Then, when box #text45 is visible, I want another plain box (#box2) to turn to hidden.
I have found some examples like the one below: (not all code has been pasted and I realize some elements like div1 would need to change to my specific element names)
document.getElementById("div1").style.visibility = "visible";
}
setTimeout("showIt()", 5000);
However, I get an error code: Cannot find name 'document'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.
When researching this, I found out that Velo cannot access the dom and elements can only be accessed via "$w".
Would someone be kind enough to set me in the right direction on how to accomplish the "goal" above? I would really appreciate it! Thank you in advance.
Here's how you would do it. Note, that it's good practice to change the IDs of your elements to more descriptive names, but I've stuck with the names you provided in your question.
Start by setting #text45 to hidden in using the Properties & Events panel.
Then use this code (note that your page might already have an onReady. If it's there an you're not using it yet, delete all the code on the page and replace it with this):
$w.onReady( () => {
setTimeout(() => {
$w('#text45').show();
$w('#box2').hide();
}, 5000)
} );
I have my own custom non-jQuery ajax which I use for programming web applications. I recently ran into problems with IE9 using TinyMCE, so am trying to switch to CKeditor
The editable text is being wrapped in a div, like so:
<div id='content'>
<div id='editable' contenteditable='true'>
page of inline text filled with ajax when links throughout the site are clicked
</div>
</div>
When I try to getData on the editable content using the examples in the documentation, I get an error.
I do this:
CKEDITOR.instances.editable.getData();
And get this:
Uncaught TypeError: Cannot call method 'getData' of undefined
So I figure that it doesn't know where the editor is in the dom... I've tried working through all editors to get the editor name, but that doesn't work-- no name appears to be found.
I've tried this:
for(var i in CKEDITOR.instances) {
alert(CKEDITOR.instances[i].name);
}
The alert is just blank-- so there's no name associated with it apparently.
I should also mention, that despite my best efforts, I cannot seem to get the editable text to have a menu appear above it like it does in the Massive Inline Editing Example
Thanks for any assistance you can bring.
Jason Silver
UPDATE:
I'm showing off my lack of knowledge here, but I had never come across "contenteditable='true'" before, so thought that because I was able to type inline, therefore the editor was instantiated somehow... but now I'm wondering if the editor is even being applied to my div.
UPDATE 2:
When the page is loaded and the script is initially called, the div does not exist. The editable div is sent into the DOM using AJAX. #Zee left a comment below that made me wonder if there is some other command that should be called in order to apply the editor to that div, so I created a button in the page with the following onclick as a way to test this approach: (adapted from the ajax example)
var editor,html='';config = {};editor=CKEDITOR.appendTo('editable',config, html );
That gives the following error in Chrome:
> Uncaught TypeError: Cannot call method 'equals' of undefined
> + CKEDITOR.tools.extend.getEditor ckeditor.js:101
> b ckeditor.js:252
> CKEDITOR.appendTo ckeditor.js:257
> onclick www.pediatricjunction.com:410
Am I headed in the right direction? Is there another way to programmatically tell CKEditor to apply the editor to a div?
UPDATE 3:
Thanks to #Reinmar I had something new to try. The most obvious way for me to test to see if this was the solution was to put a button above the content editable div that called CKEDITOR.inlineAll() and inline('editable') respectively:
<input type='button' onclick=\"CKEDITOR.inlineAll();\" value='InlineAll'/>
<input type='button' onclick=\"CKEDITOR.inline('editable');\" value='Inline'/>
<input type='button' onclick=\"var editor = CKEDITOR.inline( document.getElementById( 'editable' ) );\" value='getElementById'/>
This returned the same type of error in Chrome for all three buttons, namely:
Uncaught TypeError: Cannot call method 'equals' of undefined ckeditor.js:101
+ CKEDITOR.tools.extend.getEditor ckeditor.js:101
CKEDITOR.inline ckeditor.js:249
CKEDITOR.inlineAll ckeditor.js:250
onclick
UPDATE 4:
Upon further fiddling, I've tracked down the problem being related to json2007.js, which is a script I use which works with Real Simple History (RSH.js). These scripts have the purpose of tracking ajax history, so as I move forward and back through the browser, the AJAX page views is not lost.
Here's the fiddle page: http://jsfiddle.net/jasonsilver/3CqPv/2/
When you want to initialize inline editor there are two ways:
If element which is editable (has contenteditable attribute) exists when page is loaded CKEditor will automatically initialize an instance for it. Its name will be taken from that element's id or it will be editor<number>. You can find editors initialized automatically on this sample.
If this element is created dynamically, then you need to initialize editor on your own.
E.g. after appending <div id="editor" contenteditable="true">X</div> to the document you should call:
CKEDITOR.inline( 'editor' )
or
CKEDITOR.inlineAll()
See docs and docs.
You can find editor initialized this way on this sample.
The appendTo method has different use. You can initialize themed (not inline) editor inside specified element. This method also accepts data of editor (as 3rd arg), when all other methods (CKEDITOR.inline, CKEDITOR.replace, CKEDITOR.inlineAll) take data from the element they are replacing/using.
Update
I checked that libraries you use together with CKEditor are poorly written and cause errors you mentioned. Remove json2007.js and rsh.js and CKEditor works fine.
OK, so I have tracked down the problem.
The library I was using for tracking Ajax history and remembering commands for the back button, called Real Simple History, was using a script called json2007 which was intrusive and extended native prototypes to the point where things broke.
RSH.js is kind of old, and I wasn't using it to it's full potential anyway, so my final solution was to rewrite the essential code I needed for that, namely, a listener that watched for anchor (hash) changes in the URL, then parsed those changes and resubmitted the ajax command.
var current_hash = window.location.hash;
function check_hash() {
if ( window.location.hash != current_hash ) {
current_hash = window.location.hash;
refreshAjax();
}
}
hashCheck = setInterval( "check_hash()", 50 );
'refreshAjax()' was an existing function anyway, so this is actually a more elegant solution than I was using with Real Simple History.
After stripping out the json2007.js script, everything else just worked, and CKEditor is beautiful.
Thanks so much for your help, #Reinmar... I appreciate your patience and effort.
So, I have this pretty complex ajax thing going.
It loads new html (including div tags and all) to show up on the page.
I included a 'more' link to load additional data.
This more link links to my javascript function. The 'more' link is located in a div, which I gave a unique id. The next time the load function is called, I use document.getElementById(the id).style.display="none"; to "remove" this div from the look of the page.
I set error traps for this, the div with that id is found without problems, but javascript fails to change my style property.
I tested alert(document.getElementById(the id).innerHTML); and that worked without problems - hence the title of the question.
So, does anyone have any ideas/do I need to offer more information? The main problem is that it doesn't throw any errors anywhere, yet it fails to complete the task I asked...
Here's a bit of code to go with it -
try
{
var myidthing = "morelink" + ContentStart.toString(); //the id is correct
var div = document.getElementById(myidthing);
if (!div)
{
}
else
{
div.style.display="none"; //this doesn't work, but doesn't raise an error
alert(div.innerHTML); //this works without problem
}
}
catch(theerr)
{
alert(theerr);
}
------------------------->EDIT<-------------------------
I'm incredibly sorry if I upset any people.
I'm also angry at myself, for it was a stupid thing in my code. Basically, I had a variable that stored the contents of a parent div. Then I (succesfully) removed the div using the removeChild() method. Then my code pasted the contents of that vaiable (including the div I wanted gone) back into the parent div.
I switched around the order and it works fine now.
Again, excuse me for this.
Throwing out a few ideas of things to look for:
You said the div is generated by javascript. Is it possible the div you are targeting is not the one you think you are? It could be you are targeting another div, which is already hidden, or obstructed... or maybe the innerHTML you are displaying goes with a different element than the one you intend to target. Put an alert or script breakpoint in the if(!div) case, also, and see if it's going down that path.
If the above code is only a stripped-down version of your actual code, check your actual code for typos (for example: style.display = "none;";)
Using the FireBug plugin for FireFox, inspect the target element after the operation completes, and make sure that the display: none appears in the style information. If not, use FireBug's debugger to walk through your javascript, and see if you can figure out why.
Use FireBug to break on all script errors, in case there is another error causing this behavior.
Try empty quotes instead of 'none' and see if that works?:
document.getElementById('element_id').style.display="";
Failing that, don't change the style, just add a class which hides the element.
In firefox, I have the following fragment in my .css file
tree (negative){ font-size: 120%; color: green;}
Using javascript, how do I change the rule, to set the color to red?
NOTE:
I do not want to change the element.
I want to change the rule.
Please do not answer with something like
...
element.style.color = 'red';
What you're looking for is the document.styleSheets property, through which you can access your css rules and manipulate them. Most browsers have this property, however the interface is slightly different for IE.
For example, try pasting the following in FF for this page and pressing enter:
javascript:alert(document.styleSheets[0].cssRules[1].cssText)
For me that yields the string "body { line-height: 1; }". There are methods/properties that allow you to manipulate the rules.
Here's a library that abstracts this interface for you (cross-browser): http://code.google.com/p/sheetup/
function changeCSSRule (stylesheetID, selectorName, replacementRules) {
var i, theStylesheet = document.getElementById(stylesheetID).sheet,
thecss = (theStylesheet.cssRules) ? theStylesheet.cssRules : theStylesheet.rules;
for(i=0; i < thecss.length; i++){
if(thecss[i].selectorText == selectorName) {
thecss[i].style.cssText = replacementRules;
}
}
};
You can change CSS rules in style sheets through the CSS Object Model (currently known as DOM Level 2 Style). However, if you literally have "tree (negative)" in your style sheet that rule will be dropped and not appear in the Object Model at all.
As there is no HTML element tree I am going to assume that tree is the id or class of another element.
You would first retrieve the DOM element by id:
var tree = document.getElementById("tree");
Now tree represents your DOM element and you can manipulate it any way you like:
tree.style.color = "red";
Here is a great reference for mapping css properties to their javascript equivalent.
I'm not sure you can do actual class/selector overrides. You would need to target each element that used the .tree class and set the CSS. The quickest and easiest way would be through jQuery (or another similar framework):
$('.tree').each(function() { this.style.color = "red"; });
You could even use the built-in CSS functions:
$('.tree').css('color', 'red');
(I did it the first way to show you how standard JS would do it. The $(...) part is jQuery for selecting all elements with the .tree class. If you're not using jQuery, you'd need alternative code.)
If tree is an ID, not a class (there should only be one on the page) so using getElementById should be fine. Your code should look like the other answer.
for( var i in document.getElementsByTagName("tree") ){
document.getElementsByTagName("tree")[i].style.color = "red";
}
As I said in another answer's comment, I've never seen this done how you want. I've only ever targeted elements the same way as the CSS renderer would and changed each element style.
I did see this though: jQuery.Rule
It sounds like it does what you want but the demo causes my browser to flip out a bit. I'd invite you to look at the source to see it really does do what you want, and if you want to use it without jQ, use it as a starting point.
Edit: yes this should work. It works by appending another <style> tag to the page and writing out your overrides within. It's fairly simple to follow if you wanted to port it to plain JS.
For debugging, you can use Firebug to change the CSS rules on-the-fly.
If you want to change the rendered css rules from one page request to the next then some sort of server-side scripting will be required. Otherwise the original style sheet would simply reload at the next page request.
If you want to use an event on the first page to force the server-side action then you can use AJAX to actually change the CSS rule for the user.
"I want to change the rule so that
when I navigate to the next page, I
don't have to make all the changes
again."
It sounds like what you might want then is a remote request ("ajax") back to the server with the request you want to make, and generate a dynamic stylesheet which is sent back to the client?
How/why is this Firefox specific?
I want to change the rule so that when I navigate to the next page, I don't have to make all the changes again.
There are two approaches I can think of here. Namely client side and/or server side.
Client side:
Store the theme setting into cookies and load them up next time by javascript.
Server side:
If your site have an login system, you may also store the user preference into the database and generate the webpages with this inforamtion in mind next time on.
Utimately, you are still writing things like element.style.color =. But, they should get what you want.
I'm trying to dynamically add some textboxes (input type=text) to a page in javascript and prefill them. The textboxes are coming up, but they are coming up empty. What is the proper way to pre-fill a textbox. Ideally I'd love to use the trick of creating a child div, setting the innerhtml property, and then adding that div to the parent main div but that didn't work. Then I thought I'd use the dom but setting textboxname.value before or after insertion won't work and doing txttextbox.setattribute('value','somevalue') won't work either. Works fine in firefox. What gives? This has to be possible? Here is my code. I know I'm only using string literals, but these will be replaced with the results of a web service call eventually. Below is some code. Oh and how do you format code to show up as you type it? I thought it said to indent four spaces, and I did that but the code is still on one line. Sorry about that.
var table=document.createElement('table');
var tbody=document.createElement('tbody');
var row=document.createElement('tr');
row.appendChild(document.createElement('td').appendChild(document.createTextNode('E-mail')));
var txtEmail=document.createElement('input');
row.appendChild(document.createElement('td').appendChild(txtEmail));
tbody.appendChild(row);
table.appendChild(tbody);
//document.getElementById('additionalEmails').innerHTML="";
document.getElementById('additionalEmails').appendChild(table);
txtEmail.value = 'my text'
Does not work?
You can also use Prototype to do this easily:
document.body.insert(new Element("input", { type: "text", size:20, value:'hello world' }))
I've encountered problems similar to this in the past, and while my memory is a bit fuzzy on why it was happening exactly, I think you may need to make sure the element is actually added to the DOM before modifying its value. e.g:
var txtEmail=document.createElement('input');
document.getElementById('someElementThatAlreadyExists').appendChild(txtEmail);
txtEmail.value = 'sample text';
I ended up solving this problem by injecting the html directly into a page via a child div. That did work, it's just that I am blind and the software I use to read the screen for some stupid reason failed to see the text in the textbox. Go figure. Thanks for the tip on prototype though, if I ever decide not to cheat and add the eleements to the dom directly, I'll do it that way.