<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fa">
	<id>https://source.islamical.org/index.php?action=history&amp;feed=atom&amp;title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C%3AEdittools.js</id>
	<title>مدیاویکی:Edittools.js - تاریخچهٔ نسخه‌ها</title>
	<link rel="self" type="application/atom+xml" href="https://source.islamical.org/index.php?action=history&amp;feed=atom&amp;title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C%3AEdittools.js"/>
	<link rel="alternate" type="text/html" href="https://source.islamical.org/index.php?title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C:Edittools.js&amp;action=history"/>
	<updated>2026-11-10T00:21:58Z</updated>
	<subtitle>تاریخچهٔ نسخه‌ها برای این صفحه در ویکی</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://source.islamical.org/index.php?title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C:Edittools.js&amp;diff=16&amp;oldid=prev</id>
		<title>Mojtabakd: ایجاد اسکریپت</title>
		<link rel="alternate" type="text/html" href="https://source.islamical.org/index.php?title=%D9%85%D8%AF%DB%8C%D8%A7%D9%88%DB%8C%DA%A9%DB%8C:Edittools.js&amp;diff=16&amp;oldid=prev"/>
		<updated>2026-11-03T06:24:24Z</updated>

		<summary type="html">&lt;p&gt;ایجاد اسکریپت&lt;/p&gt;
