Version Description
- Major update of the code
- Fixed all reported bugs
- Performance improvements
- Many new features
- If oyu like this update please rate the plugin!
Download this release
Release Info
Developer | freediver |
Plugin | SEO Smart Links |
Version | 3.0 |
Comparing to | |
See all releases |
Code changes from version 2.7.8 to 3.0
- i/asc.gif +0 -0
- i/bg.gif +0 -0
- i/bin.gif +0 -0
- i/desc.gif +0 -0
- i/first.png +0 -0
- i/help.png +0 -0
- i/home.png +0 -0
- i/icon.png +0 -0
- i/last.png +0 -0
- i/logo.png +0 -0
- i/more.png +0 -0
- i/mwp250_2.png +0 -0
- i/next.png +0 -0
- i/p1.png +0 -0
- i/page_edit.gif +0 -0
- i/paypal.gif +0 -0
- i/prev.png +0 -0
- i/seoimages125_v2.jpg +0 -0
- i/seosmart125.png +0 -0
- i/twit.png +0 -0
- js/filter.js +92 -0
- js/jquery.tablednd_0_5.js +382 -0
- js/pager.js +189 -0
- js/quicksearch.js +146 -0
- js/seo-links.js +251 -0
- js/tablesorter.js +852 -0
- readme.txt +9 -2
- seo-links.php +1752 -675
- sml.css +128 -0
i/asc.gif
ADDED
Binary file
|
i/bg.gif
ADDED
Binary file
|
i/bin.gif
ADDED
Binary file
|
i/desc.gif
ADDED
Binary file
|
i/first.png
ADDED
Binary file
|
i/help.png
DELETED
Binary file
|
i/home.png
DELETED
Binary file
|
i/icon.png
ADDED
Binary file
|
i/last.png
ADDED
Binary file
|
i/logo.png
ADDED
Binary file
|
i/more.png
DELETED
Binary file
|
i/mwp250_2.png
ADDED
Binary file
|
i/next.png
ADDED
Binary file
|
i/p1.png
DELETED
Binary file
|
i/page_edit.gif
ADDED
Binary file
|
i/paypal.gif
DELETED
Binary file
|
i/prev.png
ADDED
Binary file
|
i/seoimages125_v2.jpg
ADDED
Binary file
|
i/seosmart125.png
ADDED
Binary file
|
i/twit.png
DELETED
Binary file
|
js/filter.js
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* Copyright (c) 2008 Greg Weber greg at gregweber.info
|
3 |
+
* Dual licensed under the MIT and GPL licenses:
|
4 |
+
* http://www.opensource.org/licenses/mit-license.php
|
5 |
+
* http://www.gnu.org/licenses/gpl.html
|
6 |
+
*
|
7 |
+
* documentation at http://gregweber.info/projects/uitablefilter
|
8 |
+
*
|
9 |
+
* allows table rows to be filtered (made invisible)
|
10 |
+
* <code>
|
11 |
+
* t = jQuery('table')
|
12 |
+
* jQuery.uiTableFilter( t, phrase )
|
13 |
+
* </code>
|
14 |
+
* arguments:
|
15 |
+
* jQuery object containing table rows
|
16 |
+
* phrase to search for
|
17 |
+
* optional arguments:
|
18 |
+
* column to limit search too (the column title in the table header)
|
19 |
+
* ifHidden - callback to execute if one or more elements was hidden
|
20 |
+
*/
|
21 |
+
(function(jQuery) {
|
22 |
+
jQuery.uiTableFilter = function(jq, phrase, column, ifHidden){
|
23 |
+
var new_hidden = false;
|
24 |
+
if( this.last_phrase === phrase ) return false;
|
25 |
+
|
26 |
+
var phrase_length = phrase.length;
|
27 |
+
var words = phrase.toLowerCase().split(" ");
|
28 |
+
|
29 |
+
// these function pointers may change
|
30 |
+
var matches = function(elem) { elem.show() }
|
31 |
+
var noMatch = function(elem) { elem.hide(); new_hidden = true }
|
32 |
+
var getText = function(elem) { return elem.text() }
|
33 |
+
|
34 |
+
if( column ) {
|
35 |
+
var index = null;
|
36 |
+
jq.find("thead > tr:last > th").each( function(i){
|
37 |
+
if( jQuery.trim(jQuery(this).text()) == column ){
|
38 |
+
index = i; return false;
|
39 |
+
}
|
40 |
+
});
|
41 |
+
if( index == null ) throw("given column: " + column + " not found")
|
42 |
+
|
43 |
+
getText = function(elem){ return jQuery(elem.find(
|
44 |
+
("td:eq(" + index + ")") )).text()
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
// if added one letter to last time,
|
49 |
+
// just check newest word and only need to hide
|
50 |
+
if( (words.size > 1) && (phrase.substr(0, phrase_length - 1) ===
|
51 |
+
this.last_phrase) ) {
|
52 |
+
|
53 |
+
if( phrase[-1] === " " )
|
54 |
+
{ this.last_phrase = phrase; return false; }
|
55 |
+
|
56 |
+
var words = words[-1]; // just search for the newest word
|
57 |
+
|
58 |
+
// only hide visible rows
|
59 |
+
matches = function(elem) {;}
|
60 |
+
var elems = jq.find("tbody > tr:visible")
|
61 |
+
}
|
62 |
+
else {
|
63 |
+
new_hidden = true;
|
64 |
+
var elems = jq.find("tbody > tr")
|
65 |
+
}
|
66 |
+
|
67 |
+
elems.each(function(){
|
68 |
+
var elem = jQuery(this);
|
69 |
+
jQuery.uiTableFilter.has_words( getText(elem), words, false ) ?
|
70 |
+
matches(elem) : noMatch(elem);
|
71 |
+
});
|
72 |
+
|
73 |
+
last_phrase = phrase;
|
74 |
+
if( ifHidden && new_hidden ) ifHidden();
|
75 |
+
return jq;
|
76 |
+
};
|
77 |
+
|
78 |
+
// caching for speedup
|
79 |
+
jQuery.uiTableFilter.last_phrase = ""
|
80 |
+
|
81 |
+
// not jQuery dependent
|
82 |
+
// "" [""] -> Boolean
|
83 |
+
// "" [""] Boolean -> Boolean
|
84 |
+
jQuery.uiTableFilter.has_words = function( str, words, caseSensitive )
|
85 |
+
{
|
86 |
+
var text = caseSensitive ? str : str.toLowerCase();
|
87 |
+
for (var i=0; i < words.length; i++) {
|
88 |
+
if (text.indexOf(words[i]) === -1) return false;
|
89 |
+
}
|
90 |
+
return true;
|
91 |
+
}
|
92 |
+
}) (jQuery);
|
js/jquery.tablednd_0_5.js
ADDED
@@ -0,0 +1,382 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* TableDnD plug-in for JQuery, allows you to drag and drop table rows
|
3 |
+
* You can set up various options to control how the system will work
|
4 |
+
* Copyright (c) Denis Howlett <denish@isocra.com>
|
5 |
+
* Licensed like jQuery, see http://docs.jquery.com/License.
|
6 |
+
*
|
7 |
+
* Configuration options:
|
8 |
+
*
|
9 |
+
* onDragStyle
|
10 |
+
* This is the style that is assigned to the row during drag. There are limitations to the styles that can be
|
11 |
+
* associated with a row (such as you can't assign a border--well you can, but it won't be
|
12 |
+
* displayed). (So instead consider using onDragClass.) The CSS style to apply is specified as
|
13 |
+
* a map (as used in the jQuery css(...) function).
|
14 |
+
* onDropStyle
|
15 |
+
* This is the style that is assigned to the row when it is dropped. As for onDragStyle, there are limitations
|
16 |
+
* to what you can do. Also this replaces the original style, so again consider using onDragClass which
|
17 |
+
* is simply added and then removed on drop.
|
18 |
+
* onDragClass
|
19 |
+
* This class is added for the duration of the drag and then removed when the row is dropped. It is more
|
20 |
+
* flexible than using onDragStyle since it can be inherited by the row cells and other content. The default
|
21 |
+
* is class is tDnD_whileDrag. So to use the default, simply customise this CSS class in your
|
22 |
+
* stylesheet.
|
23 |
+
* onDrop
|
24 |
+
* Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table
|
25 |
+
* and the row that was dropped. You can work out the new order of the rows by using
|
26 |
+
* table.rows.
|
27 |
+
* onDragStart
|
28 |
+
* Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the
|
29 |
+
* table and the row which the user has started to drag.
|
30 |
+
* onAllowDrop
|
31 |
+
* Pass a function that will be called as a row is over another row. If the function returns true, allow
|
32 |
+
* dropping on that row, otherwise not. The function takes 2 parameters: the dragged row and the row under
|
33 |
+
* the cursor. It returns a boolean: true allows the drop, false doesn't allow it.
|
34 |
+
* scrollAmount
|
35 |
+
* This is the number of pixels to scroll if the user moves the mouse cursor to the top or bottom of the
|
36 |
+
* window. The page should automatically scroll up or down as appropriate (tested in IE6, IE7, Safari, FF2,
|
37 |
+
* FF3 beta
|
38 |
+
* dragHandle
|
39 |
+
* This is the name of a class that you assign to one or more cells in each row that is draggable. If you
|
40 |
+
* specify this class, then you are responsible for setting cursor: move in the CSS and only these cells
|
41 |
+
* will have the drag behaviour. If you do not specify a dragHandle, then you get the old behaviour where
|
42 |
+
* the whole row is draggable.
|
43 |
+
*
|
44 |
+
* Other ways to control behaviour:
|
45 |
+
*
|
46 |
+
* Add class="nodrop" to any rows for which you don't want to allow dropping, and class="nodrag" to any rows
|
47 |
+
* that you don't want to be draggable.
|
48 |
+
*
|
49 |
+
* Inside the onDrop method you can also call $.tableDnD.serialize() this returns a string of the form
|
50 |
+
* <tableID>[]=<rowID1>&<tableID>[]=<rowID2> so that you can send this back to the server. The table must have
|
51 |
+
* an ID as must all the rows.
|
52 |
+
*
|
53 |
+
* Other methods:
|
54 |
+
*
|
55 |
+
* $("...").tableDnDUpdate()
|
56 |
+
* Will update all the matching tables, that is it will reapply the mousedown method to the rows (or handle cells).
|
57 |
+
* This is useful if you have updated the table rows using Ajax and you want to make the table draggable again.
|
58 |
+
* The table maintains the original configuration (so you don't have to specify it again).
|
59 |
+
*
|
60 |
+
* $("...").tableDnDSerialize()
|
61 |
+
* Will serialize and return the serialized string as above, but for each of the matching tables--so it can be
|
62 |
+
* called from anywhere and isn't dependent on the currentTable being set up correctly before calling
|
63 |
+
*
|
64 |
+
* Known problems:
|
65 |
+
* - Auto-scoll has some problems with IE7 (it scrolls even when it shouldn't), work-around: set scrollAmount to 0
|
66 |
+
*
|
67 |
+
* Version 0.2: 2008-02-20 First public version
|
68 |
+
* Version 0.3: 2008-02-07 Added onDragStart option
|
69 |
+
* Made the scroll amount configurable (default is 5 as before)
|
70 |
+
* Version 0.4: 2008-03-15 Changed the noDrag/noDrop attributes to nodrag/nodrop classes
|
71 |
+
* Added onAllowDrop to control dropping
|
72 |
+
* Fixed a bug which meant that you couldn't set the scroll amount in both directions
|
73 |
+
* Added serialize method
|
74 |
+
* Version 0.5: 2008-05-16 Changed so that if you specify a dragHandle class it doesn't make the whole row
|
75 |
+
* draggable
|
76 |
+
* Improved the serialize method to use a default (and settable) regular expression.
|
77 |
+
* Added tableDnDupate() and tableDnDSerialize() to be called when you are outside the table
|
78 |
+
*/
|
79 |
+
jQuery.tableDnD = {
|
80 |
+
/** Keep hold of the current table being dragged */
|
81 |
+
currentTable : null,
|
82 |
+
/** Keep hold of the current drag object if any */
|
83 |
+
dragObject: null,
|
84 |
+
/** The current mouse offset */
|
85 |
+
mouseOffset: null,
|
86 |
+
/** Remember the old value of Y so that we don't do too much processing */
|
87 |
+
oldY: 0,
|
88 |
+
|
89 |
+
/** Actually build the structure */
|
90 |
+
build: function(options) {
|
91 |
+
// Set up the defaults if any
|
92 |
+
|
93 |
+
this.each(function() {
|
94 |
+
// This is bound to each matching table, set up the defaults and override with user options
|
95 |
+
this.tableDnDConfig = jQuery.extend({
|
96 |
+
onDragStyle: null,
|
97 |
+
onDropStyle: null,
|
98 |
+
// Add in the default class for whileDragging
|
99 |
+
onDragClass: "tDnD_whileDrag",
|
100 |
+
onDrop: null,
|
101 |
+
onDragStart: null,
|
102 |
+
scrollAmount: 5,
|
103 |
+
serializeRegexp: /[^\-]*$/, // The regular expression to use to trim row IDs
|
104 |
+
serializeParamName: null, // If you want to specify another parameter name instead of the table ID
|
105 |
+
dragHandle: null // If you give the name of a class here, then only Cells with this class will be draggable
|
106 |
+
}, options || {});
|
107 |
+
// Now make the rows draggable
|
108 |
+
jQuery.tableDnD.makeDraggable(this);
|
109 |
+
});
|
110 |
+
|
111 |
+
// Now we need to capture the mouse up and mouse move event
|
112 |
+
// We can use bind so that we don't interfere with other event handlers
|
113 |
+
jQuery(document)
|
114 |
+
.bind('mousemove', jQuery.tableDnD.mousemove)
|
115 |
+
.bind('mouseup', jQuery.tableDnD.mouseup);
|
116 |
+
|
117 |
+
// Don't break the chain
|
118 |
+
return this;
|
119 |
+
},
|
120 |
+
|
121 |
+
/** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */
|
122 |
+
makeDraggable: function(table) {
|
123 |
+
var config = table.tableDnDConfig;
|
124 |
+
if (table.tableDnDConfig.dragHandle) {
|
125 |
+
// We only need to add the event to the specified cells
|
126 |
+
var cells = jQuery("td."+table.tableDnDConfig.dragHandle, table);
|
127 |
+
cells.each(function() {
|
128 |
+
// The cell is bound to "this"
|
129 |
+
jQuery(this).mousedown(function(ev) {
|
130 |
+
jQuery.tableDnD.dragObject = this.parentNode;
|
131 |
+
jQuery.tableDnD.currentTable = table;
|
132 |
+
jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
|
133 |
+
if (config.onDragStart) {
|
134 |
+
// Call the onDrop method if there is one
|
135 |
+
config.onDragStart(table, this);
|
136 |
+
}
|
137 |
+
return false;
|
138 |
+
});
|
139 |
+
})
|
140 |
+
} else {
|
141 |
+
// For backwards compatibility, we add the event to the whole row
|
142 |
+
var rows = jQuery("tr", table); // get all the rows as a wrapped set
|
143 |
+
rows.each(function() {
|
144 |
+
// Iterate through each row, the row is bound to "this"
|
145 |
+
var row = jQuery(this);
|
146 |
+
if (! row.hasClass("nodrag")) {
|
147 |
+
row.mousedown(function(ev) {
|
148 |
+
if (ev.target.tagName == "TD") {
|
149 |
+
jQuery.tableDnD.dragObject = this;
|
150 |
+
jQuery.tableDnD.currentTable = table;
|
151 |
+
jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
|
152 |
+
if (config.onDragStart) {
|
153 |
+
// Call the onDrop method if there is one
|
154 |
+
config.onDragStart(table, this);
|
155 |
+
}
|
156 |
+
return false;
|
157 |
+
}
|
158 |
+
}).css("cursor", "move"); // Store the tableDnD object
|
159 |
+
}
|
160 |
+
});
|
161 |
+
}
|
162 |
+
},
|
163 |
+
|
164 |
+
updateTables: function() {
|
165 |
+
this.each(function() {
|
166 |
+
// this is now bound to each matching table
|
167 |
+
if (this.tableDnDConfig) {
|
168 |
+
jQuery.tableDnD.makeDraggable(this);
|
169 |
+
}
|
170 |
+
})
|
171 |
+
},
|
172 |
+
|
173 |
+
/** Get the mouse coordinates from the event (allowing for browser differences) */
|
174 |
+
mouseCoords: function(ev){
|
175 |
+
if(ev.pageX || ev.pageY){
|
176 |
+
return {x:ev.pageX, y:ev.pageY};
|
177 |
+
}
|
178 |
+
return {
|
179 |
+
x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
|
180 |
+
y:ev.clientY + document.body.scrollTop - document.body.clientTop
|
181 |
+
};
|
182 |
+
},
|
183 |
+
|
184 |
+
/** Given a target element and a mouse event, get the mouse offset from that element.
|
185 |
+
To do this we need the element's position and the mouse position */
|
186 |
+
getMouseOffset: function(target, ev) {
|
187 |
+
ev = ev || window.event;
|
188 |
+
|
189 |
+
var docPos = this.getPosition(target);
|
190 |
+
var mousePos = this.mouseCoords(ev);
|
191 |
+
return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
|
192 |
+
},
|
193 |
+
|
194 |
+
/** Get the position of an element by going up the DOM tree and adding up all the offsets */
|
195 |
+
getPosition: function(e){
|
196 |
+
var left = 0;
|
197 |
+
var top = 0;
|
198 |
+
/** Safari fix -- thanks to Luis Chato for this! */
|
199 |
+
if (e.offsetHeight == 0) {
|
200 |
+
/** Safari 2 doesn't correctly grab the offsetTop of a table row
|
201 |
+
this is detailed here:
|
202 |
+
http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/
|
203 |
+
the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild.
|
204 |
+
note that firefox will return a text node as a first child, so designing a more thorough
|
205 |
+
solution may need to take that into account, for now this seems to work in firefox, safari, ie */
|
206 |
+
e = e.firstChild; // a table cell
|
207 |
+
}
|
208 |
+
|
209 |
+
while (e.offsetParent){
|
210 |
+
left += e.offsetLeft;
|
211 |
+
top += e.offsetTop;
|
212 |
+
e = e.offsetParent;
|
213 |
+
}
|
214 |
+
|
215 |
+
left += e.offsetLeft;
|
216 |
+
top += e.offsetTop;
|
217 |
+
|
218 |
+
return {x:left, y:top};
|
219 |
+
},
|
220 |
+
|
221 |
+
mousemove: function(ev) {
|
222 |
+
if (jQuery.tableDnD.dragObject == null) {
|
223 |
+
return;
|
224 |
+
}
|
225 |
+
|
226 |
+
var dragObj = jQuery(jQuery.tableDnD.dragObject);
|
227 |
+
var config = jQuery.tableDnD.currentTable.tableDnDConfig;
|
228 |
+
var mousePos = jQuery.tableDnD.mouseCoords(ev);
|
229 |
+
var y = mousePos.y - jQuery.tableDnD.mouseOffset.y;
|
230 |
+
//auto scroll the window
|
231 |
+
var yOffset = window.pageYOffset;
|
232 |
+
if (document.all) {
|
233 |
+
// Windows version
|
234 |
+
//yOffset=document.body.scrollTop;
|
235 |
+
if (typeof document.compatMode != 'undefined' &&
|
236 |
+
document.compatMode != 'BackCompat') {
|
237 |
+
yOffset = document.documentElement.scrollTop;
|
238 |
+
}
|
239 |
+
else if (typeof document.body != 'undefined') {
|
240 |
+
yOffset=document.body.scrollTop;
|
241 |
+
}
|
242 |
+
|
243 |
+
}
|
244 |
+
|
245 |
+
if (mousePos.y-yOffset < config.scrollAmount) {
|
246 |
+
window.scrollBy(0, -config.scrollAmount);
|
247 |
+
} else {
|
248 |
+
var windowHeight = window.innerHeight ? window.innerHeight
|
249 |
+
: document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;
|
250 |
+
if (windowHeight-(mousePos.y-yOffset) < config.scrollAmount) {
|
251 |
+
window.scrollBy(0, config.scrollAmount);
|
252 |
+
}
|
253 |
+
}
|
254 |
+
|
255 |
+
|
256 |
+
if (y != jQuery.tableDnD.oldY) {
|
257 |
+
// work out if we're going up or down...
|
258 |
+
var movingDown = y > jQuery.tableDnD.oldY;
|
259 |
+
// update the old value
|
260 |
+
jQuery.tableDnD.oldY = y;
|
261 |
+
// update the style to show we're dragging
|
262 |
+
if (config.onDragClass) {
|
263 |
+
dragObj.addClass(config.onDragClass);
|
264 |
+
} else {
|
265 |
+
dragObj.css(config.onDragStyle);
|
266 |
+
}
|
267 |
+
// If we're over a row then move the dragged row to there so that the user sees the
|
268 |
+
// effect dynamically
|
269 |
+
var currentRow = jQuery.tableDnD.findDropTargetRow(dragObj, y);
|
270 |
+
if (currentRow) {
|
271 |
+
// TODO worry about what happens when there are multiple TBODIES
|
272 |
+
if (movingDown && jQuery.tableDnD.dragObject != currentRow) {
|
273 |
+
jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow.nextSibling);
|
274 |
+
} else if (! movingDown && jQuery.tableDnD.dragObject != currentRow) {
|
275 |
+
jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow);
|
276 |
+
}
|
277 |
+
}
|
278 |
+
}
|
279 |
+
|
280 |
+
return false;
|
281 |
+
},
|
282 |
+
|
283 |
+
/** We're only worried about the y position really, because we can only move rows up and down */
|
284 |
+
findDropTargetRow: function(draggedRow, y) {
|
285 |
+
var rows = jQuery.tableDnD.currentTable.rows;
|
286 |
+
for (var i=0; i<rows.length; i++) {
|
287 |
+
var row = rows[i];
|
288 |
+
var rowY = this.getPosition(row).y;
|
289 |
+
var rowHeight = parseInt(row.offsetHeight)/2;
|
290 |
+
if (row.offsetHeight == 0) {
|
291 |
+
rowY = this.getPosition(row.firstChild).y;
|
292 |
+
rowHeight = parseInt(row.firstChild.offsetHeight)/2;
|
293 |
+
}
|
294 |
+
// Because we always have to insert before, we need to offset the height a bit
|
295 |
+
if ((y > rowY - rowHeight) && (y < (rowY + rowHeight))) {
|
296 |
+
// that's the row we're over
|
297 |
+
// If it's the same as the current row, ignore it
|
298 |
+
if (row == draggedRow) {return null;}
|
299 |
+
var config = jQuery.tableDnD.currentTable.tableDnDConfig;
|
300 |
+
if (config.onAllowDrop) {
|
301 |
+
if (config.onAllowDrop(draggedRow, row)) {
|
302 |
+
return row;
|
303 |
+
} else {
|
304 |
+
return null;
|
305 |
+
}
|
306 |
+
} else {
|
307 |
+
// If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic)
|
308 |
+
var nodrop = jQuery(row).hasClass("nodrop");
|
309 |
+
if (! nodrop) {
|
310 |
+
return row;
|
311 |
+
} else {
|
312 |
+
return null;
|
313 |
+
}
|
314 |
+
}
|
315 |
+
return row;
|
316 |
+
}
|
317 |
+
}
|
318 |
+
return null;
|
319 |
+
},
|
320 |
+
|
321 |
+
mouseup: function(e) {
|
322 |
+
if (jQuery.tableDnD.currentTable && jQuery.tableDnD.dragObject) {
|
323 |
+
var droppedRow = jQuery.tableDnD.dragObject;
|
324 |
+
var config = jQuery.tableDnD.currentTable.tableDnDConfig;
|
325 |
+
// If we have a dragObject, then we need to release it,
|
326 |
+
// The row will already have been moved to the right place so we just reset stuff
|
327 |
+
if (config.onDragClass) {
|
328 |
+
jQuery(droppedRow).removeClass(config.onDragClass);
|
329 |
+
} else {
|
330 |
+
jQuery(droppedRow).css(config.onDropStyle);
|
331 |
+
}
|
332 |
+
jQuery.tableDnD.dragObject = null;
|
333 |
+
if (config.onDrop) {
|
334 |
+
// Call the onDrop method if there is one
|
335 |
+
config.onDrop(jQuery.tableDnD.currentTable, droppedRow);
|
336 |
+
}
|
337 |
+
jQuery.tableDnD.currentTable = null; // let go of the table too
|
338 |
+
}
|
339 |
+
},
|
340 |
+
|
341 |
+
serialize: function() {
|
342 |
+
if (jQuery.tableDnD.currentTable) {
|
343 |
+
return jQuery.tableDnD.serializeTable(jQuery.tableDnD.currentTable);
|
344 |
+
} else {
|
345 |
+
return "Error: No Table id set, you need to set an id on your table and every row";
|
346 |
+
}
|
347 |
+
},
|
348 |
+
|
349 |
+
serializeTable: function(table) {
|
350 |
+
var result = "";
|
351 |
+
var tableId = table.id;
|
352 |
+
var rows = table.rows;
|
353 |
+
for (var i=0; i<rows.length; i++) {
|
354 |
+
if (result.length > 0) result += "&";
|
355 |
+
var rowId = rows[i].id;
|
356 |
+
if (rowId && rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) {
|
357 |
+
rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0];
|
358 |
+
}
|
359 |
+
|
360 |
+
result += tableId + '[]=' + rowId;
|
361 |
+
}
|
362 |
+
return result;
|
363 |
+
},
|
364 |
+
|
365 |
+
serializeTables: function() {
|
366 |
+
var result = "";
|
367 |
+
this.each(function() {
|
368 |
+
// this is now bound to each matching table
|
369 |
+
result += jQuery.tableDnD.serializeTable(this);
|
370 |
+
});
|
371 |
+
return result;
|
372 |
+
}
|
373 |
+
|
374 |
+
}
|
375 |
+
|
376 |
+
jQuery.fn.extend(
|
377 |
+
{
|
378 |
+
tableDnD : jQuery.tableDnD.build,
|
379 |
+
tableDnDUpdate : jQuery.tableDnD.updateTables,
|
380 |
+
tableDnDSerialize: jQuery.tableDnD.serializeTables
|
381 |
+
}
|
382 |
+
);
|
js/pager.js
ADDED
@@ -0,0 +1,189 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
(function(jQuery) {
|
2 |
+
jQuery.extend({
|
3 |
+
tablesorterPager: new function() {
|
4 |
+
|
5 |
+
function updatePageDisplay(c) {
|
6 |
+
|
7 |
+
var s = jQuery(c.cssPageDisplay,c.container).val((c.page+1) + c.seperator + c.totalPages);
|
8 |
+
|
9 |
+
}
|
10 |
+
|
11 |
+
function setPageSize(table,size) {
|
12 |
+
var c = table.config;
|
13 |
+
c.size = size;
|
14 |
+
c.totalPages = Math.ceil(c.totalRows / c.size);
|
15 |
+
c.pagerPositionSet = false;
|
16 |
+
moveToPage(table);
|
17 |
+
fixPosition(table);
|
18 |
+
}
|
19 |
+
|
20 |
+
function fixPosition(table) {
|
21 |
+
var c = table.config;
|
22 |
+
if(!c.pagerPositionSet && c.positionFixed) {
|
23 |
+
var c = table.config, o = jQuery(table);
|
24 |
+
if(o.offset) {
|
25 |
+
c.container.css({
|
26 |
+
top: o.offset().top + o.height() + 'px',
|
27 |
+
position: 'absolute'
|
28 |
+
});
|
29 |
+
}
|
30 |
+
c.pagerPositionSet = true;
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
function moveToFirstPage(table) {
|
35 |
+
var c = table.config;
|
36 |
+
c.page = 0;
|
37 |
+
moveToPage(table);
|
38 |
+
}
|
39 |
+
|
40 |
+
function moveToLastPage(table) {
|
41 |
+
var c = table.config;
|
42 |
+
|
43 |
+
c.page = (c.totalPages-1);
|
44 |
+
moveToPage(table);
|
45 |
+
}
|
46 |
+
|
47 |
+
function moveToNextPage(table) {
|
48 |
+
var c = table.config;
|
49 |
+
c.page++;
|
50 |
+
|
51 |
+
if(c.page >= (c.totalPages-1)) {
|
52 |
+
c.page = (c.totalPages-1);
|
53 |
+
}
|
54 |
+
moveToPage(table);
|
55 |
+
}
|
56 |
+
|
57 |
+
function moveToPrevPage(table) {
|
58 |
+
var c = table.config;
|
59 |
+
|
60 |
+
c.page--;
|
61 |
+
if(c.page <= 0) {
|
62 |
+
c.page = 0;
|
63 |
+
}
|
64 |
+
moveToPage(table);
|
65 |
+
}
|
66 |
+
|
67 |
+
|
68 |
+
function moveToPage(table) {
|
69 |
+
var c = table.config;
|
70 |
+
if(c.page < 0 || c.page > (c.totalPages-1)) {
|
71 |
+
c.page = 0;
|
72 |
+
}
|
73 |
+
|
74 |
+
renderTable(table,c.rowsCopy);
|
75 |
+
}
|
76 |
+
|
77 |
+
function renderTable(table,rows) {
|
78 |
+
|
79 |
+
var c = table.config;
|
80 |
+
var l = rows.length;
|
81 |
+
var s = (c.page * c.size);
|
82 |
+
var e = (s + c.size);
|
83 |
+
if(e > rows.length ) {
|
84 |
+
e = rows.length;
|
85 |
+
}
|
86 |
+
//alert(c.size);
|
87 |
+
|
88 |
+
var tableBody = jQuery(table.tBodies[0]);
|
89 |
+
|
90 |
+
// clear the table body
|
91 |
+
|
92 |
+
jQuery.tablesorter.clearTableBody(table);
|
93 |
+
|
94 |
+
for(var i = s; i < e; i++) {
|
95 |
+
|
96 |
+
//tableBody.append(rows[i]);
|
97 |
+
|
98 |
+
var o = rows[i];
|
99 |
+
var l = o.length;
|
100 |
+
for(var j=0; j < l; j++) {
|
101 |
+
|
102 |
+
tableBody[0].appendChild(o[j]);
|
103 |
+
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
fixPosition(table,tableBody);
|
108 |
+
|
109 |
+
jQuery(table).trigger("applyWidgets");
|
110 |
+
|
111 |
+
if( c.page >= c.totalPages ) {
|
112 |
+
moveToLastPage(table);
|
113 |
+
}
|
114 |
+
|
115 |
+
updatePageDisplay(c);
|
116 |
+
}
|
117 |
+
|
118 |
+
this.appender = function(table,rows) {
|
119 |
+
|
120 |
+
var c = table.config;
|
121 |
+
|
122 |
+
c.rowsCopy = rows;
|
123 |
+
c.totalRows = rows.length;
|
124 |
+
c.totalPages = Math.ceil(c.totalRows / c.size);
|
125 |
+
|
126 |
+
renderTable(table,rows);
|
127 |
+
};
|
128 |
+
|
129 |
+
this.defaults = {
|
130 |
+
size: 25,
|
131 |
+
offset: 0,
|
132 |
+
page: 0,
|
133 |
+
totalRows: 0,
|
134 |
+
totalPages: 0,
|
135 |
+
container: null,
|
136 |
+
cssNext: '.next',
|
137 |
+
cssPrev: '.prev',
|
138 |
+
cssFirst: '.first',
|
139 |
+
cssLast: '.last',
|
140 |
+
cssPageDisplay: '.pagedisplay',
|
141 |
+
cssPageSize: '.pagesize',
|
142 |
+
seperator: "/",
|
143 |
+
positionFixed: false,
|
144 |
+
appender: this.appender
|
145 |
+
};
|
146 |
+
|
147 |
+
this.construct = function(settings) {
|
148 |
+
|
149 |
+
return this.each(function() {
|
150 |
+
|
151 |
+
config = jQuery.extend(this.config, jQuery.tablesorterPager.defaults, settings);
|
152 |
+
|
153 |
+
var table = this, pager = config.container;
|
154 |
+
|
155 |
+
jQuery(this).trigger("appendCache");
|
156 |
+
|
157 |
+
config.size = parseInt(jQuery(".pagesize",pager).val());
|
158 |
+
|
159 |
+
jQuery(config.cssFirst,pager).click(function() {
|
160 |
+
moveToFirstPage(table);
|
161 |
+
return false;
|
162 |
+
});
|
163 |
+
jQuery(config.cssNext,pager).click(function() {
|
164 |
+
moveToNextPage(table);
|
165 |
+
return false;
|
166 |
+
});
|
167 |
+
jQuery(config.cssPrev,pager).click(function() {
|
168 |
+
moveToPrevPage(table);
|
169 |
+
return false;
|
170 |
+
});
|
171 |
+
jQuery(config.cssLast,pager).click(function() {
|
172 |
+
moveToLastPage(table);
|
173 |
+
return false;
|
174 |
+
});
|
175 |
+
jQuery(config.cssPageSize,pager).change(function() {
|
176 |
+
setPageSize(table,parseInt(jQuery(this).val()));
|
177 |
+
return false;
|
178 |
+
});
|
179 |
+
});
|
180 |
+
};
|
181 |
+
|
182 |
+
}
|
183 |
+
});
|
184 |
+
// extend plugin scope
|
185 |
+
jQuery.fn.extend({
|
186 |
+
tablesorterPager: jQuery.tablesorterPager.construct
|
187 |
+
});
|
188 |
+
|
189 |
+
})(jQuery);
|
js/quicksearch.js
ADDED
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function ($) {
|
2 |
+
$.fn.quicksearch = function (target, opt) {
|
3 |
+
|
4 |
+
var timeout, cache, rowcache, jq_results, val = '', e = this, options = $.extend({
|
5 |
+
delay: 100,
|
6 |
+
selector: null,
|
7 |
+
stripeRows: null,
|
8 |
+
loader: null,
|
9 |
+
noResults: '',
|
10 |
+
bind: 'keyup',
|
11 |
+
onBefore: function () {
|
12 |
+
return;
|
13 |
+
},
|
14 |
+
onAfter: function () {
|
15 |
+
return;
|
16 |
+
},
|
17 |
+
show: function () {
|
18 |
+
this.style.display = "";
|
19 |
+
},
|
20 |
+
hide: function () {
|
21 |
+
this.style.display = "none";
|
22 |
+
}
|
23 |
+
}, opt);
|
24 |
+
|
25 |
+
this.go = function () {
|
26 |
+
|
27 |
+
var i = 0, noresults = true, vals = val.toLowerCase().split(' ');
|
28 |
+
|
29 |
+
var rowcache_length = rowcache.length;
|
30 |
+
for (var i = 0; i < rowcache_length; i++)
|
31 |
+
{
|
32 |
+
if (this.test(vals, cache[i]) || val == "") {
|
33 |
+
options.show.apply(rowcache[i]);
|
34 |
+
noresults = false;
|
35 |
+
} else {
|
36 |
+
options.hide.apply(rowcache[i]);
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
if (noresults) {
|
41 |
+
this.results(false);
|
42 |
+
} else {
|
43 |
+
this.results(true);
|
44 |
+
this.stripe();
|
45 |
+
}
|
46 |
+
|
47 |
+
this.loader(false);
|
48 |
+
options.onAfter();
|
49 |
+
|
50 |
+
return this;
|
51 |
+
};
|
52 |
+
|
53 |
+
this.stripe = function () {
|
54 |
+
|
55 |
+
if (typeof options.stripeRows === "object" && options.stripeRows !== null)
|
56 |
+
{
|
57 |
+
var joined = options.stripeRows.join(' ');
|
58 |
+
var stripeRows_length = options.stripeRows.length;
|
59 |
+
|
60 |
+
jq_results.not(':hidden').each(function (i) {
|
61 |
+
$(this).removeClass(joined).addClass(options.stripeRows[i % stripeRows_length]);
|
62 |
+
});
|
63 |
+
}
|
64 |
+
|
65 |
+
return this;
|
66 |
+
};
|
67 |
+
|
68 |
+
this.strip_html = function (input) {
|
69 |
+
var output = input.replace(new RegExp('<[^<]+\>', 'g'), "");
|
70 |
+
output = $.trim(output.toLowerCase());
|
71 |
+
return output;
|
72 |
+
};
|
73 |
+
|
74 |
+
this.results = function (bool) {
|
75 |
+
if (typeof options.noResults === "string" && options.noResults !== "") {
|
76 |
+
if (bool) {
|
77 |
+
$(options.noResults).hide();
|
78 |
+
} else {
|
79 |
+
$(options.noResults).show();
|
80 |
+
}
|
81 |
+
}
|
82 |
+
return this;
|
83 |
+
};
|
84 |
+
|
85 |
+
this.loader = function (bool) {
|
86 |
+
if (typeof options.loader === "string" && options.loader !== "") {
|
87 |
+
(bool) ? $(options.loader).show() : $(options.loader).hide();
|
88 |
+
}
|
89 |
+
return this;
|
90 |
+
};
|
91 |
+
|
92 |
+
this.test = function (vals, t) {
|
93 |
+
for (var i = 0; i < vals.length; i += 1) {
|
94 |
+
if (t.indexOf(vals[i]) === -1) {
|
95 |
+
return false;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
return true;
|
99 |
+
};
|
100 |
+
|
101 |
+
this.cache = function () {
|
102 |
+
|
103 |
+
jq_results = $(target);
|
104 |
+
|
105 |
+
if (typeof options.noResults === "string" && options.noResults !== "") {
|
106 |
+
jq_results = jq_results.not(options.noResults);
|
107 |
+
}
|
108 |
+
|
109 |
+
var t = (typeof options.selector === "string") ? jq_results.find(options.selector) : $(target).not(options.noResults);
|
110 |
+
cache = t.map(function () {
|
111 |
+
return e.strip_html(this.innerHTML);
|
112 |
+
});
|
113 |
+
|
114 |
+
rowcache = jq_results.map(function () {
|
115 |
+
return this;
|
116 |
+
});
|
117 |
+
|
118 |
+
return this.go();
|
119 |
+
};
|
120 |
+
|
121 |
+
this.trigger = function () {
|
122 |
+
this.loader(true);
|
123 |
+
options.onBefore();
|
124 |
+
|
125 |
+
window.clearTimeout(timeout);
|
126 |
+
timeout = window.setTimeout(function () {
|
127 |
+
e.go();
|
128 |
+
}, options.delay);
|
129 |
+
|
130 |
+
return this;
|
131 |
+
};
|
132 |
+
|
133 |
+
this.cache();
|
134 |
+
this.results(true);
|
135 |
+
this.stripe();
|
136 |
+
this.loader(false);
|
137 |
+
|
138 |
+
return this.each(function () {
|
139 |
+
$(this).bind(options.bind, function () {
|
140 |
+
val = $(this).val();
|
141 |
+
e.trigger();
|
142 |
+
});
|
143 |
+
});
|
144 |
+
|
145 |
+
};
|
146 |
+
});
|
js/seo-links.js
ADDED
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function() {
|
2 |
+
var theTable = jQuery('table#mySortable');
|
3 |
+
|
4 |
+
jQuery("#filter").keyup(function(e) {
|
5 |
+
|
6 |
+
if (e.keyCode == 13)
|
7 |
+
jQuery.uiTableFilter(theTable, this.value);
|
8 |
+
|
9 |
+
jQuery("#mySortable tbody tr:eq(0)").hide();
|
10 |
+
|
11 |
+
});
|
12 |
+
|
13 |
+
});
|
14 |
+
|
15 |
+
jQuery(document).ready(function() {
|
16 |
+
|
17 |
+
jQuery("#datatable")
|
18 |
+
.tablesorter({ } )
|
19 |
+
.tablesorterPager({container: jQuery("#pager")});
|
20 |
+
|
21 |
+
|
22 |
+
|
23 |
+
refresh_me();
|
24 |
+
|
25 |
+
jQuery("input").bind("keypress", function(e) {
|
26 |
+
if (e.keyCode == 13)
|
27 |
+
return false;
|
28 |
+
});
|
29 |
+
|
30 |
+
jQuery("a#edit_all").bind("click", function() {
|
31 |
+
jQuery("#customkey").toggle(0);
|
32 |
+
|
33 |
+
|
34 |
+
});
|
35 |
+
|
36 |
+
jQuery("input").bind("keypress", function(e) {
|
37 |
+
if (e.keyCode == 13)
|
38 |
+
return false;
|
39 |
+
});
|
40 |
+
jQuery("input[name=addword]").keypress(function(e) {
|
41 |
+
if (e.keyCode == 13) {
|
42 |
+
|
43 |
+
jQuery("#saveadd").click();
|
44 |
+
}
|
45 |
+
if (e.keyCode == 27) {
|
46 |
+
|
47 |
+
jQuery("#canceladd").click();
|
48 |
+
}
|
49 |
+
});
|
50 |
+
|
51 |
+
jQuery("input[name=addurl]").keypress(function(e) {
|
52 |
+
if (e.keyCode == 13) {
|
53 |
+
|
54 |
+
jQuery("#saveadd").click();
|
55 |
+
}
|
56 |
+
if (e.keyCode == 27) {
|
57 |
+
|
58 |
+
jQuery("#canceladd").click();
|
59 |
+
}
|
60 |
+
});
|
61 |
+
|
62 |
+
});
|
63 |
+
|
64 |
+
function put_data() {
|
65 |
+
|
66 |
+
var tmp = '';
|
67 |
+
|
68 |
+
jQuery('table#mySortable tbody tr').each(function(i) {
|
69 |
+
//iterate tr
|
70 |
+
if (i) {
|
71 |
+
jQuery(this).find('td').each(function(i) {
|
72 |
+
//iterate td
|
73 |
+
elem = jQuery(this);
|
74 |
+
if (elem.text())
|
75 |
+
if (elem.is(".word") || elem.is(".url") || elem.is(".redir")) {
|
76 |
+
|
77 |
+
if (i == 1 || i == 2)
|
78 |
+
tmp += '|';//SEOSmartOptions.separator;
|
79 |
+
|
80 |
+
tmp += elem.text();
|
81 |
+
|
82 |
+
}
|
83 |
+
if (i==2)
|
84 |
+
tmp+="\n";
|
85 |
+
});
|
86 |
+
}
|
87 |
+
|
88 |
+
});
|
89 |
+
|
90 |
+
document.getElementById('customkey').value = tmp;
|
91 |
+
|
92 |
+
}
|
93 |
+
|
94 |
+
function refresh_me() {
|
95 |
+
|
96 |
+
jQuery("table#mySortable").tableDnD({
|
97 |
+
onDrop: function(table, row) {
|
98 |
+
//jQuery("table#mySortable tr").removeClass('odd');
|
99 |
+
//jQuery("table#mySortable tr:visible:odd").addClass('odd');
|
100 |
+
put_data();
|
101 |
+
|
102 |
+
}
|
103 |
+
});
|
104 |
+
|
105 |
+
|
106 |
+
jQuery(".editlink").click(function() {
|
107 |
+
|
108 |
+
jQuery(this).hide();
|
109 |
+
var datapos = jQuery(this).parent().parent().prevAll().length;
|
110 |
+
var editpos = datapos + 1;
|
111 |
+
|
112 |
+
|
113 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.savelink").show();
|
114 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.cancellink").show();
|
115 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.removelink").hide();
|
116 |
+
|
117 |
+
var word = jQuery("#mySortable tbody tr:eq(" + datapos + ") td.word").text();
|
118 |
+
var word_input = '<span name="editword" style="display: none;">' + word + '</span><input type="text" name="editword" value="' + word + '" />';
|
119 |
+
var url = jQuery("#mySortable tbody tr:eq(" + datapos + ") td.url").text();
|
120 |
+
var url_input = '<span name="editlink" style="display: none;">' + url + '</span><input type="text" name="editlink" value="' + url + '" />';
|
121 |
+
var redir = jQuery("#mySortable tbody tr:eq(" + datapos + ") td.redir").text();
|
122 |
+
var redir_input = '<span name="editredir" style="display: none;">' + redir + '</span><input type="text" name="editredir" value="' + redir + '" />';
|
123 |
+
|
124 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td.word").html(word_input);
|
125 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td.url").html(url_input);
|
126 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td.redir").html(redir_input);
|
127 |
+
|
128 |
+
jQuery("input").bind("keypress", function(e) {
|
129 |
+
if (e.keyCode == 13)
|
130 |
+
return false;
|
131 |
+
});
|
132 |
+
jQuery("input[name=editword]").keypress(function(e) {
|
133 |
+
if (e.keyCode == 13) {
|
134 |
+
|
135 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.savelink").click();
|
136 |
+
}
|
137 |
+
if (e.keyCode == 27) {
|
138 |
+
|
139 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.cancellink").click();
|
140 |
+
}
|
141 |
+
});
|
142 |
+
|
143 |
+
jQuery("input[name=editlink]").keypress(function(e) {
|
144 |
+
if (e.keyCode == 13) {
|
145 |
+
|
146 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.savelink").click();
|
147 |
+
}
|
148 |
+
if (e.keyCode == 27) {
|
149 |
+
|
150 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.cancellink").click();
|
151 |
+
}
|
152 |
+
});
|
153 |
+
|
154 |
+
});
|
155 |
+
|
156 |
+
jQuery(".cancellink").click(function() {
|
157 |
+
var datapos = jQuery(this).parent().parent().prevAll().length;
|
158 |
+
|
159 |
+
var editword = jQuery("#mySortable tbody tr:eq(" + datapos + ") td span[name=editword]").text();
|
160 |
+
var editlink = jQuery("#mySortable tbody tr:eq(" + datapos + ") td span[name=editlink]").text();
|
161 |
+
var editredir = jQuery("#mySortable tbody tr:eq(" + datapos + ") td span[name=editredir]").text();
|
162 |
+
|
163 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td.word").html(editword);
|
164 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td.url").html(editlink);
|
165 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td.redir").html(editredir);
|
166 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.savelink").hide();
|
167 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.cancellink").hide();
|
168 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.removelink").show();
|
169 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.editlink").show();
|
170 |
+
|
171 |
+
put_data();
|
172 |
+
});
|
173 |
+
|
174 |
+
jQuery(".removelink").click(function() {
|
175 |
+
var datapos = jQuery(this).parent().parent().prevAll().length;
|
176 |
+
|
177 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ")").remove();
|
178 |
+
|
179 |
+
jQuery("#updatemessage").text("Keyword removed").fadeOut(2000, function() {
|
180 |
+
jQuery(this).css('display', 'block').text("");
|
181 |
+
});
|
182 |
+
put_data();
|
183 |
+
|
184 |
+
|
185 |
+
});
|
186 |
+
|
187 |
+
jQuery(".savelink").click(function() {
|
188 |
+
var datapos = jQuery(this).parent().parent().prevAll().length;
|
189 |
+
|
190 |
+
var editword = jQuery("#mySortable tbody tr:eq(" + datapos + ") td input[name=editword]").val();
|
191 |
+
var editlink = jQuery("#mySortable tbody tr:eq(" + datapos + ") td input[name=editlink]").val();
|
192 |
+
var editredir = jQuery("#mySortable tbody tr:eq(" + datapos + ") td input[name=editredir]").val();
|
193 |
+
|
194 |
+
//alert(editword);
|
195 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td.word").text(editword);
|
196 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td.url").text(editlink);
|
197 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td.redir").text(editredir);
|
198 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.savelink").hide();
|
199 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.cancellink").hide();
|
200 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.removelink").show();
|
201 |
+
jQuery("#mySortable tbody tr:eq(" + datapos + ") td a.editlink").show();
|
202 |
+
|
203 |
+
jQuery("#updatemessage").text("Keyword updated").fadeOut(2000, function() {
|
204 |
+
jQuery(this).css('display', 'block').text("");
|
205 |
+
});
|
206 |
+
|
207 |
+
put_data();
|
208 |
+
|
209 |
+
|
210 |
+
});
|
211 |
+
|
212 |
+
jQuery("#addrowbutton").unbind('click').click(function() {
|
213 |
+
jQuery("#addrow").show();
|
214 |
+
});
|
215 |
+
|
216 |
+
jQuery("#canceladd").click(function() {
|
217 |
+
jQuery("#addrow").hide();
|
218 |
+
});
|
219 |
+
|
220 |
+
jQuery("#saveadd").click(function() {
|
221 |
+
|
222 |
+
jQuery("#mySortable tbody tr:eq(0)").clone(true).insertAfter("#mySortable tbody tr:eq(0)");
|
223 |
+
|
224 |
+
var addword = jQuery("#addrow input[name=addword]").val();
|
225 |
+
var addurl = jQuery("#addrow input[name=addurl]").val();
|
226 |
+
var addredir = jQuery("#addrow input[name=addredir]").val();
|
227 |
+
|
228 |
+
jQuery("#mySortable tbody tr:eq(1)").show();
|
229 |
+
jQuery("#mySortable tbody tr:eq(1) .word").text(addword);
|
230 |
+
jQuery("#mySortable tbody tr:eq(1) .url").text(addurl);
|
231 |
+
jQuery("#mySortable tbody tr:eq(1) .redir").text(addredir);
|
232 |
+
|
233 |
+
jQuery("#addrow input[name=addword]").val("");
|
234 |
+
jQuery("#addrow input[name=addurl]").val("http://");
|
235 |
+
jQuery("#addrow input[name=addredir]").val("");
|
236 |
+
|
237 |
+
jQuery("#addrow").hide();
|
238 |
+
|
239 |
+
jQuery("#updatemessage").text("Keyword added").fadeOut(2000, function() {
|
240 |
+
jQuery(this).css('display', 'block').text("");
|
241 |
+
});
|
242 |
+
|
243 |
+
// sort on the first column
|
244 |
+
jQuery("#mySortable").trigger("applyWidgets", "zebra");
|
245 |
+
|
246 |
+
put_data();
|
247 |
+
|
248 |
+
});
|
249 |
+
|
250 |
+
}
|
251 |
+
//end refresh me
|
js/tablesorter.js
ADDED
@@ -0,0 +1,852 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
*
|
3 |
+
* TableSorter 2.0 - Client-side table sorting with ease!
|
4 |
+
* Version 2.0.3
|
5 |
+
* @requires jQuery v1.2.3
|
6 |
+
*
|
7 |
+
* Copyright (c) 2007 Christian Bach
|
8 |
+
* Examples and docs at: http://tablesorter.com
|
9 |
+
* Dual licensed under the MIT and GPL licenses:
|
10 |
+
* http://www.opensource.org/licenses/mit-license.php
|
11 |
+
* http://www.gnu.org/licenses/gpl.html
|
12 |
+
*
|
13 |
+
*/
|
14 |
+
/**
|
15 |
+
*
|
16 |
+
* @description Create a sortable table with multi-column sorting capabilitys
|
17 |
+
*
|
18 |
+
* @example $('table').tablesorter();
|
19 |
+
* @desc Create a simple tablesorter interface.
|
20 |
+
*
|
21 |
+
* @example $('table').tablesorter({ sortList:[[0,0],[1,0]] });
|
22 |
+
* @desc Create a tablesorter interface and sort on the first and secound column in ascending order.
|
23 |
+
*
|
24 |
+
* @example $('table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } });
|
25 |
+
* @desc Create a tablesorter interface and disableing the first and secound column headers.
|
26 |
+
*
|
27 |
+
* @example $('table').tablesorter({ 0: {sorter:"integer"}, 1: {sorter:"currency"} });
|
28 |
+
* @desc Create a tablesorter interface and set a column parser for the first and secound column.
|
29 |
+
*
|
30 |
+
*
|
31 |
+
* @param Object settings An object literal containing key/value pairs to provide optional settings.
|
32 |
+
*
|
33 |
+
* @option String cssHeader (optional) A string of the class name to be appended to sortable tr elements in the thead of the table.
|
34 |
+
* Default value: "header"
|
35 |
+
*
|
36 |
+
* @option String cssAsc (optional) A string of the class name to be appended to sortable tr elements in the thead on a ascending sort.
|
37 |
+
* Default value: "headerSortUp"
|
38 |
+
*
|
39 |
+
* @option String cssDesc (optional) A string of the class name to be appended to sortable tr elements in the thead on a descending sort.
|
40 |
+
* Default value: "headerSortDown"
|
41 |
+
*
|
42 |
+
* @option String sortInitialOrder (optional) A string of the inital sorting order can be asc or desc.
|
43 |
+
* Default value: "asc"
|
44 |
+
*
|
45 |
+
* @option String sortMultisortKey (optional) A string of the multi-column sort key.
|
46 |
+
* Default value: "shiftKey"
|
47 |
+
*
|
48 |
+
* @option String textExtraction (optional) A string of the text-extraction method to use.
|
49 |
+
* For complex html structures inside td cell set this option to "complex",
|
50 |
+
* on large tables the complex option can be slow.
|
51 |
+
* Default value: "simple"
|
52 |
+
*
|
53 |
+
* @option Object headers (optional) An array containing the forces sorting rules.
|
54 |
+
* This option let's you specify a default sorting rule.
|
55 |
+
* Default value: null
|
56 |
+
*
|
57 |
+
* @option Array sortList (optional) An array containing the forces sorting rules.
|
58 |
+
* This option let's you specify a default sorting rule.
|
59 |
+
* Default value: null
|
60 |
+
*
|
61 |
+
* @option Array sortForce (optional) An array containing forced sorting rules.
|
62 |
+
* This option let's you specify a default sorting rule, which is prepended to user-selected rules.
|
63 |
+
* Default value: null
|
64 |
+
*
|
65 |
+
* @option Array sortAppend (optional) An array containing forced sorting rules.
|
66 |
+
* This option let's you specify a default sorting rule, which is appended to user-selected rules.
|
67 |
+
* Default value: null
|
68 |
+
*
|
69 |
+
* @option Boolean widthFixed (optional) Boolean flag indicating if tablesorter should apply fixed widths to the table columns.
|
70 |
+
* This is usefull when using the pager companion plugin.
|
71 |
+
* This options requires the dimension jquery plugin.
|
72 |
+
* Default value: false
|
73 |
+
*
|
74 |
+
* @option Boolean cancelSelection (optional) Boolean flag indicating if tablesorter should cancel selection of the table headers text.
|
75 |
+
* Default value: true
|
76 |
+
*
|
77 |
+
* @option Boolean debug (optional) Boolean flag indicating if tablesorter should display debuging information usefull for development.
|
78 |
+
*
|
79 |
+
* @type jQuery
|
80 |
+
*
|
81 |
+
* @name tablesorter
|
82 |
+
*
|
83 |
+
* @cat Plugins/Tablesorter
|
84 |
+
*
|
85 |
+
* @author Christian Bach/christian.bach@polyester.se
|
86 |
+
*/
|
87 |
+
|
88 |
+
(function($) {
|
89 |
+
$.extend({
|
90 |
+
tablesorter: new function() {
|
91 |
+
|
92 |
+
var parsers = [], widgets = [];
|
93 |
+
|
94 |
+
this.defaults = {
|
95 |
+
cssHeader: "header",
|
96 |
+
cssAsc: "headerSortUp",
|
97 |
+
cssDesc: "headerSortDown",
|
98 |
+
sortInitialOrder: "asc",
|
99 |
+
sortMultiSortKey: "shiftKey",
|
100 |
+
sortForce: null,
|
101 |
+
sortAppend: null,
|
102 |
+
textExtraction: "simple",
|
103 |
+
parsers: {},
|
104 |
+
widgets: [],
|
105 |
+
widgetZebra: {css: ["even","odd"]},
|
106 |
+
headers: {},
|
107 |
+
widthFixed: false,
|
108 |
+
cancelSelection: true,
|
109 |
+
sortList: [],
|
110 |
+
headerList: [],
|
111 |
+
dateFormat: "us",
|
112 |
+
decimal: '.',
|
113 |
+
debug: false
|
114 |
+
};
|
115 |
+
|
116 |
+
/* debuging utils */
|
117 |
+
function benchmark(s,d) {
|
118 |
+
log(s + "," + (new Date().getTime() - d.getTime()) + "ms");
|
119 |
+
}
|
120 |
+
|
121 |
+
this.benchmark = benchmark;
|
122 |
+
|
123 |
+
function log(s) {
|
124 |
+
if (typeof console != "undefined" && typeof console.debug != "undefined") {
|
125 |
+
console.log(s);
|
126 |
+
} else {
|
127 |
+
alert(s);
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
/* parsers utils */
|
132 |
+
function buildParserCache(table,$headers) {
|
133 |
+
|
134 |
+
if(table.config.debug) { var parsersDebug = ""; }
|
135 |
+
|
136 |
+
var rows = table.tBodies[0].rows;
|
137 |
+
|
138 |
+
if(table.tBodies[0].rows[0]) {
|
139 |
+
|
140 |
+
var list = [], cells = rows[0].cells, l = cells.length;
|
141 |
+
|
142 |
+
for (var i=0;i < l; i++) {
|
143 |
+
var p = false;
|
144 |
+
|
145 |
+
if($.metadata && ($($headers[i]).metadata() && $($headers[i]).metadata().sorter) ) {
|
146 |
+
|
147 |
+
p = getParserById($($headers[i]).metadata().sorter);
|
148 |
+
|
149 |
+
} else if((table.config.headers[i] && table.config.headers[i].sorter)) {
|
150 |
+
|
151 |
+
p = getParserById(table.config.headers[i].sorter);
|
152 |
+
}
|
153 |
+
if(!p) {
|
154 |
+
p = detectParserForColumn(table,cells[i]);
|
155 |
+
}
|
156 |
+
|
157 |
+
if(table.config.debug) { parsersDebug += "column:" + i + " parser:" +p.id + "\n"; }
|
158 |
+
|
159 |
+
list.push(p);
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
if(table.config.debug) { log(parsersDebug); }
|
164 |
+
|
165 |
+
return list;
|
166 |
+
};
|
167 |
+
|
168 |
+
function detectParserForColumn(table,node) {
|
169 |
+
var l = parsers.length;
|
170 |
+
for(var i=1; i < l; i++) {
|
171 |
+
if(parsers[i].is($.trim(getElementText(table.config,node)),table,node)) {
|
172 |
+
return parsers[i];
|
173 |
+
}
|
174 |
+
}
|
175 |
+
// 0 is always the generic parser (text)
|
176 |
+
return parsers[0];
|
177 |
+
}
|
178 |
+
|
179 |
+
function getParserById(name) {
|
180 |
+
var l = parsers.length;
|
181 |
+
for(var i=0; i < l; i++) {
|
182 |
+
if(parsers[i].id.toLowerCase() == name.toLowerCase()) {
|
183 |
+
return parsers[i];
|
184 |
+
}
|
185 |
+
}
|
186 |
+
return false;
|
187 |
+
}
|
188 |
+
|
189 |
+
/* utils */
|
190 |
+
function buildCache(table) {
|
191 |
+
|
192 |
+
if(table.config.debug) { var cacheTime = new Date(); }
|
193 |
+
|
194 |
+
|
195 |
+
var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0,
|
196 |
+
totalCells = (table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length) || 0,
|
197 |
+
parsers = table.config.parsers,
|
198 |
+
cache = {row: [], normalized: []};
|
199 |
+
|
200 |
+
for (var i=0;i < totalRows; ++i) {
|
201 |
+
|
202 |
+
/** Add the table data to main data array */
|
203 |
+
var c = table.tBodies[0].rows[i], cols = [];
|
204 |
+
|
205 |
+
cache.row.push($(c));
|
206 |
+
|
207 |
+
for(var j=0; j < totalCells; ++j) {
|
208 |
+
cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j]));
|
209 |
+
}
|
210 |
+
|
211 |
+
cols.push(i); // add position for rowCache
|
212 |
+
cache.normalized.push(cols);
|
213 |
+
cols = null;
|
214 |
+
};
|
215 |
+
|
216 |
+
if(table.config.debug) { benchmark("Building cache for " + totalRows + " rows:", cacheTime); }
|
217 |
+
|
218 |
+
return cache;
|
219 |
+
};
|
220 |
+
|
221 |
+
function getElementText(config,node) {
|
222 |
+
|
223 |
+
if(!node) return "";
|
224 |
+
|
225 |
+
var t = "";
|
226 |
+
|
227 |
+
if(config.textExtraction == "simple") {
|
228 |
+
if(node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
|
229 |
+
t = node.childNodes[0].innerHTML;
|
230 |
+
} else {
|
231 |
+
t = node.innerHTML;
|
232 |
+
}
|
233 |
+
} else {
|
234 |
+
if(typeof(config.textExtraction) == "function") {
|
235 |
+
t = config.textExtraction(node);
|
236 |
+
} else {
|
237 |
+
t = $(node).text();
|
238 |
+
}
|
239 |
+
}
|
240 |
+
return t;
|
241 |
+
}
|
242 |
+
|
243 |
+
function appendToTable(table,cache) {
|
244 |
+
|
245 |
+
if(table.config.debug) {var appendTime = new Date()}
|
246 |
+
|
247 |
+
var c = cache,
|
248 |
+
r = c.row,
|
249 |
+
n= c.normalized,
|
250 |
+
totalRows = n.length,
|
251 |
+
checkCell = (n[0].length-1),
|
252 |
+
tableBody = $(table.tBodies[0]),
|
253 |
+
rows = [];
|
254 |
+
|
255 |
+
for (var i=0;i < totalRows; i++) {
|
256 |
+
rows.push(r[n[i][checkCell]]);
|
257 |
+
if(!table.config.appender) {
|
258 |
+
|
259 |
+
var o = r[n[i][checkCell]];
|
260 |
+
var l = o.length;
|
261 |
+
for(var j=0; j < l; j++) {
|
262 |
+
|
263 |
+
tableBody[0].appendChild(o[j]);
|
264 |
+
|
265 |
+
}
|
266 |
+
|
267 |
+
//tableBody.append(r[n[i][checkCell]]);
|
268 |
+
}
|
269 |
+
}
|
270 |
+
|
271 |
+
if(table.config.appender) {
|
272 |
+
|
273 |
+
table.config.appender(table,rows);
|
274 |
+
}
|
275 |
+
|
276 |
+
rows = null;
|
277 |
+
|
278 |
+
if(table.config.debug) { benchmark("Rebuilt table:", appendTime); }
|
279 |
+
|
280 |
+
//apply table widgets
|
281 |
+
applyWidget(table);
|
282 |
+
|
283 |
+
// trigger sortend
|
284 |
+
setTimeout(function() {
|
285 |
+
$(table).trigger("sortEnd");
|
286 |
+
},0);
|
287 |
+
|
288 |
+
};
|
289 |
+
|
290 |
+
function buildHeaders(table) {
|
291 |
+
|
292 |
+
if(table.config.debug) { var time = new Date(); }
|
293 |
+
|
294 |
+
var meta = ($.metadata) ? true : false, tableHeadersRows = [];
|
295 |
+
|
296 |
+
for(var i = 0; i < table.tHead.rows.length; i++) { tableHeadersRows[i]=0; };
|
297 |
+
|
298 |
+
$tableHeaders = $("thead th",table);
|
299 |
+
|
300 |
+
$tableHeaders.each(function(index) {
|
301 |
+
|
302 |
+
this.count = 0;
|
303 |
+
this.column = index;
|
304 |
+
this.order = formatSortingOrder(table.config.sortInitialOrder);
|
305 |
+
|
306 |
+
if(checkHeaderMetadata(this) || checkHeaderOptions(table,index)) this.sortDisabled = true;
|
307 |
+
|
308 |
+
if(!this.sortDisabled) {
|
309 |
+
$(this).addClass(table.config.cssHeader);
|
310 |
+
}
|
311 |
+
|
312 |
+
// add cell to headerList
|
313 |
+
table.config.headerList[index]= this;
|
314 |
+
});
|
315 |
+
|
316 |
+
if(table.config.debug) { benchmark("Built headers:", time); log($tableHeaders); }
|
317 |
+
|
318 |
+
return $tableHeaders;
|
319 |
+
|
320 |
+
};
|
321 |
+
|
322 |
+
function checkCellColSpan(table, rows, row) {
|
323 |
+
var arr = [], r = table.tHead.rows, c = r[row].cells;
|
324 |
+
|
325 |
+
for(var i=0; i < c.length; i++) {
|
326 |
+
var cell = c[i];
|
327 |
+
|
328 |
+
if ( cell.colSpan > 1) {
|
329 |
+
arr = arr.concat(checkCellColSpan(table, headerArr,row++));
|
330 |
+
} else {
|
331 |
+
if(table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row+1])) {
|
332 |
+
arr.push(cell);
|
333 |
+
}
|
334 |
+
//headerArr[row] = (i+row);
|
335 |
+
}
|
336 |
+
}
|
337 |
+
return arr;
|
338 |
+
};
|
339 |
+
|
340 |
+
function checkHeaderMetadata(cell) {
|
341 |
+
if(($.metadata) && ($(cell).metadata().sorter === false)) { return true; };
|
342 |
+
return false;
|
343 |
+
}
|
344 |
+
|
345 |
+
function checkHeaderOptions(table,i) {
|
346 |
+
if((table.config.headers[i]) && (table.config.headers[i].sorter === false)) { return true; };
|
347 |
+
return false;
|
348 |
+
}
|
349 |
+
|
350 |
+
function applyWidget(table) {
|
351 |
+
var c = table.config.widgets;
|
352 |
+
var l = c.length;
|
353 |
+
for(var i=0; i < l; i++) {
|
354 |
+
|
355 |
+
getWidgetById(c[i]).format(table);
|
356 |
+
}
|
357 |
+
|
358 |
+
}
|
359 |
+
|
360 |
+
function getWidgetById(name) {
|
361 |
+
var l = widgets.length;
|
362 |
+
for(var i=0; i < l; i++) {
|
363 |
+
if(widgets[i].id.toLowerCase() == name.toLowerCase() ) {
|
364 |
+
return widgets[i];
|
365 |
+
}
|
366 |
+
}
|
367 |
+
};
|
368 |
+
|
369 |
+
function formatSortingOrder(v) {
|
370 |
+
|
371 |
+
if(typeof(v) != "Number") {
|
372 |
+
i = (v.toLowerCase() == "desc") ? 1 : 0;
|
373 |
+
} else {
|
374 |
+
i = (v == (0 || 1)) ? v : 0;
|
375 |
+
}
|
376 |
+
return i;
|
377 |
+
}
|
378 |
+
|
379 |
+
function isValueInArray(v, a) {
|
380 |
+
var l = a.length;
|
381 |
+
for(var i=0; i < l; i++) {
|
382 |
+
if(a[i][0] == v) {
|
383 |
+
return true;
|
384 |
+
}
|
385 |
+
}
|
386 |
+
return false;
|
387 |
+
}
|
388 |
+
|
389 |
+
function setHeadersCss(table,$headers, list, css) {
|
390 |
+
// remove all header information
|
391 |
+
$headers.removeClass(css[0]).removeClass(css[1]);
|
392 |
+
|
393 |
+
var h = [];
|
394 |
+
$headers.each(function(offset) {
|
395 |
+
if(!this.sortDisabled) {
|
396 |
+
h[this.column] = $(this);
|
397 |
+
}
|
398 |
+
});
|
399 |
+
|
400 |
+
var l = list.length;
|
401 |
+
for(var i=0; i < l; i++) {
|
402 |
+
h[list[i][0]].addClass(css[list[i][1]]);
|
403 |
+
}
|
404 |
+
}
|
405 |
+
|
406 |
+
function fixColumnWidth(table,$headers) {
|
407 |
+
var c = table.config;
|
408 |
+
if(c.widthFixed) {
|
409 |
+
var colgroup = $('<colgroup>');
|
410 |
+
$("tr:first td",table.tBodies[0]).each(function() {
|
411 |
+
colgroup.append($('<col>').css('width',$(this).width()));
|
412 |
+
});
|
413 |
+
$(table).prepend(colgroup);
|
414 |
+
};
|
415 |
+
}
|
416 |
+
|
417 |
+
function updateHeaderSortCount(table,sortList) {
|
418 |
+
var c = table.config, l = sortList.length;
|
419 |
+
for(var i=0; i < l; i++) {
|
420 |
+
var s = sortList[i], o = c.headerList[s[0]];
|
421 |
+
o.count = s[1];
|
422 |
+
o.count++;
|
423 |
+
}
|
424 |
+
}
|
425 |
+
|
426 |
+
/* sorting methods */
|
427 |
+
function multisort(table,sortList,cache) {
|
428 |
+
|
429 |
+
if(table.config.debug) { var sortTime = new Date(); }
|
430 |
+
|
431 |
+
var dynamicExp = "var sortWrapper = function(a,b) {", l = sortList.length;
|
432 |
+
|
433 |
+
for(var i=0; i < l; i++) {
|
434 |
+
|
435 |
+
var c = sortList[i][0];
|
436 |
+
var order = sortList[i][1];
|
437 |
+
var s = (getCachedSortType(table.config.parsers,c) == "text") ? ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ? "sortNumeric" : "sortNumericDesc");
|
438 |
+
|
439 |
+
var e = "e" + i;
|
440 |
+
|
441 |
+
dynamicExp += "var " + e + " = " + s + "(a[" + c + "],b[" + c + "]); ";
|
442 |
+
dynamicExp += "if(" + e + ") { return " + e + "; } ";
|
443 |
+
dynamicExp += "else { ";
|
444 |
+
}
|
445 |
+
|
446 |
+
// if value is the same keep orignal order
|
447 |
+
var orgOrderCol = cache.normalized[0].length - 1;
|
448 |
+
dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];";
|
449 |
+
|
450 |
+
for(var i=0; i < l; i++) {
|
451 |
+
dynamicExp += "}; ";
|
452 |
+
}
|
453 |
+
|
454 |
+
dynamicExp += "return 0; ";
|
455 |
+
dynamicExp += "}; ";
|
456 |
+
|
457 |
+
eval(dynamicExp);
|
458 |
+
|
459 |
+
cache.normalized.sort(sortWrapper);
|
460 |
+
|
461 |
+
if(table.config.debug) { benchmark("Sorting on " + sortList.toString() + " and dir " + order+ " time:", sortTime); }
|
462 |
+
|
463 |
+
return cache;
|
464 |
+
};
|
465 |
+
|
466 |
+
function sortText(a,b) {
|
467 |
+
return ((a < b) ? -1 : ((a > b) ? 1 : 0));
|
468 |
+
};
|
469 |
+
|
470 |
+
function sortTextDesc(a,b) {
|
471 |
+
return ((b < a) ? -1 : ((b > a) ? 1 : 0));
|
472 |
+
};
|
473 |
+
|
474 |
+
function sortNumeric(a,b) {
|
475 |
+
return a-b;
|
476 |
+
};
|
477 |
+
|
478 |
+
function sortNumericDesc(a,b) {
|
479 |
+
return b-a;
|
480 |
+
};
|
481 |
+
|
482 |
+
function getCachedSortType(parsers,i) {
|
483 |
+
return parsers[i].type;
|
484 |
+
};
|
485 |
+
|
486 |
+
/* public methods */
|
487 |
+
this.construct = function(settings) {
|
488 |
+
|
489 |
+
return this.each(function() {
|
490 |
+
|
491 |
+
if(!this.tHead || !this.tBodies) return;
|
492 |
+
|
493 |
+
var $this, $document,$headers, cache, config, shiftDown = 0, sortOrder;
|
494 |
+
|
495 |
+
this.config = {};
|
496 |
+
|
497 |
+
config = $.extend(this.config, $.tablesorter.defaults, settings);
|
498 |
+
|
499 |
+
// store common expression for speed
|
500 |
+
$this = $(this);
|
501 |
+
|
502 |
+
// build headers
|
503 |
+
$headers = buildHeaders(this);
|
504 |
+
|
505 |
+
// try to auto detect column type, and store in tables config
|
506 |
+
this.config.parsers = buildParserCache(this,$headers);
|
507 |
+
|
508 |
+
|
509 |
+
// build the cache for the tbody cells
|
510 |
+
cache = buildCache(this);
|
511 |
+
|
512 |
+
// get the css class names, could be done else where.
|
513 |
+
var sortCSS = [config.cssDesc,config.cssAsc];
|
514 |
+
|
515 |
+
// fixate columns if the users supplies the fixedWidth option
|
516 |
+
fixColumnWidth(this);
|
517 |
+
|
518 |
+
// apply event handling to headers
|
519 |
+
// this is to big, perhaps break it out?
|
520 |
+
$headers.click(function(e) {
|
521 |
+
|
522 |
+
$this.trigger("sortStart");
|
523 |
+
|
524 |
+
var totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0;
|
525 |
+
|
526 |
+
if(!this.sortDisabled && totalRows > 0) {
|
527 |
+
|
528 |
+
|
529 |
+
// store exp, for speed
|
530 |
+
var $cell = $(this);
|
531 |
+
|
532 |
+
// get current column index
|
533 |
+
var i = this.column;
|
534 |
+
|
535 |
+
// get current column sort order
|
536 |
+
this.order = this.count++ % 2;
|
537 |
+
|
538 |
+
// user only whants to sort on one column
|
539 |
+
if(!e[config.sortMultiSortKey]) {
|
540 |
+
|
541 |
+
// flush the sort list
|
542 |
+
config.sortList = [];
|
543 |
+
|
544 |
+
if(config.sortForce != null) {
|
545 |
+
var a = config.sortForce;
|
546 |
+
for(var j=0; j < a.length; j++) {
|
547 |
+
if(a[j][0] != i) {
|
548 |
+
config.sortList.push(a[j]);
|
549 |
+
}
|
550 |
+
}
|
551 |
+
}
|
552 |
+
|
553 |
+
// add column to sort list
|
554 |
+
config.sortList.push([i,this.order]);
|
555 |
+
|
556 |
+
// multi column sorting
|
557 |
+
} else {
|
558 |
+
// the user has clicked on an all ready sortet column.
|
559 |
+
if(isValueInArray(i,config.sortList)) {
|
560 |
+
|
561 |
+
// revers the sorting direction for all tables.
|
562 |
+
for(var j=0; j < config.sortList.length; j++) {
|
563 |
+
var s = config.sortList[j], o = config.headerList[s[0]];
|
564 |
+
if(s[0] == i) {
|
565 |
+
o.count = s[1];
|
566 |
+
o.count++;
|
567 |
+
s[1] = o.count % 2;
|
568 |
+
}
|
569 |
+
}
|
570 |
+
} else {
|
571 |
+
// add column to sort list array
|
572 |
+
config.sortList.push([i,this.order]);
|
573 |
+
}
|
574 |
+
};
|
575 |
+
setTimeout(function() {
|
576 |
+
//set css for headers
|
577 |
+
setHeadersCss($this[0],$headers,config.sortList,sortCSS);
|
578 |
+
appendToTable($this[0],multisort($this[0],config.sortList,cache));
|
579 |
+
},1);
|
580 |
+
// stop normal event by returning false
|
581 |
+
return false;
|
582 |
+
}
|
583 |
+
// cancel selection
|
584 |
+
}).mousedown(function() {
|
585 |
+
if(config.cancelSelection) {
|
586 |
+
this.onselectstart = function() {return false};
|
587 |
+
return false;
|
588 |
+
}
|
589 |
+
});
|
590 |
+
|
591 |
+
// apply easy methods that trigger binded events
|
592 |
+
$this.bind("update",function() {
|
593 |
+
|
594 |
+
// rebuild parsers.
|
595 |
+
this.config.parsers = buildParserCache(this,$headers);
|
596 |
+
|
597 |
+
// rebuild the cache map
|
598 |
+
cache = buildCache(this);
|
599 |
+
|
600 |
+
}).bind("sorton",function(e,list) {
|
601 |
+
|
602 |
+
$(this).trigger("sortStart");
|
603 |
+
|
604 |
+
config.sortList = list;
|
605 |
+
|
606 |
+
// update and store the sortlist
|
607 |
+
var sortList = config.sortList;
|
608 |
+
|
609 |
+
// update header count index
|
610 |
+
updateHeaderSortCount(this,sortList);
|
611 |
+
|
612 |
+
//set css for headers
|
613 |
+
setHeadersCss(this,$headers,sortList,sortCSS);
|
614 |
+
|
615 |
+
|
616 |
+
// sort the table and append it to the dom
|
617 |
+
appendToTable(this,multisort(this,sortList,cache));
|
618 |
+
|
619 |
+
}).bind("appendCache",function() {
|
620 |
+
|
621 |
+
appendToTable(this,cache);
|
622 |
+
|
623 |
+
}).bind("applyWidgetId",function(e,id) {
|
624 |
+
|
625 |
+
getWidgetById(id).format(this);
|
626 |
+
|
627 |
+
}).bind("applyWidgets",function() {
|
628 |
+
// apply widgets
|
629 |
+
applyWidget(this);
|
630 |
+
});
|
631 |
+
|
632 |
+
if($.metadata && ($(this).metadata() && $(this).metadata().sortlist)) {
|
633 |
+
config.sortList = $(this).metadata().sortlist;
|
634 |
+
}
|
635 |
+
// if user has supplied a sort list to constructor.
|
636 |
+
if(config.sortList.length > 0) {
|
637 |
+
$this.trigger("sorton",[config.sortList]);
|
638 |
+
}
|
639 |
+
|
640 |
+
// apply widgets
|
641 |
+
applyWidget(this);
|
642 |
+
});
|
643 |
+
};
|
644 |
+
|
645 |
+
this.addParser = function(parser) {
|
646 |
+
var l = parsers.length, a = true;
|
647 |
+
for(var i=0; i < l; i++) {
|
648 |
+
if(parsers[i].id.toLowerCase() == parser.id.toLowerCase()) {
|
649 |
+
a = false;
|
650 |
+
}
|
651 |
+
}
|
652 |
+
if(a) { parsers.push(parser); };
|
653 |
+
};
|
654 |
+
|
655 |
+
this.addWidget = function(widget) {
|
656 |
+
widgets.push(widget);
|
657 |
+
};
|
658 |
+
|
659 |
+
this.formatFloat = function(s) {
|
660 |
+
var i = parseFloat(s);
|
661 |
+
return (isNaN(i)) ? 0 : i;
|
662 |
+
};
|
663 |
+
this.formatInt = function(s) {
|
664 |
+
var i = parseInt(s);
|
665 |
+
return (isNaN(i)) ? 0 : i;
|
666 |
+
};
|
667 |
+
|
668 |
+
this.isDigit = function(s,config) {
|
669 |
+
var DECIMAL = '\\' + config.decimal;
|
670 |
+
var exp = '/(^[+]?0(' + DECIMAL +'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)' + DECIMAL +'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*' + DECIMAL +'0+$)/';
|
671 |
+
return RegExp(exp).test($.trim(s));
|
672 |
+
};
|
673 |
+
|
674 |
+
this.clearTableBody = function(table) {
|
675 |
+
if($.browser.msie) {
|
676 |
+
function empty() {
|
677 |
+
while ( this.firstChild ) this.removeChild( this.firstChild );
|
678 |
+
}
|
679 |
+
empty.apply(table.tBodies[0]);
|
680 |
+
} else {
|
681 |
+
table.tBodies[0].innerHTML = "";
|
682 |
+
}
|
683 |
+
};
|
684 |
+
}
|
685 |
+
});
|
686 |
+
|
687 |
+
// extend plugin scope
|
688 |
+
$.fn.extend({
|
689 |
+
tablesorter: $.tablesorter.construct
|
690 |
+
});
|
691 |
+
|
692 |
+
var ts = $.tablesorter;
|
693 |
+
|
694 |
+
// add default parsers
|
695 |
+
ts.addParser({
|
696 |
+
id: "text",
|
697 |
+
is: function(s) {
|
698 |
+
return true;
|
699 |
+
},
|
700 |
+
format: function(s) {
|
701 |
+
return $.trim(s.toLowerCase());
|
702 |
+
},
|
703 |
+
type: "text"
|
704 |
+
});
|
705 |
+
|
706 |
+
ts.addParser({
|
707 |
+
id: "digit",
|
708 |
+
is: function(s,table) {
|
709 |
+
var c = table.config;
|
710 |
+
return $.tablesorter.isDigit(s,c);
|
711 |
+
},
|
712 |
+
format: function(s) {
|
713 |
+
return $.tablesorter.formatFloat(s);
|
714 |
+
},
|
715 |
+
type: "numeric"
|
716 |
+
});
|
717 |
+
|
718 |
+
ts.addParser({
|
719 |
+
id: "currency",
|
720 |
+
is: function(s) {
|
721 |
+
return /^[£$€?.]/.test(s);
|
722 |
+
},
|
723 |
+
format: function(s) {
|
724 |
+
return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));
|
725 |
+
},
|
726 |
+
type: "numeric"
|
727 |
+
});
|
728 |
+
|
729 |
+
ts.addParser({
|
730 |
+
id: "ipAddress",
|
731 |
+
is: function(s) {
|
732 |
+
return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);
|
733 |
+
},
|
734 |
+
format: function(s) {
|
735 |
+
var a = s.split("."), r = "", l = a.length;
|
736 |
+
for(var i = 0; i < l; i++) {
|
737 |
+
var item = a[i];
|
738 |
+
if(item.length == 2) {
|
739 |
+
r += "0" + item;
|
740 |
+
} else {
|
741 |
+
r += item;
|
742 |
+
}
|
743 |
+
}
|
744 |
+
return $.tablesorter.formatFloat(r);
|
745 |
+
},
|
746 |
+
type: "numeric"
|
747 |
+
});
|
748 |
+
|
749 |
+
ts.addParser({
|
750 |
+
id: "url",
|
751 |
+
is: function(s) {
|
752 |
+
return /^(https?|ftp|file):\/\/$/.test(s);
|
753 |
+
},
|
754 |
+
format: function(s) {
|
755 |
+
return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));
|
756 |
+
},
|
757 |
+
type: "text"
|
758 |
+
});
|
759 |
+
|
760 |
+
ts.addParser({
|
761 |
+
id: "isoDate",
|
762 |
+
is: function(s) {
|
763 |
+
return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);
|
764 |
+
},
|
765 |
+
format: function(s) {
|
766 |
+
return $.tablesorter.formatFloat((s != "") ? new Date(s.replace(new RegExp(/-/g),"/")).getTime() : "0");
|
767 |
+
},
|
768 |
+
type: "numeric"
|
769 |
+
});
|
770 |
+
|
771 |
+
ts.addParser({
|
772 |
+
id: "percent",
|
773 |
+
is: function(s) {
|
774 |
+
return /\%$/.test($.trim(s));
|
775 |
+
},
|
776 |
+
format: function(s) {
|
777 |
+
return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));
|
778 |
+
},
|
779 |
+
type: "numeric"
|
780 |
+
});
|
781 |
+
|
782 |
+
ts.addParser({
|
783 |
+
id: "usLongDate",
|
784 |
+
is: function(s) {
|
785 |
+
return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));
|
786 |
+
},
|
787 |
+
format: function(s) {
|
788 |
+
return $.tablesorter.formatFloat(new Date(s).getTime());
|
789 |
+
},
|
790 |
+
type: "numeric"
|
791 |
+
});
|
792 |
+
|
793 |
+
ts.addParser({
|
794 |
+
id: "shortDate",
|
795 |
+
is: function(s) {
|
796 |
+
return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);
|
797 |
+
},
|
798 |
+
format: function(s,table) {
|
799 |
+
var c = table.config;
|
800 |
+
s = s.replace(/\-/g,"/");
|
801 |
+
if(c.dateFormat == "us") {
|
802 |
+
// reformat the string in ISO format
|
803 |
+
s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$1/$2");
|
804 |
+
} else if(c.dateFormat == "uk") {
|
805 |
+
//reformat the string in ISO format
|
806 |
+
s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1");
|
807 |
+
} else if(c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") {
|
808 |
+
s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$1/$2/$3");
|
809 |
+
}
|
810 |
+
return $.tablesorter.formatFloat(new Date(s).getTime());
|
811 |
+
},
|
812 |
+
type: "numeric"
|
813 |
+
});
|
814 |
+
|
815 |
+
ts.addParser({
|
816 |
+
id: "time",
|
817 |
+
is: function(s) {
|
818 |
+
return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);
|
819 |
+
},
|
820 |
+
format: function(s) {
|
821 |
+
return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime());
|
822 |
+
},
|
823 |
+
type: "numeric"
|
824 |
+
});
|
825 |
+
|
826 |
+
|
827 |
+
ts.addParser({
|
828 |
+
id: "metadata",
|
829 |
+
is: function(s) {
|
830 |
+
return false;
|
831 |
+
},
|
832 |
+
format: function(s,table,cell) {
|
833 |
+
var c = table.config, p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName;
|
834 |
+
return $(cell).metadata()[p];
|
835 |
+
},
|
836 |
+
type: "numeric"
|
837 |
+
});
|
838 |
+
|
839 |
+
// add default widgets
|
840 |
+
ts.addWidget({
|
841 |
+
id: "zebra",
|
842 |
+
format: function(table) {
|
843 |
+
if(table.config.debug) { var time = new Date(); }
|
844 |
+
$("tr:visible",table.tBodies[0])
|
845 |
+
.filter(':even')
|
846 |
+
.removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0])
|
847 |
+
.end().filter(':odd')
|
848 |
+
.removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]);
|
849 |
+
if(table.config.debug) { $.tablesorter.benchmark("Applying Zebra widget", time); }
|
850 |
+
}
|
851 |
+
});
|
852 |
+
})(jQuery);
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: freediver
|
|
3 |
Donate link: https://www.networkforgood.org/donation/MakeDonation.aspx?ORGID2=520781390
|
4 |
Tags: Post, posts, comments, links, seo, google, automatic, affiliate
|
5 |
Requires at least: 2.3
|
6 |
-
Tested up to: 4.
|
7 |
Stable tag: trunk
|
8 |
|
9 |
SEO Smart Links provides automatic SEO benefits for your site in addition to custom keyword lists, nofollow and much more.
|
@@ -11,7 +11,7 @@ SEO Smart Links provides automatic SEO benefits for your site in addition to cus
|
|
11 |
|
12 |
== Description ==
|
13 |
|
14 |
-
<a href="http://www.prelovac.com/products/seo-smart-links">SEO Smart Links Premium</a> is now available with
|
15 |
|
16 |
SEO Smart Links provides automatic SEO benefits for your site in addition to custom keyword lists, nofollow and much more.
|
17 |
|
@@ -26,6 +26,13 @@ Everything happens completely transparent, and you can edit the options from the
|
|
26 |
|
27 |
== Changelog ==
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
= 2.7.8 =
|
30 |
* WordPress 3.8 compatibility
|
31 |
|
3 |
Donate link: https://www.networkforgood.org/donation/MakeDonation.aspx?ORGID2=520781390
|
4 |
Tags: Post, posts, comments, links, seo, google, automatic, affiliate
|
5 |
Requires at least: 2.3
|
6 |
+
Tested up to: 4.1
|
7 |
Stable tag: trunk
|
8 |
|
9 |
SEO Smart Links provides automatic SEO benefits for your site in addition to custom keyword lists, nofollow and much more.
|
11 |
|
12 |
== Description ==
|
13 |
|
14 |
+
<a href="http://www.prelovac.com/products/seo-smart-links">SEO Smart Links Premium</a> is now available with premium support and new features.
|
15 |
|
16 |
SEO Smart Links provides automatic SEO benefits for your site in addition to custom keyword lists, nofollow and much more.
|
17 |
|
26 |
|
27 |
== Changelog ==
|
28 |
|
29 |
+
= 3.0 =
|
30 |
+
* Major update of the code
|
31 |
+
* Fixed all reported bugs
|
32 |
+
* Performance improvements
|
33 |
+
* Many new features
|
34 |
+
* If oyu like this update please rate the plugin!
|
35 |
+
|
36 |
= 2.7.8 =
|
37 |
* WordPress 3.8 compatibility
|
38 |
|
seo-links.php
CHANGED
@@ -1,676 +1,1753 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/*
|
4 |
-
Plugin Name: SEO Smart Links
|
5 |
-
Version:
|
6 |
-
Plugin URI: http://www.prelovac.com/vladimir/wordpress-plugins/seo-smart-links
|
7 |
-
Author: Vladimir Prelovac
|
8 |
-
Author URI: http://www.prelovac.com/vladimir
|
9 |
-
Description: SEO Smart Links provides automatic SEO benefits for your site in addition to custom keyword lists, nofollow and much more.
|
10 |
-
*/
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
//
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
676 |
?>
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
Plugin Name: SEO Smart Links
|
5 |
+
Version: 3.0
|
6 |
+
Plugin URI: http://www.prelovac.com/vladimir/wordpress-plugins/seo-smart-links
|
7 |
+
Author: Vladimir Prelovac
|
8 |
+
Author URI: http://www.prelovac.com/vladimir
|
9 |
+
Description: SEO Smart Links provides automatic SEO benefits for your site in addition to custom keyword lists, nofollow and much more.
|
10 |
+
*/
|
11 |
+
|
12 |
+
if (!class_exists('SEOLinks')):
|
13 |
+
class SEOLinks
|
14 |
+
{
|
15 |
+
// Name for our options in the DB
|
16 |
+
var $version = '3.0';
|
17 |
+
var $name = 'SEO Smart Links';
|
18 |
+
var $SEOLinks_DB_option = 'SEOLinks';
|
19 |
+
var $SEOLinks_options;
|
20 |
+
var $key = "SEO Smart Links";
|
21 |
+
|
22 |
+
|
23 |
+
var $meta_boxes = array("custom_process" => array("name" => "box_process", "type" => "checkbox", "title" => "Do not process this post", "description" => "Check to instruct SEO Smart Links not to process this post"), "custom_nolink" => array("name" => "box_nolink", "type" => "checkbox", "title" => "Do not link to this post", "description" => "Check to instruct SEO Smart Links not to link to this post"), "post_keywords" => array("name" => "box_post_keywords", "type" => "input", "title" => "Post Keywords", "description" => "Define additional keywords this post will be recognized as and possibly automatically linked to from other posts. Separate keywords with commma or leave empty if you do not want to use this."), "custom_keywords" => array("name" => "box_custom_keywords", "type" => "textarea", "title" => "Custom Keywords", "description" => "Override the global custom keywords settings for this post. Leave empty to enforce global custom keyword rules."), "custom_add" => array("name" => "add_instead_override", "type" => "checkbox", "title" => "Add the keywords to the global list instead of override", "description" => "Entered keywords should be added to the global custom keywords list"));
|
24 |
+
//"custom_nofollow" => array("name" => "box_nofollow", "type" => "checkbox", "title" => "Do not add nofollow to external links", "description" => "Check to instruct SEO Smart Links not to add nofollow to external links in this post"), "custom_blank" => array("name" => "box_blank", "type" => "checkbox", "title" => "Do not open external links in new window", "description" => "Check to instruct SEO Smart Links to not open external links in new window for this post"),
|
25 |
+
var $cap = 'manage_options';
|
26 |
+
|
27 |
+
//var $cap = 'edit_posts'; // for test version
|
28 |
+
|
29 |
+
// Initialize WordPress hooks
|
30 |
+
function SEOLinks()
|
31 |
+
{
|
32 |
+
$options = $this->get_options();
|
33 |
+
if ($options) {
|
34 |
+
if ($options['post'] || $options['page'])
|
35 |
+
add_filter('the_content', array(
|
36 |
+
&$this,
|
37 |
+
'SEOLinks_the_content_filter'
|
38 |
+
), 200);
|
39 |
+
if ($options['comment'])
|
40 |
+
add_filter('comment_text', array(
|
41 |
+
&$this,
|
42 |
+
'SEOLinks_the_content_filter'
|
43 |
+
), 200);
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
// Add Options Page
|
48 |
+
add_action('admin_menu', array(
|
49 |
+
&$this,
|
50 |
+
'SEOLinks_admin_menu'
|
51 |
+
));
|
52 |
+
|
53 |
+
add_action('init', array(
|
54 |
+
&$this,
|
55 |
+
'redirect_link'
|
56 |
+
));
|
57 |
+
|
58 |
+
if ($options['disable_texturize']) {
|
59 |
+
remove_filter('the_content', 'wptexturize');
|
60 |
+
remove_filter('the_excerpt', 'wptexturize');
|
61 |
+
remove_filter('comment_text', 'wptexturize');
|
62 |
+
remove_filter('the_title', 'wptexturize');
|
63 |
+
}
|
64 |
+
if ($options['box_custom']) {
|
65 |
+
add_action('admin_menu', array(
|
66 |
+
&$this,
|
67 |
+
'create_meta_box'
|
68 |
+
));
|
69 |
+
|
70 |
+
add_action('save_post', array(
|
71 |
+
&$this,
|
72 |
+
'save_meta_box'
|
73 |
+
));
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
function microtime_float()
|
79 |
+
{
|
80 |
+
list($usec, $sec) = explode(" ", microtime());
|
81 |
+
return ((float) $usec + (float) $sec);
|
82 |
+
}
|
83 |
+
|
84 |
+
function redirect_link()
|
85 |
+
{
|
86 |
+
$options = $this->get_options();
|
87 |
+
|
88 |
+
$reqURL = $_SERVER['REQUEST_URI'];
|
89 |
+
$fullURL = 'http://' . $_SERVER['HTTP_HOST'] . $reqURL;
|
90 |
+
|
91 |
+
$hopURL = '/' . $options['base_url'] . '/';
|
92 |
+
|
93 |
+
if ($options['base_url'] != '')
|
94 |
+
if (stristr($fullURL, $hopURL) !== false) {
|
95 |
+
$reqArr = explode('/', $reqURL);
|
96 |
+
foreach ($reqArr as $key => $token) {
|
97 |
+
if ($token == '') {
|
98 |
+
unset($reqArr[$key]);
|
99 |
+
}
|
100 |
+
}
|
101 |
+
$tag = array_pop($reqArr);
|
102 |
+
$tag = strtok($tag, '?');
|
103 |
+
|
104 |
+
$reg = '/(https?\:\/\/[^\n]*)\|\s*' . $tag . '/imsuU';
|
105 |
+
//echo $reg; print_r($options['customkey']);
|
106 |
+
preg_match($reg, $options['customkey'], $matches);
|
107 |
+
|
108 |
+
$urls = explode('|', $matches[1]);
|
109 |
+
$url = trim($urls[rand(0, count($urls) - 1)]);
|
110 |
+
|
111 |
+
|
112 |
+
if ($url) {
|
113 |
+
$redir = trim($url);
|
114 |
+
} else {
|
115 |
+
$redir = get_bloginfo('home');
|
116 |
+
}
|
117 |
+
header("HTTP/1.1 301 Moved Permanently");
|
118 |
+
header('Location: ' . $redir);
|
119 |
+
die();
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
function sidebar_news()
|
124 |
+
{
|
125 |
+
$imgpath = trailingslashit(plugins_url('/i', __FILE__));
|
126 |
+
return '
|
127 |
+
<div style="float: right; width:270px; height:800px; margin-left: 10px;" id="sideblock">
|
128 |
+
|
129 |
+
<div class="ad">
|
130 |
+
<a href="http://managewp.com/?utm_source=Plugins&utm_medium=Banner&utm_content=mwp250_2&utm_campaign=SEOSmartLinks" title="ManageWP.com - Manage your sites from one dashboard"><img src="'.$imgpath.'/mwp250_2.png" alt="ManageWP.com - Manage Multiple WordPress Sites"></a>
|
131 |
+
</div><br>
|
132 |
+
<div class="ad">
|
133 |
+
<a target="_blank" href="http://www.prelovac.com/products/seo-smart-links"><img src="'.$imgpath.'/seosmart125.png" title="SEO Smart Links Premium" alt="SEO Smart Links Premium"></a>
|
134 |
+
<a target="_blank" href="http://www.prelovac.com/products/seo-friendly-images"><img src="'.$imgpath.'/seoimages125_v2.jpg" title="SEO Friendly Images Premium" alt="SEO Friendly Images Premium"></a>
|
135 |
+
</div>
|
136 |
+
|
137 |
+
</div>';
|
138 |
+
}
|
139 |
+
|
140 |
+
function pluralize($word)
|
141 |
+
{
|
142 |
+
static $rules = array(1 => array('o' => 'oes', 'y' => 'ies', 'x' => 'xes', 'f' => 'ves', 's' => 'ses', 'z' => 'zzes'), 2 => array('sh' => 'shes', 'ch' => 'ches'));
|
143 |
+
|
144 |
+
foreach ($rules as $len => $rule) {
|
145 |
+
$key = substr($word, -$len);
|
146 |
+
if (isset($rule[$key])) {
|
147 |
+
return substr($word, 0, -$len) . $rule[$key];
|
148 |
+
}
|
149 |
+
}
|
150 |
+
|
151 |
+
return $word . 's';
|
152 |
+
|
153 |
+
}
|
154 |
+
|
155 |
+
function getexcerpt($text, $length = 25)
|
156 |
+
{
|
157 |
+
$text = strip_tags($text);
|
158 |
+
$words = explode(' ', $text, $length + 1);
|
159 |
+
if (count($words) > $length) {
|
160 |
+
array_pop($words);
|
161 |
+
array_push($words, '[...]');
|
162 |
+
$text = implode(' ', $words);
|
163 |
+
}
|
164 |
+
return $text;
|
165 |
+
}
|
166 |
+
|
167 |
+
function trim_quote($s)
|
168 |
+
{
|
169 |
+
return preg_quote(trim($s), '/');
|
170 |
+
|
171 |
+
}
|
172 |
+
|
173 |
+
function SEOLinks_process_text($text, $recreate_cache = false)
|
174 |
+
{
|
175 |
+
global $wpdb, $post, $wp_version, $id;
|
176 |
+
|
177 |
+
$options = $this->get_options();
|
178 |
+
$min_length = $options['min_length'];
|
179 |
+
|
180 |
+
$kw_array = array();
|
181 |
+
|
182 |
+
$links = 0;
|
183 |
+
$data = 0;
|
184 |
+
$num_links = 0;
|
185 |
+
$sml_meta_data = '';
|
186 |
+
$self_id = -1;
|
187 |
+
|
188 |
+
|
189 |
+
$thisurl = '';
|
190 |
+
|
191 |
+
|
192 |
+
if ($options['box_custom']) {
|
193 |
+
$sml_meta_data = get_post_meta($post->ID, $this->key, true);
|
194 |
+
if (isset($sml_meta_data['box_process']) && $sml_meta_data['box_process'] == 'on')
|
195 |
+
return $text;
|
196 |
+
}
|
197 |
+
|
198 |
+
if (is_feed() && !$options['allowfeed'])
|
199 |
+
return $text;
|
200 |
+
else if (!$recreate_cache && ($options['onlysingle'] && (!is_singular())))
|
201 |
+
return $text;
|
202 |
+
|
203 |
+
$arrignorepost = $this->explode_trim(",", ($options['ignorepost']));
|
204 |
+
|
205 |
+
if (is_page($arrignorepost) || is_single($arrignorepost)) {
|
206 |
+
return $text;
|
207 |
+
}
|
208 |
+
|
209 |
+
if ($post->post_type == 'post' && !$options['post'])
|
210 |
+
return $text;
|
211 |
+
else if ($post->post_type == 'page' && !$options['page'])
|
212 |
+
return $text;
|
213 |
+
|
214 |
+
if ($options['skipdays'] > 0) {
|
215 |
+
$expire = time() - $options['skipdays'] * 24 * 60 * 60;
|
216 |
+
|
217 |
+
if (mysql2date("U", $post->post_date) > $expire)
|
218 |
+
return $text;
|
219 |
+
}
|
220 |
+
|
221 |
+
if ($options['maxtotallinks'] > 0) {
|
222 |
+
$regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
|
223 |
+
$num_links = preg_match_all("/$regexp/siU", $text, $mat_links);
|
224 |
+
if ($num_links >= $options['maxtotallinks'])
|
225 |
+
return $text;
|
226 |
+
else
|
227 |
+
$options['maxlinks'] = min($options['maxlinks'], max(0, $options['maxtotallinks'] - $num_links));
|
228 |
+
}
|
229 |
+
|
230 |
+
$maxlinks = ($options['maxlinks'] > 0) ? $options['maxlinks'] : 0;
|
231 |
+
$maxsingle = ($options['maxsingle'] > 0) ? $options['maxsingle'] : 1;
|
232 |
+
$maxsingleurl = ($options['maxsingleurl'] > 0) ? $options['maxsingleurl'] : 0;
|
233 |
+
$minusage = ($options['minusage'] > 0) ? $options['minusage'] : 0;
|
234 |
+
|
235 |
+
$self = ($post->post_type == 'page' && !$options['pageself']) || ($post->post_type == 'post' && !$options['postself']);
|
236 |
+
if (isset($post_types) && is_array($post_types))
|
237 |
+
foreach ($post_types as $post_type) {
|
238 |
+
$self = $self || ($post->post_type == $post_type && !$post_types_options[$post_type]['self']);
|
239 |
+
}
|
240 |
+
if ($self) {
|
241 |
+
$thisurl = trailingslashit(get_permalink($post->ID));
|
242 |
+
$self_id = $post->ID;
|
243 |
+
}
|
244 |
+
|
245 |
+
|
246 |
+
|
247 |
+
$limit = $options['limit_posts'] > 0 ? $options['limit_posts'] : 500;
|
248 |
+
|
249 |
+
$urls = array();
|
250 |
+
$keyword_count = array();
|
251 |
+
|
252 |
+
$arrignore = $this->explode_trim_lower(",", ($options['ignore']));
|
253 |
+
|
254 |
+
if ($options['samecat']) {
|
255 |
+
$cats = wp_get_post_categories($post->ID);
|
256 |
+
$cats = implode(',', $cats);
|
257 |
+
}
|
258 |
+
|
259 |
+
$urltemplate = html_entity_decode($options['urltemplate']);
|
260 |
+
|
261 |
+
|
262 |
+
|
263 |
+
if ($options['utfsupport'])
|
264 |
+
$reg = $options['casesens'] ? '/(?!\pL)($name)(?!\pL)(?!(?:(?!<\/?[ha].*?>).)*<\/[ha].*?>)(?![^<>]*>)/mUu' : '/(?<!\pL)($name)(?!\pL)(?!(?:(?!<\/?[ha].*?>).)*<\/[ha].*?>)(?![^<>]*>)/iumU';
|
265 |
+
else
|
266 |
+
$reg = $options['casesens'] ? '/\b($name)\b(?!(?:(?!<\/?[ha].*?>).)*<\/[ha].*?>)(?![^<>]*>)/mU' : '/\b($name)\b(?!(?:(?!<\/?[ha].*?>).)*<\/[ha].*?>)(?![^<>]*>)/imU';
|
267 |
+
|
268 |
+
|
269 |
+
|
270 |
+
$strpos_fnc = $options['casesens'] ? 'strpos' : 'stripos';
|
271 |
+
|
272 |
+
$text = " $text ";
|
273 |
+
|
274 |
+
if ($options['box_custom']) {
|
275 |
+
if (isset($sml_meta_data['box_custom_keywords']) && $sml_meta_data['box_custom_keywords']) {
|
276 |
+
if (isset($sml_meta_data['add_instead_override']) && $sml_meta_data['add_instead_override'] == 'on')
|
277 |
+
$options['customkey'] = $sml_meta_data['box_custom_keywords'] . "\n" . $options['customkey'];
|
278 |
+
else
|
279 |
+
$options['customkey'] = $sml_meta_data['box_custom_keywords'];
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
|
284 |
+
|
285 |
+
|
286 |
+
|
287 |
+
if (!empty($options['customkey'])) {
|
288 |
+
$line_array = explode("\n", stripslashes($options['customkey']));
|
289 |
+
|
290 |
+
foreach ($line_array as $line) {
|
291 |
+
$parts = explode("|", $line);
|
292 |
+
|
293 |
+
//$keywords = trim($parts[0]);
|
294 |
+
|
295 |
+
$keywords = ($parts[0]); // no trimming since 1.6.2
|
296 |
+
$uris = trim($parts[1]);
|
297 |
+
if (isset($parts[2]))
|
298 |
+
$word = trim($parts[2]);
|
299 |
+
else $word = '';
|
300 |
+
|
301 |
+
|
302 |
+
if ($options['trimspaces'])
|
303 |
+
$chunks = array_map('trim', explode($options['custom_separator'] != '' ? $options['custom_separator'] : ',', $keywords));
|
304 |
+
|
305 |
+
else
|
306 |
+
$chunks = explode($options['custom_separator'] != '' ? $options['custom_separator'] : ',', $keywords);
|
307 |
+
|
308 |
+
$url = '';
|
309 |
+
|
310 |
+
if ($word)
|
311 |
+
$url = get_bloginfo('home') . '/' . $options['base_url'] . '/' . $word;
|
312 |
+
else if (!empty($uris)) {
|
313 |
+
$temp = explode($options['custom_separator'] != '' ? $options['custom_separator'] : ',', $uris);
|
314 |
+
$url = trim($temp[rand(0, count($temp) - 1)]);
|
315 |
+
}
|
316 |
+
|
317 |
+
if ($options['check_plural']) {
|
318 |
+
for ($i = 0; $i < count($chunks); $i++)
|
319 |
+
$chunks[$i] = $chunks[$i] . '| ' . $this->pluralize($chunks[$i]);
|
320 |
+
}
|
321 |
+
|
322 |
+
$total_chunks = count($chunks);
|
323 |
+
$i = 0;
|
324 |
+
if ($url) {
|
325 |
+
if ($options['customkey_preventduplicatelink'] == TRUE)
|
326 |
+
$kw_array[implode('| ', $chunks)] = $url;
|
327 |
+
else
|
328 |
+
while ($i < $total_chunks) {
|
329 |
+
if (!empty($chunks[$i]))
|
330 |
+
$kw_array[$chunks[$i]] = $url;
|
331 |
+
$i++;
|
332 |
+
}
|
333 |
+
}
|
334 |
+
}
|
335 |
+
}
|
336 |
+
|
337 |
+
|
338 |
+
$name_plural = '';
|
339 |
+
|
340 |
+
foreach ($kw_array as $name => $url) {
|
341 |
+
if ($url && (!$maxlinks || ($links < $maxlinks)) && (!$maxsingleurl || $urls[$url] < $maxsingleurl) && (trailingslashit($url) != $thisurl) && !in_array($options['casesens'] ? $name : strtolower($name), $arrignore)) {
|
342 |
+
$chunks_match = explode('| ', $name);
|
343 |
+
|
344 |
+
$cnt = count($chunks_match);
|
345 |
+
for ($i = 0; $i < $cnt; $i++) {
|
346 |
+
$name = $chunks_match[$i];
|
347 |
+
if ($name && (!$maxsingle || (isset($keyword_count[$name]) && $keyword_count[$name]) < $maxsingle) && $strpos_fnc($text, $name) !== false) {
|
348 |
+
$replace = str_replace(array(
|
349 |
+
'{keyword}',
|
350 |
+
'{url}',
|
351 |
+
'{description}'
|
352 |
+
), array(
|
353 |
+
'$1',
|
354 |
+
$url,
|
355 |
+
'$1'
|
356 |
+
), $urltemplate);
|
357 |
+
|
358 |
+
$regexp = str_replace('$name', preg_quote($name, '/'), $reg);
|
359 |
+
|
360 |
+
$newtext = preg_replace($regexp, $replace, $text, $maxsingle);
|
361 |
+
|
362 |
+
if ($newtext != $text) {
|
363 |
+
$links++;
|
364 |
+
$text = $newtext;
|
365 |
+
if (!isset($urls[$url]))
|
366 |
+
$urls[$url] = 1;
|
367 |
+
else
|
368 |
+
$urls[$url]++;
|
369 |
+
|
370 |
+
if (!isset($keyword_count[$name]))
|
371 |
+
$keyword_count[$name] = 1;
|
372 |
+
else
|
373 |
+
$keyword_count[$name]++;
|
374 |
+
|
375 |
+
|
376 |
+
|
377 |
+
break;
|
378 |
+
}
|
379 |
+
}
|
380 |
+
}
|
381 |
+
}
|
382 |
+
}
|
383 |
+
|
384 |
+
|
385 |
+
|
386 |
+
$urltemplate = str_replace('{url}', '$$$url$$$', $urltemplate);
|
387 |
+
|
388 |
+
$porderby = 'ORDER BY ' . ($options['limit_post_order'] == 'date' ? 'post_date ' : 'LENGTH(post_title) ') . ($options['limit_post_sort'] == 'asc' ? 'ASC' : 'DESC');
|
389 |
+
|
390 |
+
if ($options['lposts'] || $options['lpages']) {
|
391 |
+
if ($options['samecat'] && $cats != '')
|
392 |
+
$query = "
|
393 |
+
SELECT DISTINCT post_title, ID, post_type, post_name
|
394 |
+
FROM $wpdb->posts wposts
|
395 |
+
LEFT JOIN $wpdb->postmeta wpostmeta ON wposts.ID = wpostmeta.post_id
|
396 |
+
LEFT JOIN $wpdb->term_relationships ON (wposts.ID = $wpdb->term_relationships.object_id)
|
397 |
+
LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
|
398 |
+
WHERE (post_type='page'
|
399 |
+
OR ($wpdb->term_taxonomy.taxonomy = 'category' AND $wpdb->term_taxonomy.term_id IN($cats)))
|
400 |
+
AND post_status = 'publish' AND LENGTH(post_title)>=$min_length $porderby LIMIT $limit";
|
401 |
+
else
|
402 |
+
$query = "SELECT post_title, ID, post_type, post_name FROM $wpdb->posts WHERE post_status = 'publish' AND LENGTH(post_title)>=$min_length $porderby LIMIT $limit";
|
403 |
+
|
404 |
+
$posts = $wpdb->get_results($query);
|
405 |
+
|
406 |
+
|
407 |
+
// $starttime = $this->microtime_float();
|
408 |
+
|
409 |
+
|
410 |
+
foreach ($posts as $postitem) {
|
411 |
+
if ((($options['lposts'] && $postitem->post_type == 'post') || ($options['lpages'] && $postitem->post_type == 'page')) && (!$maxlinks || ($links < $maxlinks)) && ($postitem->ID != $self_id) && (!in_array(($options['casesens'] ? ($postitem->post_title) : strtolower(($postitem->post_title))), $arrignore))) {
|
412 |
+
$sml_target_data = '';
|
413 |
+
|
414 |
+
if ($options['box_custom']) {
|
415 |
+
$sml_target_data = get_post_meta($postitem->ID, $this->key, true);
|
416 |
+
|
417 |
+
if (isset($sml_target_data['box_nolink']) && $sml_target_data['box_nolink'] == 'on') {
|
418 |
+
continue;
|
419 |
+
}
|
420 |
+
}
|
421 |
+
$name = trim($postitem->post_title);
|
422 |
+
|
423 |
+
|
424 |
+
$checking = true;
|
425 |
+
$checkedkw = array();
|
426 |
+
|
427 |
+
while ($checking) {
|
428 |
+
$found = false;
|
429 |
+
|
430 |
+
if ((!$maxsingle || $keyword_count[$name] < $maxsingle) && !$checkedkw[$name] && $strpos_fnc($text, $name) !== false) {
|
431 |
+
$found = true;
|
432 |
+
} else if ($options['match_slug']) {
|
433 |
+
$name = str_replace('-', ' ', $postitem->post_name);
|
434 |
+
if (!in_array($name, $arrignore) && (!$maxsingle || $keyword_count[$name] < $maxsingle) && !$checkedkw[$name] && $strpos_fnc($text, $name) !== false)
|
435 |
+
$found = true;
|
436 |
+
|
437 |
+
}
|
438 |
+
|
439 |
+
|
440 |
+
if (!$found && isset($sml_target_data['box_post_keywords']) && $sml_target_data['box_post_keywords']) {
|
441 |
+
$chunks_match = array_map('trim', explode(",", $sml_target_data['box_post_keywords']));
|
442 |
+
|
443 |
+
$cnt = count($chunks_match);
|
444 |
+
for ($i = 0; $i < $cnt; $i++) {
|
445 |
+
$name = $chunks_match[$i];
|
446 |
+
if ($name && (!$maxsingle || $keyword_count[$name] < $maxsingle) && !$checkedkw[$name] && $strpos_fnc($text, $name) !== false) {
|
447 |
+
$found = true;
|
448 |
+
break;
|
449 |
+
}
|
450 |
+
}
|
451 |
+
}
|
452 |
+
|
453 |
+
|
454 |
+
|
455 |
+
if ($found) {
|
456 |
+
$regexp = str_replace('$name', preg_quote($name, '/'), $reg);
|
457 |
+
|
458 |
+
$replace = str_replace('{keyword}', '$1', $urltemplate);
|
459 |
+
|
460 |
+
if (strpos($urltemplate, '{description}') !== false) {
|
461 |
+
$query = "SELECT post_excerpt, post_content FROM $wpdb->posts WHERE post_status = 'publish' AND ID=$postitem->ID LIMIT 1";
|
462 |
+
$postex = $wpdb->get_row($query);
|
463 |
+
$desc = ($postex->post_excerpt != '') ? $postex->post_excerpt : $this->getexcerpt($postex->post_content, 25);
|
464 |
+
$replace = str_replace('{description}', $desc, $replace);
|
465 |
+
}
|
466 |
+
|
467 |
+
$newtext = preg_replace($regexp, $replace, $text, $maxsingle);
|
468 |
+
|
469 |
+
$checkedkw[$name] = 1;
|
470 |
+
|
471 |
+
if ($newtext != $text) {
|
472 |
+
$url = get_permalink($postitem->ID);
|
473 |
+
if (!$maxsingleurl || $urls[$url] < $maxsingleurl) {
|
474 |
+
$links++;
|
475 |
+
|
476 |
+
$text = str_replace('$$$url$$$', $url, $newtext);
|
477 |
+
|
478 |
+
if (!isset($urls[$url]))
|
479 |
+
$urls[$url] = 1;
|
480 |
+
else
|
481 |
+
$urls[$url]++;
|
482 |
+
|
483 |
+
if (!isset($keyword_count[$name]))
|
484 |
+
$keyword_count[$name] = 1;
|
485 |
+
else
|
486 |
+
$keyword_count[$name]++;
|
487 |
+
|
488 |
+
if ($urls[$url] >= $maxsingleurl)
|
489 |
+
$checking = false;
|
490 |
+
}
|
491 |
+
}
|
492 |
+
|
493 |
+
} else
|
494 |
+
$checking = false;
|
495 |
+
|
496 |
+
}
|
497 |
+
}
|
498 |
+
}
|
499 |
+
}
|
500 |
+
/* $endtime = $this->microtime_float();
|
501 |
+
$totaltime =($endtime - $starttime)*1000;
|
502 |
+
|
503 |
+
echo 'Post: '.$totaltime.'<br>'; */
|
504 |
+
|
505 |
+
|
506 |
+
$taxs['category'] = $options['lcats'];
|
507 |
+
$taxs['post_tag'] = $options['ltags'];
|
508 |
+
|
509 |
+
if (version_compare($wp_version, '2.7.9', '>')) {
|
510 |
+
$args = array(
|
511 |
+
'public' => true,
|
512 |
+
'_builtin' => false
|
513 |
+
|
514 |
+
);
|
515 |
+
$taxonomies = get_taxonomies($args, 'names');
|
516 |
+
$checktax = $options['tax'];
|
517 |
+
|
518 |
+
if ($taxonomies) {
|
519 |
+
foreach ($taxonomies as $taxonomy) {
|
520 |
+
if (isset($options['tax']['smltax_' . $taxonomy]))
|
521 |
+
$taxs[$taxonomy] = $options['tax']['smltax_' . $taxonomy];
|
522 |
+
|
523 |
+
}
|
524 |
+
}
|
525 |
+
|
526 |
+
}
|
527 |
+
|
528 |
+
foreach ($taxs as $tax_slug => $tax_option)
|
529 |
+
if ($tax_option) {
|
530 |
+
$query = "SELECT $wpdb->terms.name, $wpdb->terms.term_id FROM $wpdb->terms LEFT JOIN $wpdb->term_taxonomy ON $wpdb->terms.term_id = $wpdb->term_taxonomy.term_id WHERE $wpdb->term_taxonomy.taxonomy = '$tax_slug' AND LENGTH($wpdb->terms.name)>=$min_length AND $wpdb->term_taxonomy.count >= $minusage ORDER BY LENGTH($wpdb->terms.name) ASC LIMIT $limit";
|
531 |
+
$tags = $wpdb->get_results($query);
|
532 |
+
|
533 |
+
|
534 |
+
foreach ($tags as $tag) {
|
535 |
+
if ((!$maxlinks || ($links < $maxlinks)) && !in_array(strtolower($tag->name), $arrignore)) {
|
536 |
+
if ((!$maxsingle || $keyword_count[$tag->name] < $maxsingle) && $strpos_fnc($text, $tag->name) !== false) {
|
537 |
+
$regexp = str_replace('$name', preg_quote($tag->name, '/'), $reg);
|
538 |
+
|
539 |
+
$replace = str_replace('{keyword}', '$1', $urltemplate);
|
540 |
+
if (strpos($urltemplate, '{description}') !== false) {
|
541 |
+
$desc = strip_tags(term_description($tag->term_id, $tax_slug));
|
542 |
+
if ($desc == '')
|
543 |
+
$desc = '$1';
|
544 |
+
|
545 |
+
$replace = str_replace('{description}', $desc, $replace);
|
546 |
+
}
|
547 |
+
|
548 |
+
$newtext = preg_replace($regexp, $replace, $text, $maxsingle);
|
549 |
+
if ($newtext != $text) {
|
550 |
+
$term = get_term($tag->term_id, $tax_slug);
|
551 |
+
$url = get_term_link($term, $tax_slug);
|
552 |
+
|
553 |
+
if (!$maxsingleurl || $urls[$url] < $maxsingleurl) {
|
554 |
+
$links++;
|
555 |
+
$text = str_replace('$$$url$$$', $url, $newtext);
|
556 |
+
|
557 |
+
if (!isset($urls[$url]))
|
558 |
+
$urls[$url] = 1;
|
559 |
+
else
|
560 |
+
$urls[$url]++;
|
561 |
+
|
562 |
+
if (!isset($keyword_count[$name]))
|
563 |
+
$keyword_count[$name] = 1;
|
564 |
+
else
|
565 |
+
$keyword_count[$name]++;
|
566 |
+
|
567 |
+
}
|
568 |
+
}
|
569 |
+
}
|
570 |
+
}
|
571 |
+
}
|
572 |
+
}
|
573 |
+
|
574 |
+
|
575 |
+
|
576 |
+
|
577 |
+
if (($options['blanko'] || $options['nofolo']) && !$recreate_cache) {
|
578 |
+
$link = parse_url(get_bloginfo('wpurl'));
|
579 |
+
$host = preg_quote($link['host']);
|
580 |
+
$base_url = preg_quote($options['base_url']);
|
581 |
+
|
582 |
+
if ($options['blanko'] )
|
583 |
+
{
|
584 |
+
if ($base_url != '')
|
585 |
+
$text = preg_replace('%(<a[^>]+)(href="https?://)((?:(?!(' . $host . '))[^"])+|(?:(?=(' . $host . '/' . $base_url . '/))[^"]+))"%i', '$1$2$3" target="_blank"', $text);
|
586 |
+
else
|
587 |
+
$text = preg_replace('%(<a[^>]+)(href="https?://)((?:(?!(' . $host . '))[^"])+)"%i', '$1$2$3" target="_blank"', $text);
|
588 |
+
}
|
589 |
+
|
590 |
+
if ($options['nofolo'] ) {
|
591 |
+
$follow_list = '';
|
592 |
+
if ($options['nofollow_whitelist']) {
|
593 |
+
$follow_array = explode("\n", $options['nofollow_whitelist']);
|
594 |
+
$empty_elements = array_keys($follow_array, "");
|
595 |
+
foreach ($empty_elements as $e)
|
596 |
+
unset($follow_array[$e]);
|
597 |
+
$follow_list = '|(?:www\.)?' . implode('|(?:www\.)?', $follow_array);
|
598 |
+
}
|
599 |
+
|
600 |
+
$text = preg_replace('%(<a[^>]+)(href="https?://)((?:(?!(' . $host . $follow_list . '))[^"])+)"%i', '$1$2$3" rel="nofollow" ', $text);
|
601 |
+
}
|
602 |
+
|
603 |
+
}
|
604 |
+
return trim($text);
|
605 |
+
|
606 |
+
}
|
607 |
+
|
608 |
+
function SEOLinks_the_content_filter($text)
|
609 |
+
{
|
610 |
+
$result = $this->SEOLinks_process_text($text, false);
|
611 |
+
|
612 |
+
return $result;
|
613 |
+
}
|
614 |
+
|
615 |
+
|
616 |
+
function explode_trim($separator, $text)
|
617 |
+
{
|
618 |
+
$arr = explode($separator, $text);
|
619 |
+
|
620 |
+
$ret = array();
|
621 |
+
foreach ($arr as $e) {
|
622 |
+
$ret[] = trim($e);
|
623 |
+
}
|
624 |
+
return $ret;
|
625 |
+
}
|
626 |
+
|
627 |
+
function explode_trim_lower($separator, $text)
|
628 |
+
{
|
629 |
+
$arr = explode($separator, $text);
|
630 |
+
|
631 |
+
$ret = array();
|
632 |
+
foreach ($arr as $e) {
|
633 |
+
$ret[] = strtolower(trim($e));
|
634 |
+
}
|
635 |
+
return $ret;
|
636 |
+
}
|
637 |
+
|
638 |
+
// Handle our options
|
639 |
+
function get_options()
|
640 |
+
{
|
641 |
+
$options = array(
|
642 |
+
'post' => 'on',
|
643 |
+
'postself' => '',
|
644 |
+
'page' => 'on',
|
645 |
+
'pageself' => '',
|
646 |
+
'comment' => '',
|
647 |
+
'lposts' => 'on',
|
648 |
+
'lpages' => '',
|
649 |
+
'lcats' => '',
|
650 |
+
'ltags' => '',
|
651 |
+
'ignore' => 'about,contact',
|
652 |
+
'ignorepost' => 'contact,',
|
653 |
+
'maxlinks' => 3,
|
654 |
+
'maxsingle' => 1,
|
655 |
+
'minusage' => 1,
|
656 |
+
'customkey' => '',
|
657 |
+
'customkey_preventduplicatelink' => FALSE,
|
658 |
+
'nofoln' => '',
|
659 |
+
'nofolo' => '',
|
660 |
+
'blankn' => '',
|
661 |
+
'blanko' => '',
|
662 |
+
'onlysingle' => 'on',
|
663 |
+
'casesens' => '',
|
664 |
+
'allowfeed' => '',
|
665 |
+
'maxsingleurl' => '1',
|
666 |
+
'samecat' => 'on',
|
667 |
+
'urltemplate' => '<a href="{url}">{keyword}</a>',
|
668 |
+
'utfsupport' => '',
|
669 |
+
'disable_texturize' => '',
|
670 |
+
'match_slug' => '',
|
671 |
+
'limit_posts' => 500,
|
672 |
+
'customkey_form_file' => '',
|
673 |
+
'append_or_replace' => '',
|
674 |
+
'box_custom' => '',
|
675 |
+
'base_url' => 'go',
|
676 |
+
'time' => 0,
|
677 |
+
'visual_kw_edit' => '',
|
678 |
+
'custom_separator' => ',',
|
679 |
+
'min_length' => 5,
|
680 |
+
'check_plural' => '',
|
681 |
+
'add_instead_override' => '',
|
682 |
+
'nofollow_whitelist' => '',
|
683 |
+
'maxtotallinks' => 0,
|
684 |
+
'limit_post_order' => 'title',
|
685 |
+
'limit_post_sort' => 'asc',
|
686 |
+
'skipdays' => 0,
|
687 |
+
'trimspaces' => 'on'
|
688 |
+
);
|
689 |
+
|
690 |
+
$saved = get_option($this->SEOLinks_DB_option);
|
691 |
+
|
692 |
+
|
693 |
+
if (!empty($saved)) {
|
694 |
+
foreach ($saved as $key => $option)
|
695 |
+
$options[$key] = $option;
|
696 |
+
}
|
697 |
+
|
698 |
+
if ($saved != $options)
|
699 |
+
update_option($this->SEOLinks_DB_option, $options);
|
700 |
+
|
701 |
+
return $options;
|
702 |
+
|
703 |
+
}
|
704 |
+
|
705 |
+
|
706 |
+
|
707 |
+
// Set up everything
|
708 |
+
function install()
|
709 |
+
{
|
710 |
+
global $wp_version;
|
711 |
+
|
712 |
+
$exit_msg = 'SEO Smart Links requires WordPress 3.0 or newer. <a href="http://codex.wordpress.org/Upgrading_WordPress">Please update!</a>';
|
713 |
+
|
714 |
+
if (version_compare($wp_version, "3.0", "<")) {
|
715 |
+
exit($exit_msg);
|
716 |
+
}
|
717 |
+
|
718 |
+
$SEOLinks_options = $this->get_options();
|
719 |
+
|
720 |
+
|
721 |
+
}
|
722 |
+
|
723 |
+
|
724 |
+
|
725 |
+
|
726 |
+
|
727 |
+
function getCustomKeywords()
|
728 |
+
{
|
729 |
+
$options = $this->get_options();
|
730 |
+
|
731 |
+
return $options['customkey'];
|
732 |
+
}
|
733 |
+
|
734 |
+
|
735 |
+
|
736 |
+
function handle_import()
|
737 |
+
{
|
738 |
+
$options = $this->get_options();
|
739 |
+
|
740 |
+
|
741 |
+
if (isset($_POST['submitted'])) {
|
742 |
+
check_admin_referer('seo-smart-links');
|
743 |
+
|
744 |
+
if ($_POST['Submit'] == 'Import from CSV') {
|
745 |
+
if ($_FILES["csv_file"]["tmp_name"] && ($file_open = file($_FILES["csv_file"]["tmp_name"])) != FALSE) {
|
746 |
+
$values = "\n";
|
747 |
+
$cnt = 0;
|
748 |
+
foreach ($file_open as $line_num => $line) {
|
749 |
+
$cnt++;
|
750 |
+
$values .= ($line);
|
751 |
+
}
|
752 |
+
$options['customkey'] = $values;
|
753 |
+
echo '<div class="updated fade"><p>Keyword import successful. (' . $cnt . ' keywords total)</p></div>';
|
754 |
+
} else
|
755 |
+
echo '<div class="updated fade"><p>No file specified, please try again.</p></div>';
|
756 |
+
} else if ($_POST['Submit'] == 'Upload') {
|
757 |
+
if ($_FILES["config_file"]["tmp_name"] && ($file_open = file_get_contents($_FILES["config_file"]["tmp_name"])) != FALSE) {
|
758 |
+
$decoded = base64_decode($file_open);
|
759 |
+
|
760 |
+
$unserialized = unserialize($decoded);
|
761 |
+
|
762 |
+
if ($unserialized == FALSE)
|
763 |
+
echo '<div class="updated fade"><p>Configuration file corrupted, import aborted.</p></div>';
|
764 |
+
else {
|
765 |
+
$options = $unserialized;
|
766 |
+
echo '<div class="updated fade"><p>Configuration imported.</p></div>';
|
767 |
+
}
|
768 |
+
} else
|
769 |
+
echo '<div class="updated fade"><p>No file specified, please try again.</p></div>';
|
770 |
+
}
|
771 |
+
$options['time'] = time();
|
772 |
+
update_option($this->SEOLinks_DB_option, $options);
|
773 |
+
}
|
774 |
+
|
775 |
+
$action_url = $_SERVER['REQUEST_URI'];
|
776 |
+
$imgpath = trailingslashit(get_option('siteurl')) . 'wp-content/plugins/' . dirname(plugin_basename(__FILE__)) . '/i';
|
777 |
+
$nonce = wp_create_nonce('seo-smart-links');
|
778 |
+
|
779 |
+
$sidebar_news = $this->sidebar_news();
|
780 |
+
echo <<<END
|
781 |
+
|
782 |
+
<div class="wrap" >
|
783 |
+
<img class="logoimg" src="$imgpath/logo.png" ><h2>$this->name</h2><h3>Import/Export</h3>
|
784 |
+
|
785 |
+
<a href="admin.php?page=sml_options">Options</a> <a href="admin.php?page=sml_custom_keywords">Custom Keywords</a> <a href="admin.php?page=sml_import">Import/Export</a> <a href="admin.php?page=sml_about">About</a>
|
786 |
+
|
787 |
+
<div id="poststuff" style="margin-top:10px;">
|
788 |
+
|
789 |
+
|
790 |
+
$sidebar_news
|
791 |
+
<div id="mainblock" >
|
792 |
+
|
793 |
+
<div class="dbx-content">
|
794 |
+
|
795 |
+
<h2>Import/Export Keywords</h2>
|
796 |
+
<p>You can export keywords in .csv file readable in most spreadsheets. Alternatively you can import your saved keywords from a .csv file.</p>
|
797 |
+
<form name="SEOLinks_import" action="$action_url" method="post" enctype="multipart/form-data">
|
798 |
+
<input type="hidden" id="_wpnonce" name="_wpnonce" value="$nonce" />
|
799 |
+
<input type="hidden" name="submitted" value="1" />
|
800 |
+
<span style="">
|
801 |
+
<p>Select a CSV file to import:</p>
|
802 |
+
<input type="file" name="csv_file" /><input type="submit" name="Submit" value="Import from CSV" class="button-primary" /> <br><br>
|
803 |
+
|
804 |
+
<p>Click to export keywords to a CSV file <a class="button-primary" href="$action_url&sml_csv=true" id="save_file_dialog" >Export to CSV</a></p>
|
805 |
+
|
806 |
+
</span>
|
807 |
+
</form>
|
808 |
+
|
809 |
+
<h2>Import/Export Configuration</h2>
|
810 |
+
<p>You can import/export your entire configuration.</p>
|
811 |
+
<form name="SEOLinks_import_options" action="$action_url" method="post" enctype="multipart/form-data">
|
812 |
+
<input type="hidden" id="_wpnonce" name="_wpnonce" value="$nonce" />
|
813 |
+
<input type="hidden" name="submitted" value="1" />
|
814 |
+
<span style="">
|
815 |
+
<p>Select a configuration file to import:</p>
|
816 |
+
<input type="file" name="config_file" /><input type="submit" name="Submit" value="Upload" class="button-primary" /> <br><br>
|
817 |
+
|
818 |
+
<p>Export configuration: <a class="button-primary" href="$action_url&sml_options=true" id="save_file_dialog" >Download</a></p>
|
819 |
+
|
820 |
+
</span>
|
821 |
+
</form>
|
822 |
+
|
823 |
+
|
824 |
+
</div>
|
825 |
+
|
826 |
+
<div>
|
827 |
+
|
828 |
+
|
829 |
+
</div>
|
830 |
+
<br/><br/><h3> </h3>
|
831 |
+
</div>
|
832 |
+
|
833 |
+
</div>
|
834 |
+
|
835 |
+
<h5>Another fine WordPress plugin by <a href="http://www.prelovac.com/vladimir/">Vladimir Prelovac</a></h5>
|
836 |
+
</div>
|
837 |
+
END;
|
838 |
+
|
839 |
+
|
840 |
+
}
|
841 |
+
|
842 |
+
|
843 |
+
|
844 |
+
function handle_about()
|
845 |
+
{
|
846 |
+
global $wp_version;
|
847 |
+
$options = $this->get_options();
|
848 |
+
|
849 |
+
|
850 |
+
|
851 |
+
$action_url = $_SERVER['REQUEST_URI'];
|
852 |
+
$nonce = wp_create_nonce('seo-smart-links');
|
853 |
+
|
854 |
+
$imgpath = trailingslashit(get_option('siteurl')) . 'wp-content/plugins/' . dirname(plugin_basename(__FILE__)) . '/i';
|
855 |
+
|
856 |
+
|
857 |
+
$lic_msg = '<p>Welcome to ' . $this->name . '.</p><p>Thank you for using my plugin, if you find it useful please <a href="https://wordpress.org/plugins/seo-automatic-links/">rate it</a>.</p>';
|
858 |
+
$sidebar_news = $this->sidebar_news();
|
859 |
+
|
860 |
+
echo <<<END
|
861 |
+
|
862 |
+
<div class="wrap" >
|
863 |
+
|
864 |
+
<img class="logoimg" src="$imgpath/logo.png" ><h2>$this->name</h2><h3>About</h3>
|
865 |
+
|
866 |
+
<a href="admin.php?page=sml_options">Options</a> <a href="admin.php?page=sml_custom_keywords">Custom Keywords</a> <a href="admin.php?page=sml_import">Import/Export</a> <a href="admin.php?page=sml_about">About</a>
|
867 |
+
|
868 |
+
<div id="poststuff" style="margin-top:10px;">
|
869 |
+
|
870 |
+
$sidebar_news
|
871 |
+
|
872 |
+
<div id="mainblock" >
|
873 |
+
|
874 |
+
<div class="dbx-content">
|
875 |
+
<form name="SEOLinks_about" action="$action_url" method="post">
|
876 |
+
<input type="hidden" id="_wpnonce" name="_wpnonce" value="$nonce" />
|
877 |
+
<input type="hidden" name="submitted" value="1" />
|
878 |
+
$lic_msg
|
879 |
+
|
880 |
+
Version: $this->version $upd_msg
|
881 |
+
</form>
|
882 |
+
</div>
|
883 |
+
|
884 |
+
<div>
|
885 |
+
|
886 |
+
|
887 |
+
</div>
|
888 |
+
<br/><br/><h3> </h3>
|
889 |
+
</div>
|
890 |
+
|
891 |
+
</div>
|
892 |
+
|
893 |
+
<h5>Another fine WordPress plugin by <a href="http://www.prelovac.com/vladimir/">Vladimir Prelovac</a></h5>
|
894 |
+
</div>
|
895 |
+
END;
|
896 |
+
|
897 |
+
|
898 |
+
}
|
899 |
+
|
900 |
+
|
901 |
+
|
902 |
+
|
903 |
+
function handle_custom_keywords()
|
904 |
+
{
|
905 |
+
$options = $this->get_options();
|
906 |
+
|
907 |
+
|
908 |
+
if (isset($_POST['submitted'])) {
|
909 |
+
check_admin_referer('seo-smart-links');
|
910 |
+
|
911 |
+
|
912 |
+
|
913 |
+
if ($_POST['Submit'] == 'Import from CSV') {
|
914 |
+
if ($_FILES["csv_file"]["tmp_name"] && ($file_open = file($_FILES["csv_file"]["tmp_name"])) != FALSE) {
|
915 |
+
$values = "\n";
|
916 |
+
$cnt = 0;
|
917 |
+
foreach ($file_open as $line_num => $line) {
|
918 |
+
$cnt++;
|
919 |
+
$values .= ($line);
|
920 |
+
}
|
921 |
+
$options['customkey'] = $values;
|
922 |
+
echo '<div class="updated fade"><p>Keyword import successful. (' . $cnt . ' keywords total)</p></div>';
|
923 |
+
} else
|
924 |
+
echo '<div class="updated fade"><p>No file specified, please try again.</p></div>';
|
925 |
+
} else if ($_POST['Submit'] == 'Upload') {
|
926 |
+
if ($_FILES["config_file"]["tmp_name"] && ($file_open = file_get_contents($_FILES["config_file"]["tmp_name"])) != FALSE) {
|
927 |
+
//echo($file_open);
|
928 |
+
$decoded = base64_decode($file_open);
|
929 |
+
//echo($decoded);
|
930 |
+
$unserialized = unserialize($decoded);
|
931 |
+
|
932 |
+
if ($unserialized == FALSE)
|
933 |
+
echo '<div class="updated fade"><p>Configuration file corrupted, import aborted.</p></div>';
|
934 |
+
else {
|
935 |
+
$options = $unserialized;
|
936 |
+
echo '<div class="updated fade"><p>Configuration imported.</p></div>';
|
937 |
+
}
|
938 |
+
} else
|
939 |
+
echo '<div class="updated fade"><p>No file specified, please try again.</p></div>';
|
940 |
+
} else {
|
941 |
+
$options['customkey'] = preg_replace('/\r\n|\r/', "\n", $_POST['customkey']);
|
942 |
+
$options['customkey_preventduplicatelink'] = $_POST['customkey_preventduplicatelink'];
|
943 |
+
$options['append_or_replace'] = $_POST['append_or_replace'];
|
944 |
+
$options['visual_kw_edit'] = $_POST['visual_kw_edit'];
|
945 |
+
$options['custom_separator'] = $_POST['custom_separator'] != '' ? $_POST['custom_separator'] : ',';
|
946 |
+
$options['check_plural'] = $_POST['check_plural'];
|
947 |
+
$options['trimspaces'] = $_POST['trimspaces'];
|
948 |
+
|
949 |
+
|
950 |
+
echo '<div class="updated fade"><p>Custom keywords options saved.</p></div>';
|
951 |
+
|
952 |
+
}
|
953 |
+
$options['time'] = time();
|
954 |
+
update_option($this->SEOLinks_DB_option, $options);
|
955 |
+
|
956 |
+
|
957 |
+
}
|
958 |
+
|
959 |
+
|
960 |
+
|
961 |
+
|
962 |
+
$action_url = $_SERVER['REQUEST_URI'];
|
963 |
+
$imgpath = trailingslashit(get_option('siteurl')) . 'wp-content/plugins/' . dirname(plugin_basename(__FILE__)) . '/i';
|
964 |
+
|
965 |
+
|
966 |
+
$customkey = htmlspecialchars(stripslashes($options['customkey']));
|
967 |
+
$customkey_preventduplicatelink = $options['customkey_preventduplicatelink'] == 'on' ? 'checked' : '';
|
968 |
+
$append_or_replace = $options['append_or_replace'] == 'on' ? 'checked' : '';
|
969 |
+
$visual_kw_edit = $options['visual_kw_edit'] == 'on' ? 'checked' : '';
|
970 |
+
$custom_separator = stripslashes($options['custom_separator']);
|
971 |
+
$check_plural = $options['check_plural'] == 'on' ? 'checked' : '';
|
972 |
+
$trimspaces = $options['trimspaces'] == 'on' ? 'checked' : '';
|
973 |
+
|
974 |
+
|
975 |
+
|
976 |
+
|
977 |
+
$lines = explode("\n", $customkey);
|
978 |
+
$data = array();
|
979 |
+
$old = 0;
|
980 |
+
foreach ($lines as $k => $v) {
|
981 |
+
$parts = explode('|', $v);
|
982 |
+
|
983 |
+
if (empty($parts[1])) { // import old settings
|
984 |
+
$old = 1;
|
985 |
+
$temp = explode($options['custom_separator'], $v);
|
986 |
+
$u = trim($temp[count($temp) - 1]);
|
987 |
+
unset($temp[count($temp) - 1]);
|
988 |
+
$w = trim(implode($options['custom_separator'], $temp));
|
989 |
+
if ($w && $u)
|
990 |
+
$lines[$k] = $w . '|' . $u;
|
991 |
+
} else
|
992 |
+
break;
|
993 |
+
|
994 |
+
}
|
995 |
+
if ($old)
|
996 |
+
$customkey = implode("\n", $lines);
|
997 |
+
|
998 |
+
|
999 |
+
if ($options['visual_kw_edit']) {
|
1000 |
+
//prepare table data
|
1001 |
+
$customkey = preg_replace('/\r\n|\r/', "\n", $customkey);
|
1002 |
+
$lines = explode("\n", $customkey);
|
1003 |
+
|
1004 |
+
$data = array();
|
1005 |
+
foreach ($lines as $k => $v) {
|
1006 |
+
$parts = explode('|', $v);
|
1007 |
+
|
1008 |
+
if ($parts[0] && $parts[1]) {
|
1009 |
+
$data[$k]['words'] = $parts[0];
|
1010 |
+
$data[$k]['link'] = $parts[1];
|
1011 |
+
$data[$k]['redirect'] = $parts[2];
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
}
|
1015 |
+
|
1016 |
+
|
1017 |
+
$table = '
|
1018 |
+
Search: <input type="text" id="filter">
|
1019 |
+
<input type="button" style="float:right" id="addrowbutton" name="addrow" value="Add Keyword" class="button-primary"/><br />
|
1020 |
+
<table id="mySortable" class="tablesorter">
|
1021 |
+
<thead>
|
1022 |
+
<tr>
|
1023 |
+
<th>Keywords</th>
|
1024 |
+
<th>URL</th>
|
1025 |
+
<th>Redirect</th>
|
1026 |
+
<th>Edit</th>
|
1027 |
+
<th>Delete</th>
|
1028 |
+
</tr>
|
1029 |
+
<tr id="addrow" style="display:none;">
|
1030 |
+
<form>
|
1031 |
+
<td><input type="text" name="addword" value="" /></td>
|
1032 |
+
<td><input type="text" name="addurl" value="http://" /></td>
|
1033 |
+
<td><input type="text" name="addredir" value="" /></td>
|
1034 |
+
|
1035 |
+
<td>
|
1036 |
+
<a href="javascript:void(0);" id="saveadd">Save</a></td> <td> <a href="javascript:void(0);" id="canceladd">Cancel</a>
|
1037 |
+
</td>
|
1038 |
+
</form>
|
1039 |
+
</tr>
|
1040 |
+
</thead>
|
1041 |
+
<tbody>
|
1042 |
+
<tr class="dataline" style="display: none">
|
1043 |
+
<td class="word"></td>
|
1044 |
+
<td class="url"></td>
|
1045 |
+
<td class="redir"></td>
|
1046 |
+
|
1047 |
+
<td><a href="javascript:void(0);" class="editlink"><img alt="Edit" style="border: 0px none; margin-left: 5px;" src="' . $imgpath . '/page_edit.gif"/></a><a style="display: none;" href="javascript:void(0);" class="savelink">Save</a></td>
|
1048 |
+
<td><a href="javascript:void(0);" class="removelink"><img alt="Remove" style="border: 0px none; margin-left: 5px;" src="' . $imgpath . '/bin.gif"/></a><a style="display: none;" href="javascript:void(0);" class="cancellink">Cancel</a></td>
|
1049 |
+
</tr>
|
1050 |
+
';
|
1051 |
+
foreach ($data as $k => $v) {
|
1052 |
+
if ($v["words"] && $v["link"])
|
1053 |
+
$table .= '<tr class="dataline">
|
1054 |
+
<td class="word">' . $v["words"] . '</td>
|
1055 |
+
<td class="url">' . $v["link"] . '</td>
|
1056 |
+
<td class="redir">' . $v["redirect"] . '</td>
|
1057 |
+
|
1058 |
+
<td><a href="javascript:void(0);" class="editlink"><img alt="Edit" style="border: 0px none; margin-left: 5px;" src="' . $imgpath . '/page_edit.gif"/></a><a style="display: none;" href="javascript:void(0);" class="savelink">Save</a></td>
|
1059 |
+
<td><a href="javascript:void(0);" class="removelink"><img alt="Remove" style="border: 0px none; margin-left: 5px;" src="' . $imgpath . '/bin.gif"/></a><a style="display: none;" href="javascript:void(0);" class="cancellink">Cancel</a></td>
|
1060 |
+
</tr>
|
1061 |
+
';
|
1062 |
+
|
1063 |
+
}
|
1064 |
+
|
1065 |
+
$table .= '</tbody></table>';
|
1066 |
+
}
|
1067 |
+
//end prepare table data
|
1068 |
+
|
1069 |
+
$nonce = wp_create_nonce('seo-smart-links');
|
1070 |
+
|
1071 |
+
$dispcustom = $visual_kw_edit ? 'display: none' : '';
|
1072 |
+
$dispcustom2 = $visual_kw_edit ? '<br/><br/><a href="#" id="edit_all" />Edit custom keywords >></a>' : '';
|
1073 |
+
|
1074 |
+
echo <<<END
|
1075 |
+
|
1076 |
+
<div class="wrap" >
|
1077 |
+
<img class="logoimg" src="$imgpath/logo.png" ><h2>$this->name</h2><h3>Custom Keywords</h3>
|
1078 |
+
|
1079 |
+
<a href="admin.php?page=sml_options">Options</a> <a href="admin.php?page=sml_custom_keywords">Custom Keywords</a> <a href="admin.php?page=sml_import">Import/Export</a> <a href="admin.php?page=sml_about">About</a>
|
1080 |
+
|
1081 |
+
<div id="poststuff" style="margin-top:10px;">
|
1082 |
+
|
1083 |
+
|
1084 |
+
|
1085 |
+
<div id="mainblock" >
|
1086 |
+
|
1087 |
+
<div class="dbx-content">
|
1088 |
+
|
1089 |
+
<p>Here you can manually add extra keywords that you want to automatically link when they apprear in your posts. Use comma (or separator you specify) to separate keywords in a group. Then separate the target URL with vertical bar ('|' character). Enter new set of comma seperated keywords and URL in the new line. You can have these keywords link to any url, not only on your site. If you enter several URLs seperated with comma, plugin will randomly select one of them to link to. If you want to use redirection, add a redirection phrase after the URL, seperated by another vertical bar | character.</p>
|
1090 |
+
<p>Examples:<br />
|
1091 |
+
car, auto, automobile|http://mycarblog.com/ (links any of the keywords to mycarblog.com)<br />
|
1092 |
+
lincoln coin, lincoln piece| http://yourcoinsite1.com, http://yourcoinsite2.com, http://yourcoinsite3.com (links any of the keywords randomly to one of the urls specified)<br />
|
1093 |
+
lincoln coin, lincoln piece| http://mycoinsite.com| lincoln (links any of the keywords to mycoinsite.com using redirection via word lincoln)<br />
|
1094 |
+
</p>
|
1095 |
+
<h2>Custom keywords settings</h2>
|
1096 |
+
<form name="SEOLinks" action="$action_url" method="post" enctype="multipart/form-data">
|
1097 |
+
<input type="hidden" id="_wpnonce" name="_wpnonce" value="$nonce" />
|
1098 |
+
<input type="hidden" name="submitted" value="1" />
|
1099 |
+
<input type="checkbox" name="visual_kw_edit" $visual_kw_edit /><label for="visual_kw_edit"> Use visual keyword editor (uses Javascript interface, recommended for small keyword sets only)</label> <br>
|
1100 |
+
|
1101 |
+
|
1102 |
+
|
1103 |
+
<input type="checkbox" name="customkey_preventduplicatelink" $customkey_preventduplicatelink /><label for="customkey_preventduplicatelink"> Prevent duplicate links for grouped keywords (will link only first of the keywords found in text)</label> <br>
|
1104 |
+
<input type="checkbox" name="check_plural" $check_plural /><label for="check_plural"> Automatically check plural form of the keyword</label> <br>
|
1105 |
+
<input type="checkbox" name="trimspaces" $trimspaces /><label for="trimspaces"> Trim spaces from custom keywords</label> <br>
|
1106 |
+
Separator for custom keyword list: <input type="text" name="custom_separator" size="1" value="$custom_separator"/> Use this option if default separator (comma) is used in your keywords or links<br>
|
1107 |
+
<p>
|
1108 |
+
<input type="submit" name="Submit" value="Save Options" class="button-primary" />
|
1109 |
+
$dispcustom2
|
1110 |
+
|
1111 |
+
|
1112 |
+
|
1113 |
+
</p>
|
1114 |
+
|
1115 |
+
|
1116 |
+
<textarea name="customkey" id="customkey" rows="25" style="width:100%;$dispcustom">$customkey</textarea>
|
1117 |
+
|
1118 |
+
|
1119 |
+
<p id="updatemessage"></p>
|
1120 |
+
|
1121 |
+
$table
|
1122 |
+
|
1123 |
+
<div class="submit">
|
1124 |
+
|
1125 |
+
<input type="submit" name="Submit" value="Save Options" class="button-primary" />
|
1126 |
+
</div>
|
1127 |
+
</form>
|
1128 |
+
|
1129 |
+
|
1130 |
+
</div>
|
1131 |
+
|
1132 |
+
<div>
|
1133 |
+
|
1134 |
+
|
1135 |
+
</div>
|
1136 |
+
<br/><br/><h3> </h3>
|
1137 |
+
</div>
|
1138 |
+
|
1139 |
+
</div>
|
1140 |
+
|
1141 |
+
<h5>Another fine WordPress plugin by <a href="http://www.prelovac.com/vladimir/">Vladimir Prelovac</a></h5>
|
1142 |
+
</div>
|
1143 |
+
END;
|
1144 |
+
|
1145 |
+
}
|
1146 |
+
|
1147 |
+
|
1148 |
+
|
1149 |
+
|
1150 |
+
|
1151 |
+
function handle_options()
|
1152 |
+
{
|
1153 |
+
global $wp_version;
|
1154 |
+
$options = $this->get_options();
|
1155 |
+
|
1156 |
+
$tax = array();
|
1157 |
+
$taxout = '';
|
1158 |
+
|
1159 |
+
if (isset($_POST['submitted'])) {
|
1160 |
+
check_admin_referer('seo-smart-links');
|
1161 |
+
|
1162 |
+
|
1163 |
+
|
1164 |
+
$options['post'] = $_POST['post'];
|
1165 |
+
$options['postself'] = $_POST['postself'];
|
1166 |
+
$options['page'] = $_POST['page'];
|
1167 |
+
$options['pageself'] = $_POST['pageself'];
|
1168 |
+
$options['comment'] = $_POST['comment'];
|
1169 |
+
$options['lposts'] = $_POST['lposts'];
|
1170 |
+
$options['lpages'] = $_POST['lpages'];
|
1171 |
+
$options['lcats'] = $_POST['lcats'];
|
1172 |
+
$options['ltags'] = $_POST['ltags'];
|
1173 |
+
$options['ignore'] = $_POST['ignore'];
|
1174 |
+
$options['ignorepost'] = $_POST['ignorepost'];
|
1175 |
+
$options['maxlinks'] = (int) $_POST['maxlinks'];
|
1176 |
+
$options['maxtotallinks'] = (int) $_POST['maxtotallinks'];
|
1177 |
+
$options['maxsingle'] = (int) $_POST['maxsingle'];
|
1178 |
+
if ($options['maxsingle'] < 1)
|
1179 |
+
$options['maxsingle'] = 1;
|
1180 |
+
$options['maxsingleurl'] = (int) $_POST['maxsingleurl'];
|
1181 |
+
$options['minusage'] = (int) $_POST['minusage'];
|
1182 |
+
|
1183 |
+
$options['nofoln'] = $_POST['nofoln'];
|
1184 |
+
$options['nofolo'] = $_POST['nofolo'];
|
1185 |
+
$options['blankn'] = $_POST['blankn'];
|
1186 |
+
$options['blanko'] = $_POST['blanko'];
|
1187 |
+
$options['onlysingle'] = $_POST['onlysingle'];
|
1188 |
+
$options['casesens'] = $_POST['casesens'];
|
1189 |
+
$options['allowfeed'] = $_POST['allowfeed'];
|
1190 |
+
$options['samecat'] = $_POST['samecat'];
|
1191 |
+
$options['urltemplate'] = stripslashes(htmlspecialchars($_POST['urltemplate']));
|
1192 |
+
$options['utfsupport'] = $_POST['utfsupport'];
|
1193 |
+
$options['disable_texturize'] = $_POST['disable_texturize'];
|
1194 |
+
$options['match_slug'] = $_POST['match_slug'];
|
1195 |
+
$options['limit_posts'] = (int) $_POST['limit_posts'];
|
1196 |
+
$options['box_custom'] = $_POST['box_custom'];
|
1197 |
+
|
1198 |
+
$options['base_url'] = $_POST['base_url'];
|
1199 |
+
$options['min_length'] = (int) $_POST['min_length'];
|
1200 |
+
$options['add_instead_override'] = $_POST['add_instead_override'];
|
1201 |
+
$options['nofollow_whitelist'] = preg_replace('/\r\n|\r/', "\n", $_POST['nofollow_whitelist']);
|
1202 |
+
|
1203 |
+
$options['limit_post_order'] = $_POST['limit_posts_order'];
|
1204 |
+
$options['limit_post_sort'] = $_POST['limit_posts_sort'];
|
1205 |
+
|
1206 |
+
$options['skipdays'] = (int) $_POST['skipdays'];
|
1207 |
+
|
1208 |
+
|
1209 |
+
|
1210 |
+
|
1211 |
+
foreach ($_POST as $key => $value) {
|
1212 |
+
if (strpos($key, 'smltax_') !== FALSE)
|
1213 |
+
$tax[$key] = 'checked';
|
1214 |
+
}
|
1215 |
+
$options['tax'] = $tax;
|
1216 |
+
$options['time'] = time();
|
1217 |
+
|
1218 |
+
update_option($this->SEOLinks_DB_option, $options);
|
1219 |
+
|
1220 |
+
echo '<div class="updated fade"><p>Options saved.</p></div>';
|
1221 |
+
|
1222 |
+
|
1223 |
+
}
|
1224 |
+
|
1225 |
+
|
1226 |
+
|
1227 |
+
|
1228 |
+
$action_url = $_SERVER['REQUEST_URI'];
|
1229 |
+
|
1230 |
+
$post = $options['post'] == 'on' ? 'checked' : '';
|
1231 |
+
$postself = $options['postself'] == 'on' ? 'checked' : '';
|
1232 |
+
$page = $options['page'] == 'on' ? 'checked' : '';
|
1233 |
+
$pageself = $options['pageself'] == 'on' ? 'checked' : '';
|
1234 |
+
$comment = $options['comment'] == 'on' ? 'checked' : '';
|
1235 |
+
$lposts = $options['lposts'] == 'on' ? 'checked' : '';
|
1236 |
+
$lpages = $options['lpages'] == 'on' ? 'checked' : '';
|
1237 |
+
$lcats = $options['lcats'] == 'on' ? 'checked' : '';
|
1238 |
+
$ltags = $options['ltags'] == 'on' ? 'checked' : '';
|
1239 |
+
$ignore = $options['ignore'];
|
1240 |
+
$ignorepost = $options['ignorepost'];
|
1241 |
+
$maxlinks = $options['maxlinks'];
|
1242 |
+
$maxtotallinks = $options['maxtotallinks'];
|
1243 |
+
$maxsingle = $options['maxsingle'];
|
1244 |
+
$maxsingleurl = $options['maxsingleurl'];
|
1245 |
+
$minusage = $options['minusage'];
|
1246 |
+
|
1247 |
+
$nofoln = $options['nofoln'] == 'on' ? 'checked' : '';
|
1248 |
+
$nofolo = $options['nofolo'] == 'on' ? 'checked' : '';
|
1249 |
+
$blankn = $options['blankn'] == 'on' ? 'checked' : '';
|
1250 |
+
$blanko = $options['blanko'] == 'on' ? 'checked' : '';
|
1251 |
+
$onlysingle = $options['onlysingle'] == 'on' ? 'checked' : '';
|
1252 |
+
$casesens = $options['casesens'] == 'on' ? 'checked' : '';
|
1253 |
+
$allowfeed = $options['allowfeed'] == 'on' ? 'checked' : '';
|
1254 |
+
$samecat = $options['samecat'] == 'on' ? 'checked' : '';
|
1255 |
+
$utfsupport = $options['utfsupport'] == 'on' ? 'checked' : '';
|
1256 |
+
$disable_texturize = $options['disable_texturize'] == 'on' ? 'checked' : '';
|
1257 |
+
$match_slug = $options['match_slug'] == 'on' ? 'checked' : '';
|
1258 |
+
$limit_posts = $options['limit_posts'];
|
1259 |
+
$box_custom = $options['box_custom'] == 'on' ? 'checked' : '';
|
1260 |
+
|
1261 |
+
$base_url = $options['base_url'];
|
1262 |
+
$min_length = $options['min_length'];
|
1263 |
+
$nofollow_whitelist = stripslashes($options['nofollow_whitelist']);
|
1264 |
+
|
1265 |
+
$add_instead_override = $options['add_instead_override'] == 'on' ? 'checked' : '';
|
1266 |
+
|
1267 |
+
$tax = $options['tax'];
|
1268 |
+
|
1269 |
+
$urltemplate = esc_html($options['urltemplate']);
|
1270 |
+
|
1271 |
+
$skipdays = $options['skipdays'];
|
1272 |
+
|
1273 |
+
$limit_post_order_1 = $options['limit_post_order'] == 'title' ? 'selected="selected"' : '';
|
1274 |
+
$limit_post_order_2 = $options['limit_post_order'] == 'date' ? 'selected="selected"' : '';
|
1275 |
+
$limit_post_sort_1 = $options['limit_post_sort'] == 'asc' ? 'selected="selected"' : '';
|
1276 |
+
$limit_post_sort_2 = $options['limit_post_sort'] == 'desc' ? 'selected="selected"' : '';
|
1277 |
+
|
1278 |
+
if (!is_numeric($minusage))
|
1279 |
+
$minusage = 1;
|
1280 |
+
|
1281 |
+
|
1282 |
+
if (version_compare($wp_version, '2.7.9', '>')) {
|
1283 |
+
$args = array(
|
1284 |
+
'public' => true,
|
1285 |
+
'_builtin' => false
|
1286 |
+
|
1287 |
+
);
|
1288 |
+
$taxonomies = get_taxonomies($args, 'names');
|
1289 |
+
|
1290 |
+
if ($taxonomies) {
|
1291 |
+
foreach ($taxonomies as $taxonomy) {
|
1292 |
+
$taxout .= '<input type="checkbox" name="smltax_' . $taxonomy . '" ' . $tax['smltax_' . $taxonomy] . '/><label for="smltax_' . $taxonomy . '"> ' . ucfirst($taxonomy) . '</label> <br>';
|
1293 |
+
|
1294 |
+
}
|
1295 |
+
}
|
1296 |
+
|
1297 |
+
}
|
1298 |
+
|
1299 |
+
|
1300 |
+
$nonce = wp_create_nonce('seo-smart-links');
|
1301 |
+
|
1302 |
+
$imgpath = trailingslashit(get_option('siteurl')) . 'wp-content/plugins/' . dirname(plugin_basename(__FILE__)) . '/i';
|
1303 |
+
|
1304 |
+
|
1305 |
+
$sidebar_news = $this->sidebar_news();
|
1306 |
+
|
1307 |
+
|
1308 |
+
echo <<<END
|
1309 |
+
|
1310 |
+
<div class="wrap">
|
1311 |
+
<img class="logoimg" src="$imgpath/logo.png" ><h2>$this->name</h2><h3>Options</h3>
|
1312 |
+
<a href="admin.php?page=sml_options">Options</a> <a href="admin.php?page=sml_custom_keywords">Custom Keywords</a> <a href="admin.php?page=sml_import">Import/Export</a> <a href="admin.php?page=sml_about">About</a>
|
1313 |
+
<div id="poststuff" style="margin-top:10px;">
|
1314 |
+
|
1315 |
+
$sidebar_news
|
1316 |
+
<div id="mainblock" >
|
1317 |
+
|
1318 |
+
<div class="dbx-content">
|
1319 |
+
<form name="SEOLinks" action="$action_url" method="post">
|
1320 |
+
<input type="hidden" id="_wpnonce" name="_wpnonce" value="$nonce" />
|
1321 |
+
<input type="hidden" name="submitted" value="1" />
|
1322 |
+
|
1323 |
+
|
1324 |
+
|
1325 |
+
|
1326 |
+
<h2>Processing options</h2>
|
1327 |
+
<p>SEO Smart Links can process your posts, pages and comments in search for suitable keywords for creating links. Use the checkboxes below to select what should be processed.</p>
|
1328 |
+
<input type="checkbox" name="post" $post/><label for="post"> Posts</label>
|
1329 |
+
<ul> <input type="checkbox" name="postself" $postself/><label for="postself"> Allow post autolinking to itself</label></ul>
|
1330 |
+
<br />
|
1331 |
+
<input type="checkbox" name="page" $page/><label for="page"> Pages</label>
|
1332 |
+
<ul> <input type="checkbox" name="pageself" $pageself/><label for="pageself"> Allow page autolinking to itself</label></ul>
|
1333 |
+
<br />
|
1334 |
+
|
1335 |
+
Process only posts older than: <input type="text" name="skipdays" size="3" value="$skipdays"/> days
|
1336 |
+
<br />
|
1337 |
+
<br />
|
1338 |
+
<input type="checkbox" name="comment" $comment /><label for="comment"> Comments (WARNING: comment links are never cached, be cautious about turning this on for big websites)</label> <br>
|
1339 |
+
|
1340 |
+
|
1341 |
+
<h2>Automatic interlinking</h2>
|
1342 |
+
|
1343 |
+
<p>SEO Smart Links can check every word in your article against your existing post/page titles or category/tag name in search for a match. If a match is made the word will be linked to the given target. Select what targets should SEO Smart Links consider for automatic link creation.</p>
|
1344 |
+
<input type="checkbox" name="lposts" $lposts /><label for="lposts"> Posts</label> <br>
|
1345 |
+
<ul> <input type="checkbox" name="samecat" $samecat/><label for="samecat"> Link only to posts within the same category</label></ul>
|
1346 |
+
<ul> <input type="checkbox" name="match_slug" $match_slug/><label for="match_slug"> Check post slug match (ie. phrase 'Getting to Mars' would link to post with the slug 'getting-to-mars') </label></ul><br>
|
1347 |
+
<input type="checkbox" name="lpages" $lpages /><label for="lpages"> Pages</label> <br><br>
|
1348 |
+
<input type="checkbox" name="lcats" $lcats /><label for="lcats"> Categories</label> <br>
|
1349 |
+
<input type="checkbox" name="ltags" $ltags /><label for="ltags"> Tags</label> <br>
|
1350 |
+
$taxout
|
1351 |
+
<br>Link only if taxonomy has been used minimum <input type="text" name="minusage" size="2" value="$minusage"/> times (at least one post is using it).
|
1352 |
+
<br>Minimum length in characters for term to be considered for autolinking <input type="text" name="min_length" size="2" value="$min_length"/> (does not relate to custom keywords).
|
1353 |
+
<br><br>
|
1354 |
+
|
1355 |
+
<h2>Misc. Options</h3>
|
1356 |
+
|
1357 |
+
<p>You can choose to have SEO Smart Links work only on single posts and pages (for example not on main page or archives).</p>
|
1358 |
+
<input type="checkbox" name="onlysingle" $onlysingle /><label for="onlysingle"> Process only single posts and pages</label> <br>
|
1359 |
+
<br>
|
1360 |
+
<p>You can specify maximum number of posts to be checked as a possible automatic interlinking target. Also you can select criteria for post filtering. Keeping check limit low helps performance. Default is 500, Post title length, Ascending (meaning all of posts on the blog will be sorted from those with smallest title to largest, and first 500 will be checked as possible link targets).</p>
|
1361 |
+
Check limit: <input type="text" name="limit_posts" size="4" value="$limit_posts"/>
|
1362 |
+
order by <select name="limit_posts_order">
|
1363 |
+
<option $limit_post_order_1 value="title">Post title length</option>
|
1364 |
+
<option $limit_post_order_2 value="date">Post date</option>
|
1365 |
+
</select>
|
1366 |
+
|
1367 |
+
|
1368 |
+
<select name="limit_posts_sort">
|
1369 |
+
<option $limit_post_sort_1 value="asc">Ascending</option>
|
1370 |
+
<option $limit_post_sort_2 value="desc">Descending</option>
|
1371 |
+
</select>
|
1372 |
+
<br>
|
1373 |
+
<br>
|
1374 |
+
<p>Allow processing of RSS feeds. SEO Smart Links will embed links in all posts in your RSS feed (according to other options)</p>
|
1375 |
+
<input type="checkbox" name="allowfeed" $allowfeed /><label for="allowfeed"> Process RSS feeds</label> <br>
|
1376 |
+
<br>
|
1377 |
+
<p>Set whether matching should be case sensitive.</p>
|
1378 |
+
<input type="checkbox" name="casesens" $casesens /><label for="casesens"> Case sensitive matching</label> <br>
|
1379 |
+
<br>
|
1380 |
+
|
1381 |
+
<p>Use this option to disable wptexturize filter which can in some cases interfere with matching algorithm.</p>
|
1382 |
+
<input type="checkbox" name="disable_texturize" $disable_texturize /><label for="disable_texturize"> Disable Wordpress Texturization</label> <br>
|
1383 |
+
<br>
|
1384 |
+
<p>Check to enable UTF-8 support if your site uses non-english characters. Also helps with matching non-letter characters.</p>
|
1385 |
+
<input type="checkbox" name="utfsupport" $utfsupport /><label for="utfsupprt"> Enable UTF-8 support</label> <br>
|
1386 |
+
<br>
|
1387 |
+
|
1388 |
+
<h2>Override options per post</h2>
|
1389 |
+
<p>If the following option is checked, you will have an extra box in the write post screen for overriding default rules. If unchecked, only the global rules will apply..</p>
|
1390 |
+
<input type="checkbox" name="box_custom" $box_custom /><label for="box_custom"> Enable options in post screen</label> <br>
|
1391 |
+
|
1392 |
+
|
1393 |
+
|
1394 |
+
|
1395 |
+
<h2>Link Template</h2>
|
1396 |
+
<p>Allows you to custimize the link HTML template.</p><p>It recognizes special replacements: <em>{keyword}</em> (replaced by the matched keyword), <em>{url}</em> (replaced with the target URL) and <em>{description}</em> (replaced by post excerpt, or taxonomy description).</p>
|
1397 |
+
<input type="text" name="urltemplate" size="90" value="$urltemplate"/>
|
1398 |
+
<br>
|
1399 |
+
|
1400 |
+
<h2>Ignore Posts and Pages</h2>
|
1401 |
+
<p>You may wish to prevent SEO Smart Links from generating any links on certain posts or pages. Enter them here either by id, slug or title and separate by comma.</p>
|
1402 |
+
<input type="text" name="ignorepost" size="90" value="$ignorepost"/>
|
1403 |
+
<br>
|
1404 |
+
|
1405 |
+
<h2>Ignore keywords</h2>
|
1406 |
+
<p>You may wish to prevent certain words or phrases from becoming links. Separate them by comma. Does not exclude custom keywords.</p>
|
1407 |
+
<input type="text" name="ignore" size="90" value="$ignore"/>
|
1408 |
+
<br><br>
|
1409 |
+
|
1410 |
+
|
1411 |
+
|
1412 |
+
<h2>Limits</h2>
|
1413 |
+
<p>You can limit the maximum number of different links SEO Smart Links will generate per post. Set to 0 for no limit. </p>
|
1414 |
+
Maximum Created Links: <input type="text" name="maxlinks" size="2" value="$maxlinks"/>
|
1415 |
+
|
1416 |
+
<p>You can set the maximum number of links the page is allowed to have (original + SEO Smart Links). If the page has 4 links already and you set this option to 5, SEO Smart Links will generate only up to one link. Set to 0 for no limit. </p>
|
1417 |
+
Maximum Total Links on page: <input type="text" name="maxtotallinks" size="2" value="$maxtotallinks"/>
|
1418 |
+
|
1419 |
+
<p>You can limit the maximum number of links created with the same keyword. </p>
|
1420 |
+
Maximum Same Keyword: <input type="text" name="maxsingle" size="2" value="$maxsingle"/>
|
1421 |
+
|
1422 |
+
<p>You can limit number of same URLs the plugin will link to. Set to 0 for no limit. Will work only if Max. Same Keyword option is set to 1.</p>
|
1423 |
+
Maximum Same Target: <input type="text" name="maxsingleurl" size="2" value="$maxsingleurl"/>
|
1424 |
+
<br><br>
|
1425 |
+
|
1426 |
+
<h2>External Links</h2>
|
1427 |
+
<p>SEO Smart Links can open links to external sites in new window and add nofollow attribute to them.</p>
|
1428 |
+
|
1429 |
+
<input type="checkbox" name="blanko" $blanko /><label for="blanko"> Open in new window</label> <br>
|
1430 |
+
|
1431 |
+
<input type="checkbox" name="nofolo" $nofolo /><label for="nofolo"> Add nofollow attribute</label> <br>
|
1432 |
+
|
1433 |
+
<p>Whitelisted domains for nofollow exclusion (enter one per line, without http://)<p>
|
1434 |
+
<textarea name="nofollow_whitelist" id="nofollow_whitelist" rows="5" style="width:500px">$nofollow_whitelist</textarea>
|
1435 |
+
|
1436 |
+
<br>
|
1437 |
+
<h2>Redirection support</h2>
|
1438 |
+
<p>SEO Smart Links provides easy to use redirection support for custom keywords. Custom keyword links can be redirected through the base path entered below.</p>
|
1439 |
+
<p>Default is 'go' (redirection link would be formed as http://yoursite.com/go/word).</p>
|
1440 |
+
Redirection base path : <input type="text" name="base_url" size="10" value="$base_url"/>
|
1441 |
+
|
1442 |
+
|
1443 |
+
<br>
|
1444 |
+
|
1445 |
+
<div class="submit"><input type="submit" name="Submit" value="Update options" class="button-primary" /></div>
|
1446 |
+
</form>
|
1447 |
+
</div>
|
1448 |
+
|
1449 |
+
<br/><br/><h3> </h3>
|
1450 |
+
</div>
|
1451 |
+
|
1452 |
+
</div>
|
1453 |
+
|
1454 |
+
<h5>Another fine WordPress plugin by <a href="http://www.prelovac.com/vladimir/">Vladimir Prelovac</a></h5>
|
1455 |
+
</div>
|
1456 |
+
END;
|
1457 |
+
|
1458 |
+
|
1459 |
+
}
|
1460 |
+
|
1461 |
+
function SEOLinks_admin_menu()
|
1462 |
+
{
|
1463 |
+
$imgpath = trailingslashit(get_option('siteurl')) . 'wp-content/plugins/' . dirname(plugin_basename(__FILE__)) . '/i';
|
1464 |
+
|
1465 |
+
add_menu_page($this->name, $this->name, $this->cap, 'sml_options', array(
|
1466 |
+
&$this,
|
1467 |
+
'handle_options'
|
1468 |
+
), $imgpath . '/icon.png');
|
1469 |
+
$page_options = add_submenu_page('sml_options', $this->name . ' Options', 'Options', $this->cap, 'sml_options', array(
|
1470 |
+
&$this,
|
1471 |
+
'handle_options'
|
1472 |
+
));
|
1473 |
+
$page_ck = add_submenu_page('sml_options', $this->name . ' Custom Keywords', 'Custom Keywords', $this->cap, 'sml_custom_keywords', array(
|
1474 |
+
&$this,
|
1475 |
+
'handle_custom_keywords'
|
1476 |
+
));
|
1477 |
+
|
1478 |
+
|
1479 |
+
$page_import = add_submenu_page('sml_options', $this->name . ' Import/Export', 'Import/Export', $this->cap, 'sml_import', array(
|
1480 |
+
&$this,
|
1481 |
+
'handle_import'
|
1482 |
+
));
|
1483 |
+
|
1484 |
+
$page_about = add_submenu_page('sml_options', $this->name . ' About', 'About', $this->cap, 'sml_about', array(
|
1485 |
+
&$this,
|
1486 |
+
'handle_about'
|
1487 |
+
));
|
1488 |
+
|
1489 |
+
|
1490 |
+
add_action('admin_print_styles-' . $page_options, array(
|
1491 |
+
&$this,
|
1492 |
+
'load_script'
|
1493 |
+
));
|
1494 |
+
add_action('admin_print_styles-' . $page_ck, array(
|
1495 |
+
&$this,
|
1496 |
+
'load_script'
|
1497 |
+
));
|
1498 |
+
add_action('admin_print_styles-' . $page_import, array(
|
1499 |
+
&$this,
|
1500 |
+
'load_script'
|
1501 |
+
));
|
1502 |
+
add_action('admin_print_styles-' . $page_about, array(
|
1503 |
+
&$this,
|
1504 |
+
'load_script'
|
1505 |
+
));
|
1506 |
+
|
1507 |
+
}
|
1508 |
+
|
1509 |
+
function load_script()
|
1510 |
+
{
|
1511 |
+
$options = $this->get_options();
|
1512 |
+
$plugin_url = trailingslashit(get_bloginfo('wpurl')) . PLUGINDIR . '/' . dirname(plugin_basename(__FILE__));
|
1513 |
+
|
1514 |
+
wp_enqueue_script('ssl_files_script1', $plugin_url . '/js/tablesorter.js', array(
|
1515 |
+
'jquery',
|
1516 |
+
'jquery-form'
|
1517 |
+
));
|
1518 |
+
|
1519 |
+
wp_enqueue_script('ssl_files_script2', $plugin_url . '/js/pager.js', array(
|
1520 |
+
'jquery',
|
1521 |
+
'jquery-form'
|
1522 |
+
));
|
1523 |
+
//wp_enqueue_script('ssl_files_script3', $plugin_url.'/js/quicksearch.js', array('jquery', 'jquery-form'));
|
1524 |
+
wp_enqueue_script('ssl_files_script4', $plugin_url . '/js/filter.js', array(
|
1525 |
+
'jquery',
|
1526 |
+
'jquery-form'
|
1527 |
+
));
|
1528 |
+
wp_enqueue_script('ssl_files_script5', $plugin_url . '/js/seo-links.js', array(
|
1529 |
+
'jquery',
|
1530 |
+
'jquery-form'
|
1531 |
+
));
|
1532 |
+
wp_localize_script('ssl_files_script5', 'SEOSmartOptions', array(
|
1533 |
+
'separator' => $options['custom_separator']
|
1534 |
+
));
|
1535 |
+
|
1536 |
+
wp_enqueue_script('ssl_files_script6', $plugin_url . '/js/jquery.tablednd_0_5.js', array(
|
1537 |
+
'jquery',
|
1538 |
+
'jquery-form'
|
1539 |
+
));
|
1540 |
+
|
1541 |
+
|
1542 |
+
wp_register_style('sml_style', $plugin_url . '/sml.css');
|
1543 |
+
wp_enqueue_style('sml_style');
|
1544 |
+
}
|
1545 |
+
|
1546 |
+
|
1547 |
+
|
1548 |
+
|
1549 |
+
|
1550 |
+
function create_meta_box()
|
1551 |
+
{
|
1552 |
+
if (function_exists('add_meta_box')) {
|
1553 |
+
add_meta_box('sml_box', 'SEO Smart Links', array(
|
1554 |
+
&$this,
|
1555 |
+
'display_meta_box'
|
1556 |
+
), 'post', 'normal', 'high');
|
1557 |
+
add_meta_box('sml_box', 'SEO Smart Links', array(
|
1558 |
+
&$this,
|
1559 |
+
'display_meta_box'
|
1560 |
+
), 'page', 'normal', 'high');
|
1561 |
+
}
|
1562 |
+
}
|
1563 |
+
|
1564 |
+
function display_meta_box()
|
1565 |
+
{
|
1566 |
+
global $post, $options;
|
1567 |
+
$options = $this->get_options();
|
1568 |
+
?>
|
1569 |
+
|
1570 |
+
<div class="form-wrap">
|
1571 |
+
|
1572 |
+
<?php
|
1573 |
+
|
1574 |
+
echo '<input type="hidden" name="sml_nonce" id="sml_nonce" value="' . wp_create_nonce(plugin_basename(__FILE__)) . '" />';
|
1575 |
+
|
1576 |
+
|
1577 |
+
foreach ($this->meta_boxes as $meta_box) {
|
1578 |
+
$data = get_post_meta($post->ID, $this->key, true);
|
1579 |
+
//if ($options[$meta_box['name']]) {
|
1580 |
+
{
|
1581 |
+
?>
|
1582 |
+
|
1583 |
+
|
1584 |
+
<?php
|
1585 |
+
if ($meta_box['type'] == 'input'):
|
1586 |
+
?>
|
1587 |
+
<div class="form-field form-required">
|
1588 |
+
<label for="<?php
|
1589 |
+
echo $meta_box['name'];
|
1590 |
+
?>"><?php
|
1591 |
+
echo $meta_box['title'];
|
1592 |
+
?></label>
|
1593 |
+
<input title="<?php
|
1594 |
+
echo $meta_box['description'];
|
1595 |
+
?>" type="text" name="<?php
|
1596 |
+
echo $meta_box['name'];
|
1597 |
+
?>" value="<?php
|
1598 |
+
if (isset($data[$meta_box['name']]))
|
1599 |
+
echo htmlspecialchars($data[$meta_box['name']]);
|
1600 |
+
?>" />
|
1601 |
+
</div>
|
1602 |
+
<?php
|
1603 |
+
elseif ($meta_box['type'] == 'textarea'):
|
1604 |
+
?>
|
1605 |
+
<div class="form-field form-required">
|
1606 |
+
<label for="<?php
|
1607 |
+
echo $meta_box['name'];
|
1608 |
+
?>"><?php
|
1609 |
+
echo $meta_box['title'];
|
1610 |
+
?></label>
|
1611 |
+
|
1612 |
+
<textarea title="<?php
|
1613 |
+
echo $meta_box['description'];
|
1614 |
+
?>" name="<?php
|
1615 |
+
echo $meta_box['name'];
|
1616 |
+
?>" id="<?php
|
1617 |
+
echo $meta_box['name'];
|
1618 |
+
?>" rows=4 style="width:100%;"><?php
|
1619 |
+
if (isset($data[$meta_box['name']]))
|
1620 |
+
echo htmlspecialchars($data[$meta_box['name']]);
|
1621 |
+
?></textarea>
|
1622 |
+
</div>
|
1623 |
+
<?php
|
1624 |
+
elseif ($meta_box['type'] == 'checkbox'):
|
1625 |
+
?>
|
1626 |
+
<input style="margin-left:10px;" title="<?php
|
1627 |
+
echo $meta_box['description'];
|
1628 |
+
?>" type="checkbox" name="<?php
|
1629 |
+
echo $meta_box['name'];
|
1630 |
+
?>" id="<?php
|
1631 |
+
echo $meta_box['name'];
|
1632 |
+
?>" <?php
|
1633 |
+
if (isset($data[$meta_box['name']]) && $data[$meta_box['name']] == 'on')
|
1634 |
+
echo 'checked';
|
1635 |
+
?> >
|
1636 |
+
<?php
|
1637 |
+
echo $meta_box['title'];
|
1638 |
+
?>
|
1639 |
+
<?php
|
1640 |
+
endif;
|
1641 |
+
?>
|
1642 |
+
|
1643 |
+
|
1644 |
+
<?php
|
1645 |
+
}
|
1646 |
+
}
|
1647 |
+
?>
|
1648 |
+
|
1649 |
+
</div>
|
1650 |
+
<?php
|
1651 |
+
}
|
1652 |
+
|
1653 |
+
function save_meta_box($post_id)
|
1654 |
+
{
|
1655 |
+
global $post;
|
1656 |
+
|
1657 |
+
|
1658 |
+
foreach ($this->meta_boxes as $meta_box) {
|
1659 |
+
$data[$meta_box['name']] = $_POST[$meta_box['name']];
|
1660 |
+
}
|
1661 |
+
|
1662 |
+
|
1663 |
+
if (!wp_verify_nonce($_POST['sml_nonce'], plugin_basename(__FILE__)))
|
1664 |
+
return $post_id;
|
1665 |
+
|
1666 |
+
if (!current_user_can('edit_post', $post_id))
|
1667 |
+
return $post_id;
|
1668 |
+
|
1669 |
+
update_post_meta($post_id, $this->key, $data);
|
1670 |
+
}
|
1671 |
+
|
1672 |
+
|
1673 |
+
|
1674 |
+
}
|
1675 |
+
endif;
|
1676 |
+
|
1677 |
+
if (is_admin()) {
|
1678 |
+
if (isset($_GET['sml_csv']) && $_GET['sml_csv'] == true) {
|
1679 |
+
$now = gmdate('D, d M Y H:i:s') . ' GMT';
|
1680 |
+
|
1681 |
+
header('Content-Type: ' . _get_mime_type());
|
1682 |
+
header('Expires: ' . $now);
|
1683 |
+
|
1684 |
+
header('Content-Disposition: attachment; filename="seosmartlinks_keywords_' . gmdate('d_m_y') . '.csv"');
|
1685 |
+
header('Pragma: no-cache');
|
1686 |
+
$SEOLinks1 = new SEOLinks();
|
1687 |
+
$options = $SEOLinks1->getCustomKeywords();
|
1688 |
+
echo html_entity_decode($options);
|
1689 |
+
exit;
|
1690 |
+
|
1691 |
+
}
|
1692 |
+
if (isset($_GET['sml_options']) && $_GET['sml_options'] == true) {
|
1693 |
+
$now = gmdate('D, d M Y H:i:s') . ' GMT';
|
1694 |
+
|
1695 |
+
header('Content-Type: ' . _get_mime_type());
|
1696 |
+
header('Expires: ' . $now);
|
1697 |
+
|
1698 |
+
header('Content-Disposition: attachment; filename="seosmartlinks_config_' . gmdate('d_m_y') . '.cfg"');
|
1699 |
+
header('Pragma: no-cache');
|
1700 |
+
$SEOLinks1 = new SEOLinks();
|
1701 |
+
$options = $SEOLinks1->get_options();
|
1702 |
+
|
1703 |
+
$serialized = serialize($options);
|
1704 |
+
$encoded = base64_encode($serialized);
|
1705 |
+
|
1706 |
+
echo ($encoded);
|
1707 |
+
exit;
|
1708 |
+
|
1709 |
+
}
|
1710 |
+
}
|
1711 |
+
function _get_browser_type()
|
1712 |
+
{
|
1713 |
+
$USER_BROWSER_AGENT = "";
|
1714 |
+
|
1715 |
+
if (ereg('OPERA(/| )([0-9].[0-9]{1,2})', strtoupper($_SERVER["HTTP_USER_AGENT"]), $log_version)) {
|
1716 |
+
$USER_BROWSER_AGENT = 'OPERA';
|
1717 |
+
} else if (ereg('MSIE ([0-9].[0-9]{1,2})', strtoupper($_SERVER["HTTP_USER_AGENT"]), $log_version)) {
|
1718 |
+
$USER_BROWSER_AGENT = 'IE';
|
1719 |
+
} else if (ereg('OMNIWEB/([0-9].[0-9]{1,2})', strtoupper($_SERVER["HTTP_USER_AGENT"]), $log_version)) {
|
1720 |
+
$USER_BROWSER_AGENT = 'OMNIWEB';
|
1721 |
+
} else if (ereg('MOZILLA/([0-9].[0-9]{1,2})', strtoupper($_SERVER["HTTP_USER_AGENT"]), $log_version)) {
|
1722 |
+
$USER_BROWSER_AGENT = 'MOZILLA';
|
1723 |
+
} else if (ereg('KONQUEROR/([0-9].[0-9]{1,2})', strtoupper($_SERVER["HTTP_USER_AGENT"]), $log_version)) {
|
1724 |
+
$USER_BROWSER_AGENT = 'KONQUEROR';
|
1725 |
+
} else {
|
1726 |
+
$USER_BROWSER_AGENT = 'OTHER';
|
1727 |
+
}
|
1728 |
+
|
1729 |
+
return $USER_BROWSER_AGENT;
|
1730 |
+
}
|
1731 |
+
|
1732 |
+
function _get_mime_type()
|
1733 |
+
{
|
1734 |
+
$USER_BROWSER_AGENT = _get_browser_type();
|
1735 |
+
|
1736 |
+
$mime_type = ($USER_BROWSER_AGENT == 'IE' || $USER_BROWSER_AGENT == 'OPERA') ? 'application/octetstream' : 'application/octet-stream';
|
1737 |
+
return $mime_type;
|
1738 |
+
}
|
1739 |
+
|
1740 |
+
|
1741 |
+
if (class_exists('SEOLinks')):
|
1742 |
+
$SEOLinksPRO = new SEOLinks();
|
1743 |
+
if (isset($SEOLinks)) {
|
1744 |
+
register_activation_hook(__FILE__, array(
|
1745 |
+
&$SEOLinks,
|
1746 |
+
'install'
|
1747 |
+
));
|
1748 |
+
}
|
1749 |
+
endif;
|
1750 |
+
|
1751 |
+
|
1752 |
+
|
1753 |
?>
|
sml.css
ADDED
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* tables */
|
2 |
+
table.tablesorter thead tr .header {
|
3 |
+
|
4 |
+
font-weight:bold;
|
5 |
+
}
|
6 |
+
|
7 |
+
thead {
|
8 |
+
text-align:left;
|
9 |
+
}
|
10 |
+
|
11 |
+
table.tablesorter thead tr .headerSortUp {
|
12 |
+
|
13 |
+
}
|
14 |
+
|
15 |
+
table.tablesorter thead tr .headerSortDown {
|
16 |
+
|
17 |
+
}
|
18 |
+
|
19 |
+
table.tablesorter {
|
20 |
+
background:white;
|
21 |
+
margin-top:5px;
|
22 |
+
}
|
23 |
+
|
24 |
+
table.tablesorter thead th {
|
25 |
+
|
26 |
+
}
|
27 |
+
|
28 |
+
table.tablesorter tbody td {
|
29 |
+
|
30 |
+
}
|
31 |
+
|
32 |
+
table.tablesorter tbody tr {
|
33 |
+
color: #3D3D3D;
|
34 |
+
padding: 4px;
|
35 |
+
vertical-align: top;
|
36 |
+
}
|
37 |
+
|
38 |
+
tr.odd {
|
39 |
+
background:#F8F8F8;
|
40 |
+
}
|
41 |
+
|
42 |
+
tr.even {
|
43 |
+
background:white;
|
44 |
+
}
|
45 |
+
|
46 |
+
#mySortable {
|
47 |
+
width:100%;
|
48 |
+
border-collapse: collapse;
|
49 |
+
border-width: 0px;
|
50 |
+
clear:both;
|
51 |
+
}
|
52 |
+
|
53 |
+
#mySortable td {
|
54 |
+
border-bottom:1px solid #EEEEEE;
|
55 |
+
font-size:14px;
|
56 |
+
text-align:left;
|
57 |
+
padding:5px;
|
58 |
+
|
59 |
+
}
|
60 |
+
|
61 |
+
#mySortable td input {
|
62 |
+
width:100%;
|
63 |
+
}
|
64 |
+
|
65 |
+
#mySortable tbody tr:hover {
|
66 |
+
background:aliceBlue;
|
67 |
+
}
|
68 |
+
|
69 |
+
#updatemessage {
|
70 |
+
color:green;
|
71 |
+
height:15px;
|
72 |
+
}
|
73 |
+
|
74 |
+
#content {
|
75 |
+
margin-top:100px;
|
76 |
+
margin-left:100px;
|
77 |
+
width:800px;
|
78 |
+
}
|
79 |
+
|
80 |
+
/* tables */
|
81 |
+
table.tablesorter {
|
82 |
+
font-family:arial;
|
83 |
+
background-color: #CDCDCD;
|
84 |
+
margin:10px 0pt 15px;
|
85 |
+
font-size: 8pt;
|
86 |
+
width: 100%;
|
87 |
+
text-align: left;
|
88 |
+
}
|
89 |
+
table.tablesorter thead tr th, table.tablesorter tfoot tr th {
|
90 |
+
background-color: #e6EEEE;
|
91 |
+
border: 1px solid #FFF;
|
92 |
+
font-size: 8pt;
|
93 |
+
padding: 4px;
|
94 |
+
}
|
95 |
+
table.tablesorter thead tr .header {
|
96 |
+
background-image: url("i/bg.gif");
|
97 |
+
background-repeat: no-repeat;
|
98 |
+
background-position: center right;
|
99 |
+
cursor: pointer;
|
100 |
+
}
|
101 |
+
table.tablesorter tbody td {
|
102 |
+
color: #3D3D3D;
|
103 |
+
padding: 4px;
|
104 |
+
background-color: #FFF;
|
105 |
+
vertical-align: top;
|
106 |
+
}
|
107 |
+
table.tablesorter tbody tr.odd td {
|
108 |
+
background-color:#F0F0F6;
|
109 |
+
}
|
110 |
+
table.tablesorter thead tr .headerSortUp {
|
111 |
+
background-image: url("i/asc.gif");
|
112 |
+
}
|
113 |
+
table.tablesorter thead tr .headerSortDown {
|
114 |
+
background-image: url("i/desc.gif");
|
115 |
+
}
|
116 |
+
table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
|
117 |
+
background-color: #8dbdd8;
|
118 |
+
}
|
119 |
+
|
120 |
+
#datatable tbody td:hover {
|
121 |
+
background:aliceBlue;
|
122 |
+
}
|
123 |
+
|
124 |
+
.logoimg {
|
125 |
+
float: left;
|
126 |
+
margin-right: 7px;
|
127 |
+
margin-top: 13px;
|
128 |
+
}
|