&lt;p&gt;&lt;b&gt;صفحهٔ تازه&lt;/b&gt;&lt;/p&gt;&lt;div&gt;// &amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
EditTools support: add a selector, change into true buttons, enable for all text input fields&lt;br /&gt;
The special characters to insert are defined at [[MediaWiki:Edittools]].&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
// Globals: getElementsByClassName, addEvent (from wikibits.js)&lt;br /&gt;
&lt;br /&gt;
if ( typeof( EditTools_set_focus ) == &amp;#039;undefined&amp;#039; ) {&lt;br /&gt;
var EditTools_set_focus = true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( typeof( EditTools_set_focus_initially ) == &amp;#039;undefined&amp;#039; ) {&lt;br /&gt;
var EditTools_set_focus_initially = EditTools_set_focus;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( typeof( EditTools_initial_subset ) == &amp;#039;undefined&amp;#039; ) {&lt;br /&gt;
var EditTools_initial_subset = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
var EditTools = {&lt;br /&gt;
createSelector: function() {&lt;br /&gt;
var spec = document.getElementById( &amp;#039;specialchars&amp;#039; );&lt;br /&gt;
if ( !spec ) {&lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
var sb = getElementsByClassName( spec, &amp;#039;p&amp;#039;, &amp;#039;specialbasic&amp;#039; );&lt;br /&gt;
if ( sb.length &amp;lt;= 1 ) {&lt;br /&gt;
return; // Only care if there is more than one&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
var sel = document.createElement( &amp;#039;select&amp;#039; );&lt;br /&gt;
sel.style.display = &amp;#039;inline&amp;#039;;&lt;br /&gt;
// sel.setAttribute( &amp;#039;onchange&amp;#039;, &amp;#039;EditTools.chooseCharSubset( selectedIndex, true );&amp;#039; );&lt;br /&gt;
// Apparently, this doesn&amp;#039;t work on IE6. Use an explicit event handling function instead:&lt;br /&gt;
sel.onchange = EditTools.handleOnchange;&lt;br /&gt;
&lt;br /&gt;
var initial = EditTools_initial_subset;&lt;br /&gt;
if ( isNaN( initial ) || initial &amp;lt; 0 || initial &amp;gt;= sb.length ) {&lt;br /&gt;
initial = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
for ( var i = 0; i &amp;lt; sb.length; i++ ) {&lt;br /&gt;
var o = document.createElement( &amp;#039;option&amp;#039; );&lt;br /&gt;
// Ugh. We have encoded Unicode characters in the names...&lt;br /&gt;
var id = sb[i].id.replace( /.([0-9A-F][0-9A-F])/g, &amp;#039;%$1&amp;#039; ).replace( /_/g, &amp;#039; &amp;#039; );&lt;br /&gt;
if ( i == initial ) {&lt;br /&gt;
o.selected = &amp;#039;selected&amp;#039;;&lt;br /&gt;
}&lt;br /&gt;
o.appendChild( document.createTextNode( decodeURIComponent( id ) ) );&lt;br /&gt;
sel.appendChild( o );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
spec.insertBefore( sel, spec.firstChild );&lt;br /&gt;
&lt;br /&gt;
EditTools.chooseCharSubset(&lt;br /&gt;
initial,&lt;br /&gt;
( mw.config.get(&amp;#039;wgAction&amp;#039;) != &amp;#039;submit&amp;#039; ) &amp;amp;&amp;amp;&lt;br /&gt;
EditTools_set_focus_initially &amp;amp;&amp;amp;&lt;br /&gt;
( mw.config.get(&amp;#039;wgCanonicalNamespace&amp;#039;) != &amp;#039;Special&amp;#039; || mw.config.get(&amp;#039;wgCanonicalSpecialPageName&amp;#039;) != &amp;#039;Upload&amp;#039; )&lt;br /&gt;
);&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
handleOnchange: function( evt ) {&lt;br /&gt;
var e    = evt || window.event;      // W3C, IE&lt;br /&gt;
var node = e.target || e.srcElement; // W3C, IE&lt;br /&gt;
&lt;br /&gt;
EditTools.chooseCharSubset( node.selectedIndex, true );&lt;br /&gt;
return true;&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
chooseCharSubset: function( selected, set_focus ) {&lt;br /&gt;
var sb = getElementsByClassName( document.getElementById( &amp;#039;specialchars&amp;#039; ), &amp;#039;p&amp;#039;, &amp;#039;specialbasic&amp;#039; );&lt;br /&gt;
EditTools.makeButtons( sb[selected] );&lt;br /&gt;
for ( var i = 0; i &amp;lt; sb.length; i++ ) {&lt;br /&gt;
sb[i].style.display = i == selected ? &amp;#039;inline&amp;#039; : &amp;#039;none&amp;#039;;&lt;br /&gt;
}&lt;br /&gt;
if ( set_focus &amp;amp;&amp;amp; EditTools_set_focus ) {&lt;br /&gt;
var txtarea = EditTools.getTextArea();&lt;br /&gt;
if ( txtarea ) {&lt;br /&gt;
txtarea.focus();&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
fixateWidth: function() {&lt;br /&gt;
var edit_bar = document.getElementById( &amp;#039;specialchars&amp;#039; );&lt;br /&gt;
if ( !edit_bar ) {&lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
// Try to fixate the width of that bar, otherwise IE6 may make it wider, which will lead to&lt;br /&gt;
// a table re-layout on the upload form resulting in the right column extending beyond the&lt;br /&gt;
// right edge of the window.&lt;br /&gt;
edit_bar.setAttribute( &amp;#039;width&amp;#039;, &amp;#039;&amp;#039; + ( edit_bar.clientWidth || edit_bar.offsetWidth ) );&lt;br /&gt;
edit_bar.style.maxWidth = &amp;#039;&amp;#039; + ( edit_bar.clientWidth || edit_bar.offsetWidth ) + &amp;#039;px&amp;#039;;&lt;br /&gt;
// If we&amp;#039;re inside a table, fixate the containing table cell, too.&lt;br /&gt;
var parent = edit_bar.parentNode;&lt;br /&gt;
while ( parent &amp;amp;&amp;amp; parent != document.body &amp;amp;&amp;amp; parent.nodeName.toLowerCase() != &amp;#039;td&amp;#039; ) {&lt;br /&gt;
parent = parent.parentNode;&lt;br /&gt;
}&lt;br /&gt;
if ( parent &amp;amp;&amp;amp; parent != document.body ) {&lt;br /&gt;
parent.setAttribute( &amp;#039;width&amp;#039;, &amp;#039;&amp;#039; + ( parent.clientWidth || parent.offsetWidth ) );&lt;br /&gt;
parent.style.maxWidth = &amp;#039;&amp;#039; + ( parent.clientWidth || parent.offsetWidth ) + &amp;#039;px&amp;#039;;&lt;br /&gt;
}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
makeButtons: function( section ) {&lt;br /&gt;
var edit_bar = section || document.getElementById( &amp;#039;specialchars&amp;#039; );&lt;br /&gt;
if ( !edit_bar ) {&lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
var links = edit_bar.getElementsByTagName( &amp;#039;a&amp;#039; );&lt;br /&gt;
// &amp;#039;links&amp;#039; is a *live* collection!&lt;br /&gt;
var b = null;&lt;br /&gt;
while ( links.length ) {&lt;br /&gt;
b = document.createElement( &amp;#039;input&amp;#039; );&lt;br /&gt;
b.type = &amp;#039;button&amp;#039;;&lt;br /&gt;
b.style.fontSize = &amp;#039;0.9em&amp;#039;;&lt;br /&gt;
b.style.paddingLeft = &amp;#039;1px&amp;#039;;&lt;br /&gt;
b.style.paddingRight = &amp;#039;1px&amp;#039;;&lt;br /&gt;
b.style.marginLeft = &amp;#039;1px&amp;#039;;&lt;br /&gt;
b.onclick = links[0].onclick;&lt;br /&gt;
b.value = links[0].firstChild.data;&lt;br /&gt;
var parent = links[0].parentNode;&lt;br /&gt;
parent.replaceChild( b, links[0] ); // This removes links[0] from links!&lt;br /&gt;
b.blur(); // IE6 insists on marking some buttons as having the focus...&lt;br /&gt;
var margin_added = false;&lt;br /&gt;
// Remove text nodes (nodeType == Node.TEXT_NODE, but IE6 doesn&amp;#039;t know that...)&lt;br /&gt;
// Insert some spacing where desired.&lt;br /&gt;
while ( b.nextSibling &amp;amp;&amp;amp; b.nextSibling.nodeType == 3 ) {&lt;br /&gt;
if ( !margin_added &amp;amp;&amp;amp; b.nextSibling.data.search( /\S/ ) &amp;gt;= 0 ) {&lt;br /&gt;
b.style.marginRight = &amp;#039;4px&amp;#039;;&lt;br /&gt;
margin_added = true;&lt;br /&gt;
}&lt;br /&gt;
parent.removeChild( b.nextSibling );&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
enableForAllFields: function() {&lt;br /&gt;
if ( typeof( insertTags ) != &amp;#039;function&amp;#039; ) {&lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
// insertTags from the site-wide /w/skins/common/edit.js just inserts in the first&lt;br /&gt;
// textarea in the document. Evidently, that&amp;#039;s not good if we have multiple textareas.&lt;br /&gt;
// My first idea was to simply add a hidden textarea as the first one, and redefine&lt;br /&gt;
// insertTags such that it copied first the last active textareas contents over to that hidden&lt;br /&gt;
// field, set the cursor or selection there, let the standard insertTags do its thing, and&lt;br /&gt;
// then copy the hidden field&amp;#039;s text, cursor position and selection back to the currently&lt;br /&gt;
// active field. Unfortunately, that is just as complex as simply copying the whole code&lt;br /&gt;
// from wikibits to here and let it work on the right text field in the first place.&lt;br /&gt;
var texts = document.getElementsByTagName( &amp;#039;textarea&amp;#039; );&lt;br /&gt;
for ( var i = 0; i &amp;lt; texts.length; i++ ) {&lt;br /&gt;
$( texts[i] ).focus( EditTools.registerTextField );&lt;br /&gt;
}&lt;br /&gt;
// While we&amp;#039;re at it, also enable it for input fields&lt;br /&gt;
texts = document.getElementsByTagName( &amp;#039;input&amp;#039; );&lt;br /&gt;
for ( var i = 0; i &amp;lt; texts.length; i++ ) {&lt;br /&gt;
if ( texts[i].type == &amp;#039;text&amp;#039; ) {&lt;br /&gt;
$( texts[i] ).focus( EditTools.registerTextField );&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
insertTags = EditTools.insertTags; // Redefine the global insertTags&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
last_active_textfield: null,&lt;br /&gt;
&lt;br /&gt;
registerTextField: function( evt ) {&lt;br /&gt;
var e = evt || window.event;&lt;br /&gt;
var node = e.target || e.srcElement;&lt;br /&gt;
if ( !node ) {&lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
EditTools.last_active_textfield = node.id;&lt;br /&gt;
return true;&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
getTextArea: function() {&lt;br /&gt;
var txtarea = null;&lt;br /&gt;
if ( EditTools.last_active_textfield &amp;amp;&amp;amp; EditTools.last_active_textfield != &amp;#039;&amp;#039; )&lt;br /&gt;
txtarea = document.getElementById( EditTools.last_active_textfield );&lt;br /&gt;
if ( !txtarea ) {&lt;br /&gt;
// Fallback option: old behaviour&lt;br /&gt;
if ( document.editform ) {&lt;br /&gt;
txtarea = document.editform.wpTextbox1;&lt;br /&gt;
} else {&lt;br /&gt;
// Some alternate form? Take the first one we can find&lt;br /&gt;
txtarea = document.getElementsByTagName( &amp;#039;textarea&amp;#039; );&lt;br /&gt;
if ( txtarea.length &amp;gt; 0 ) {&lt;br /&gt;
txtarea = txtarea[0];&lt;br /&gt;
} else {&lt;br /&gt;
txtarea = null;&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
return txtarea;&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
insertTags: function( tagOpen, tagClose, sampleText ) {&lt;br /&gt;
/* Usability initiative compatibility */&lt;br /&gt;
if ( typeof $ != &amp;#039;undefined&amp;#039; &amp;amp;&amp;amp; typeof $.fn.textSelection != &amp;#039;undefined&amp;#039; ) {&lt;br /&gt;
$( &amp;#039;#wpTextbox1&amp;#039; ).textSelection(&lt;br /&gt;
&amp;#039;encapsulateSelection&amp;#039;, { &amp;#039;pre&amp;#039;: tagOpen, &amp;#039;peri&amp;#039;: sampleText, &amp;#039;post&amp;#039;: tagClose }&lt;br /&gt;
);&lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
var txtarea = EditTools.getTextArea ();&lt;br /&gt;
if ( !txtarea ) {&lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
var selText, isSample = false;&lt;br /&gt;
&lt;br /&gt;
function checkSelectedText() {&lt;br /&gt;
if ( !selText ) {&lt;br /&gt;
selText = sampleText;&lt;br /&gt;
isSample = true;&lt;br /&gt;
} else if ( selText.charAt( selText.length - 1 ) == &amp;#039; &amp;#039; ) { // Exclude ending space char&lt;br /&gt;
selText = selText.substring( 0, selText.length - 1 );&lt;br /&gt;
tagClose += &amp;#039; &amp;#039;;&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( document.selection &amp;amp;&amp;amp; document.selection.createRange ) { // IE/Opera&lt;br /&gt;
// Save window scroll position&lt;br /&gt;
var winScroll = 0;&lt;br /&gt;
if ( document.documentElement &amp;amp;&amp;amp; document.documentElement.scrollTop ) {&lt;br /&gt;
winScroll = document.documentElement.scrollTop;&lt;br /&gt;
} else if ( document.body ) {&lt;br /&gt;
winScroll = document.body.scrollTop;&lt;br /&gt;
}&lt;br /&gt;
// Get current selection&lt;br /&gt;
txtarea.focus();&lt;br /&gt;
var range = document.selection.createRange();&lt;br /&gt;
selText = range.text;&lt;br /&gt;
// Insert tags&lt;br /&gt;
checkSelectedText ();&lt;br /&gt;
range.text = tagOpen + selText + tagClose;&lt;br /&gt;
// Mark sample text as selected&lt;br /&gt;
if ( isSample &amp;amp;&amp;amp; range.moveStart ) {&lt;br /&gt;
if ( window.opera ) {&lt;br /&gt;
tagClose = tagClose.replace( /\n/g, &amp;#039;&amp;#039; );&lt;br /&gt;
}&lt;br /&gt;
range.moveStart( &amp;#039;character&amp;#039;, - tagClose.length - selText.length );&lt;br /&gt;
range.moveEnd( &amp;#039;character&amp;#039;, - tagClose.length );&lt;br /&gt;
}&lt;br /&gt;
range.select();&lt;br /&gt;
// Restore window scroll position&lt;br /&gt;
if ( document.documentElement &amp;amp;&amp;amp; document.documentElement.scrollTop ) {&lt;br /&gt;
document.documentElement.scrollTop = winScroll;&lt;br /&gt;
} else if ( document.body ) {&lt;br /&gt;
document.body.scrollTop = winScroll;&lt;br /&gt;
}&lt;br /&gt;
} else if ( txtarea.selectionStart || txtarea.selectionStart == &amp;#039;0&amp;#039; ) { // Mozilla&lt;br /&gt;
// Save textarea scroll position&lt;br /&gt;
var textScroll = txtarea.scrollTop;&lt;br /&gt;
// Get current selection&lt;br /&gt;
txtarea.focus();&lt;br /&gt;
var startPos = txtarea.selectionStart;&lt;br /&gt;
var endPos   = txtarea.selectionEnd;&lt;br /&gt;
selText = txtarea.value.substring( startPos, endPos );&lt;br /&gt;
// Insert tags&lt;br /&gt;
checkSelectedText();&lt;br /&gt;
txtarea.value = txtarea.value.substring( 0, startPos ) +&lt;br /&gt;
tagOpen + selText + tagClose +&lt;br /&gt;
txtarea.value.substring( endPos );&lt;br /&gt;
// Set new selection&lt;br /&gt;
if ( isSample ) {&lt;br /&gt;
txtarea.selectionStart = startPos + tagOpen.length;&lt;br /&gt;
txtarea.selectionEnd = startPos + tagOpen.length + selText.length;&lt;br /&gt;
} else {&lt;br /&gt;
txtarea.selectionStart = startPos + tagOpen.length + selText.length + tagClose.length;&lt;br /&gt;
txtarea.selectionEnd = txtarea.selectionStart;&lt;br /&gt;
}&lt;br /&gt;
// Restore textarea scroll position&lt;br /&gt;
txtarea.scrollTop = textScroll;&lt;br /&gt;
}&lt;br /&gt;
}, // end insertTags&lt;br /&gt;
&lt;br /&gt;
setup: function() {&lt;br /&gt;
EditTools.fixateWidth();&lt;br /&gt;
EditTools.createSelector();&lt;br /&gt;
EditTools.enableForAllFields();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} // end EditTools&lt;br /&gt;
&lt;br /&gt;
// Do not use addOnloadHook; it runs *before* the onload event fires. At that time, onclick or&lt;br /&gt;
// onfocus handlers may not yet be set up properly.&lt;br /&gt;
// FIXME: This has been broken since 2015&lt;br /&gt;
//unknown(EditTools.setup);&lt;br /&gt;
&lt;br /&gt;
// &amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mojtabakd</name></author>
	</entry>
</feed>