Login With Ajax - Version 2.0

Version Description

  • Made plugin widget available as multiple instances (using new 2.8 Widget API)
  • Profile login link now controllable at widget level
  • Fixed bug where shortcode only appears at beginning of posts
  • Other Small Bug fixes

=

Download this release

Release Info

Developer netweblogic
Plugin Icon 128x128 Login With Ajax
Version 2.0
Comparing to
See all releases

Code changes from version 1.3.1 to 2.0

form.js DELETED
@@ -1,632 +0,0 @@
1
- /*
2
- * jQuery Form Plugin
3
- * version: 2.18 (06-JAN-2009)
4
- * @requires jQuery v1.2.2 or later
5
- *
6
- * Examples and documentation at: http://malsup.com/jquery/form/
7
- * Dual licensed under the MIT and GPL licenses:
8
- * http://www.opensource.org/licenses/mit-license.php
9
- * http://www.gnu.org/licenses/gpl.html
10
- *
11
- * Revision: $Id: jquery.form.js 6061 2009-01-07 01:43:18Z malsup $
12
- */
13
- ;(function($) {
14
-
15
- /*
16
- Usage Note:
17
- -----------
18
- Do not use both ajaxSubmit and ajaxForm on the same form. These
19
- functions are intended to be exclusive. Use ajaxSubmit if you want
20
- to bind your own submit handler to the form. For example,
21
-
22
- $(document).ready(function() {
23
- $('#myForm').bind('submit', function() {
24
- $(this).ajaxSubmit({
25
- target: '#output'
26
- });
27
- return false; // <-- important!
28
- });
29
- });
30
-
31
- Use ajaxForm when you want the plugin to manage all the event binding
32
- for you. For example,
33
-
34
- $(document).ready(function() {
35
- $('#myForm').ajaxForm({
36
- target: '#output'
37
- });
38
- });
39
-
40
- When using ajaxForm, the ajaxSubmit function will be invoked for you
41
- at the appropriate time.
42
- */
43
-
44
- /**
45
- * ajaxSubmit() provides a mechanism for immediately submitting
46
- * an HTML form using AJAX.
47
- */
48
- $.fn.ajaxSubmit = function(options) {
49
- // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
50
- if (!this.length) {
51
- log('ajaxSubmit: skipping submit process - no element selected');
52
- return this;
53
- }
54
-
55
- if (typeof options == 'function')
56
- options = { success: options };
57
-
58
- options = $.extend({
59
- url: this.attr('action') || window.location.toString(),
60
- type: this.attr('method') || 'GET'
61
- }, options || {});
62
-
63
- // hook for manipulating the form data before it is extracted;
64
- // convenient for use with rich editors like tinyMCE or FCKEditor
65
- var veto = {};
66
- this.trigger('form-pre-serialize', [this, options, veto]);
67
- if (veto.veto) {
68
- log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
69
- return this;
70
- }
71
-
72
- // provide opportunity to alter form data before it is serialized
73
- if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
74
- log('ajaxSubmit: submit aborted via beforeSerialize callback');
75
- return this;
76
- }
77
-
78
- var a = this.formToArray(options.semantic);
79
- if (options.data) {
80
- options.extraData = options.data;
81
- for (var n in options.data) {
82
- if(options.data[n] instanceof Array) {
83
- for (var k in options.data[n])
84
- a.push( { name: n, value: options.data[n][k] } )
85
- }
86
- else
87
- a.push( { name: n, value: options.data[n] } );
88
- }
89
- }
90
-
91
- // give pre-submit callback an opportunity to abort the submit
92
- if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
93
- log('ajaxSubmit: submit aborted via beforeSubmit callback');
94
- return this;
95
- }
96
-
97
- // fire vetoable 'validate' event
98
- this.trigger('form-submit-validate', [a, this, options, veto]);
99
- if (veto.veto) {
100
- log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
101
- return this;
102
- }
103
-
104
- var q = $.param(a);
105
-
106
- if (options.type.toUpperCase() == 'GET') {
107
- options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
108
- options.data = null; // data is null for 'get'
109
- }
110
- else
111
- options.data = q; // data is the query string for 'post'
112
-
113
- var $form = this, callbacks = [];
114
- if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
115
- if (options.clearForm) callbacks.push(function() { $form.clearForm(); });
116
-
117
- // perform a load on the target only if dataType is not provided
118
- if (!options.dataType && options.target) {
119
- var oldSuccess = options.success || function(){};
120
- callbacks.push(function(data) {
121
- $(options.target).html(data).each(oldSuccess, arguments);
122
- });
123
- }
124
- else if (options.success)
125
- callbacks.push(options.success);
126
-
127
- options.success = function(data, status) {
128
- for (var i=0, max=callbacks.length; i < max; i++)
129
- callbacks[i].apply(options, [data, status, $form]);
130
- };
131
-
132
- // are there files to upload?
133
- var files = $('input:file', this).fieldValue();
134
- var found = false;
135
- for (var j=0; j < files.length; j++)
136
- if (files[j])
137
- found = true;
138
-
139
- // options.iframe allows user to force iframe mode
140
- if (options.iframe || found) {
141
- // hack to fix Safari hang (thanks to Tim Molendijk for this)
142
- // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
143
- if ($.browser.safari && options.closeKeepAlive)
144
- $.get(options.closeKeepAlive, fileUpload);
145
- else
146
- fileUpload();
147
- }
148
- else
149
- $.ajax(options);
150
-
151
- // fire 'notify' event
152
- this.trigger('form-submit-notify', [this, options]);
153
- return this;
154
-
155
-
156
- // private function for handling file uploads (hat tip to YAHOO!)
157
- function fileUpload() {
158
- var form = $form[0];
159
-
160
- if ($(':input[name=submit]', form).length) {
161
- alert('Error: Form elements must not be named "submit".');
162
- return;
163
- }
164
-
165
- var opts = $.extend({}, $.ajaxSettings, options);
166
- var s = jQuery.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts);
167
-
168
- var id = 'jqFormIO' + (new Date().getTime());
169
- var $io = $('<iframe id="' + id + '" name="' + id + '" />');
170
- var io = $io[0];
171
-
172
- if ($.browser.msie || $.browser.opera)
173
- io.src = 'javascript:false;document.write("");';
174
- $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
175
-
176
- var xhr = { // mock object
177
- aborted: 0,
178
- responseText: null,
179
- responseXML: null,
180
- status: 0,
181
- statusText: 'n/a',
182
- getAllResponseHeaders: function() {},
183
- getResponseHeader: function() {},
184
- setRequestHeader: function() {},
185
- abort: function() {
186
- this.aborted = 1;
187
- $io.attr('src','about:blank'); // abort op in progress
188
- }
189
- };
190
-
191
- var g = opts.global;
192
- // trigger ajax global events so that activity/block indicators work like normal
193
- if (g && ! $.active++) $.event.trigger("ajaxStart");
194
- if (g) $.event.trigger("ajaxSend", [xhr, opts]);
195
-
196
- if (s.beforeSend && s.beforeSend(xhr, s) === false) {
197
- s.global && jQuery.active--;
198
- return;
199
- }
200
- if (xhr.aborted)
201
- return;
202
-
203
- var cbInvoked = 0;
204
- var timedOut = 0;
205
-
206
- // add submitting element to data if we know it
207
- var sub = form.clk;
208
- if (sub) {
209
- var n = sub.name;
210
- if (n && !sub.disabled) {
211
- options.extraData = options.extraData || {};
212
- options.extraData[n] = sub.value;
213
- if (sub.type == "image") {
214
- options.extraData[name+'.x'] = form.clk_x;
215
- options.extraData[name+'.y'] = form.clk_y;
216
- }
217
- }
218
- }
219
-
220
- // take a breath so that pending repaints get some cpu time before the upload starts
221
- setTimeout(function() {
222
- // make sure form attrs are set
223
- var t = $form.attr('target'), a = $form.attr('action');
224
- $form.attr({
225
- target: id,
226
- method: 'POST',
227
- action: opts.url
228
- });
229
-
230
- // ie borks in some cases when setting encoding
231
- if (! options.skipEncodingOverride) {
232
- $form.attr({
233
- encoding: 'multipart/form-data',
234
- enctype: 'multipart/form-data'
235
- });
236
- }
237
-
238
- // support timout
239
- if (opts.timeout)
240
- setTimeout(function() { timedOut = true; cb(); }, opts.timeout);
241
-
242
- // add "extra" data to form if provided in options
243
- var extraInputs = [];
244
- try {
245
- if (options.extraData)
246
- for (var n in options.extraData)
247
- extraInputs.push(
248
- $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
249
- .appendTo(form)[0]);
250
-
251
- // add iframe to doc and submit the form
252
- $io.appendTo('body');
253
- io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
254
- form.submit();
255
- }
256
- finally {
257
- // reset attrs and remove "extra" input elements
258
- $form.attr('action', a);
259
- t ? $form.attr('target', t) : $form.removeAttr('target');
260
- $(extraInputs).remove();
261
- }
262
- }, 10);
263
-
264
- function cb() {
265
- if (cbInvoked++) return;
266
-
267
- io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
268
-
269
- var operaHack = 0;
270
- var ok = true;
271
- try {
272
- if (timedOut) throw 'timeout';
273
- // extract the server response from the iframe
274
- var data, doc;
275
-
276
- doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
277
-
278
- if (doc.body == null && !operaHack && $.browser.opera) {
279
- // In Opera 9.2.x the iframe DOM is not always traversable when
280
- // the onload callback fires so we give Opera 100ms to right itself
281
- operaHack = 1;
282
- cbInvoked--;
283
- setTimeout(cb, 100);
284
- return;
285
- }
286
-
287
- xhr.responseText = doc.body ? doc.body.innerHTML : null;
288
- xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
289
- xhr.getResponseHeader = function(header){
290
- var headers = {'content-type': opts.dataType};
291
- return headers[header];
292
- };
293
-
294
- if (opts.dataType == 'json' || opts.dataType == 'script') {
295
- var ta = doc.getElementsByTagName('textarea')[0];
296
- xhr.responseText = ta ? ta.value : xhr.responseText;
297
- }
298
- else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
299
- xhr.responseXML = toXml(xhr.responseText);
300
- }
301
- data = $.httpData(xhr, opts.dataType);
302
- }
303
- catch(e){
304
- ok = false;
305
- $.handleError(opts, xhr, 'error', e);
306
- }
307
-
308
- // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
309
- if (ok) {
310
- opts.success(data, 'success');
311
- if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
312
- }
313
- if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
314
- if (g && ! --$.active) $.event.trigger("ajaxStop");
315
- if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');
316
-
317
- // clean up
318
- setTimeout(function() {
319
- $io.remove();
320
- xhr.responseXML = null;
321
- }, 100);
322
- };
323
-
324
- function toXml(s, doc) {
325
- if (window.ActiveXObject) {
326
- doc = new ActiveXObject('Microsoft.XMLDOM');
327
- doc.async = 'false';
328
- doc.loadXML(s);
329
- }
330
- else
331
- doc = (new DOMParser()).parseFromString(s, 'text/xml');
332
- return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
333
- };
334
- };
335
- };
336
-
337
- /**
338
- * ajaxForm() provides a mechanism for fully automating form submission.
339
- *
340
- * The advantages of using this method instead of ajaxSubmit() are:
341
- *
342
- * 1: This method will include coordinates for <input type="image" /> elements (if the element
343
- * is used to submit the form).
344
- * 2. This method will include the submit element's name/value data (for the element that was
345
- * used to submit the form).
346
- * 3. This method binds the submit() method to the form for you.
347
- *
348
- * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
349
- * passes the options argument along after properly binding events for submit elements and
350
- * the form itself.
351
- */
352
- $.fn.ajaxForm = function(options) {
353
- return this.ajaxFormUnbind().bind('submit.form-plugin',function() {
354
- $(this).ajaxSubmit(options);
355
- return false;
356
- }).each(function() {
357
- // store options in hash
358
- $(":submit,input:image", this).bind('click.form-plugin',function(e) {
359
- var form = this.form;
360
- form.clk = this;
361
- if (this.type == 'image') {
362
- if (e.offsetX != undefined) {
363
- form.clk_x = e.offsetX;
364
- form.clk_y = e.offsetY;
365
- } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
366
- var offset = $(this).offset();
367
- form.clk_x = e.pageX - offset.left;
368
- form.clk_y = e.pageY - offset.top;
369
- } else {
370
- form.clk_x = e.pageX - this.offsetLeft;
371
- form.clk_y = e.pageY - this.offsetTop;
372
- }
373
- }
374
- // clear form vars
375
- setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 10);
376
- });
377
- });
378
- };
379
-
380
- // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
381
- $.fn.ajaxFormUnbind = function() {
382
- this.unbind('submit.form-plugin');
383
- return this.each(function() {
384
- $(":submit,input:image", this).unbind('click.form-plugin');
385
- });
386
-
387
- };
388
-
389
- /**
390
- * formToArray() gathers form element data into an array of objects that can
391
- * be passed to any of the following ajax functions: $.get, $.post, or load.
392
- * Each object in the array has both a 'name' and 'value' property. An example of
393
- * an array for a simple login form might be:
394
- *
395
- * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
396
- *
397
- * It is this array that is passed to pre-submit callback functions provided to the
398
- * ajaxSubmit() and ajaxForm() methods.
399
- */
400
- $.fn.formToArray = function(semantic) {
401
- var a = [];
402
- if (this.length == 0) return a;
403
-
404
- var form = this[0];
405
- var els = semantic ? form.getElementsByTagName('*') : form.elements;
406
- if (!els) return a;
407
- for(var i=0, max=els.length; i < max; i++) {
408
- var el = els[i];
409
- var n = el.name;
410
- if (!n) continue;
411
-
412
- if (semantic && form.clk && el.type == "image") {
413
- // handle image inputs on the fly when semantic == true
414
- if(!el.disabled && form.clk == el)
415
- a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
416
- continue;
417
- }
418
-
419
- var v = $.fieldValue(el, true);
420
- if (v && v.constructor == Array) {
421
- for(var j=0, jmax=v.length; j < jmax; j++)
422
- a.push({name: n, value: v[j]});
423
- }
424
- else if (v !== null && typeof v != 'undefined')
425
- a.push({name: n, value: v});
426
- }
427
-
428
- if (!semantic && form.clk) {
429
- // input type=='image' are not found in elements array! handle them here
430
- var inputs = form.getElementsByTagName("input");
431
- for(var i=0, max=inputs.length; i < max; i++) {
432
- var input = inputs[i];
433
- var n = input.name;
434
- if(n && !input.disabled && input.type == "image" && form.clk == input)
435
- a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
436
- }
437
- }
438
- return a;
439
- };
440
-
441
- /**
442
- * Serializes form data into a 'submittable' string. This method will return a string
443
- * in the format: name1=value1&amp;name2=value2
444
- */
445
- $.fn.formSerialize = function(semantic) {
446
- //hand off to jQuery.param for proper encoding
447
- return $.param(this.formToArray(semantic));
448
- };
449
-
450
- /**
451
- * Serializes all field elements in the jQuery object into a query string.
452
- * This method will return a string in the format: name1=value1&amp;name2=value2
453
- */
454
- $.fn.fieldSerialize = function(successful) {
455
- var a = [];
456
- this.each(function() {
457
- var n = this.name;
458
- if (!n) return;
459
- var v = $.fieldValue(this, successful);
460
- if (v && v.constructor == Array) {
461
- for (var i=0,max=v.length; i < max; i++)
462
- a.push({name: n, value: v[i]});
463
- }
464
- else if (v !== null && typeof v != 'undefined')
465
- a.push({name: this.name, value: v});
466
- });
467
- //hand off to jQuery.param for proper encoding
468
- return $.param(a);
469
- };
470
-
471
- /**
472
- * Returns the value(s) of the element in the matched set. For example, consider the following form:
473
- *
474
- * <form><fieldset>
475
- * <input name="A" type="text" />
476
- * <input name="A" type="text" />
477
- * <input name="B" type="checkbox" value="B1" />
478
- * <input name="B" type="checkbox" value="B2"/>
479
- * <input name="C" type="radio" value="C1" />
480
- * <input name="C" type="radio" value="C2" />
481
- * </fieldset></form>
482
- *
483
- * var v = $(':text').fieldValue();
484
- * // if no values are entered into the text inputs
485
- * v == ['','']
486
- * // if values entered into the text inputs are 'foo' and 'bar'
487
- * v == ['foo','bar']
488
- *
489
- * var v = $(':checkbox').fieldValue();
490
- * // if neither checkbox is checked
491
- * v === undefined
492
- * // if both checkboxes are checked
493
- * v == ['B1', 'B2']
494
- *
495
- * var v = $(':radio').fieldValue();
496
- * // if neither radio is checked
497
- * v === undefined
498
- * // if first radio is checked
499
- * v == ['C1']
500
- *
501
- * The successful argument controls whether or not the field element must be 'successful'
502
- * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
503
- * The default value of the successful argument is true. If this value is false the value(s)
504
- * for each element is returned.
505
- *
506
- * Note: This method *always* returns an array. If no valid value can be determined the
507
- * array will be empty, otherwise it will contain one or more values.
508
- */
509
- $.fn.fieldValue = function(successful) {
510
- for (var val=[], i=0, max=this.length; i < max; i++) {
511
- var el = this[i];
512
- var v = $.fieldValue(el, successful);
513
- if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
514
- continue;
515
- v.constructor == Array ? $.merge(val, v) : val.push(v);
516
- }
517
- return val;
518
- };
519
-
520
- /**
521
- * Returns the value of the field element.
522
- */
523
- $.fieldValue = function(el, successful) {
524
- var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
525
- if (typeof successful == 'undefined') successful = true;
526
-
527
- if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
528
- (t == 'checkbox' || t == 'radio') && !el.checked ||
529
- (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
530
- tag == 'select' && el.selectedIndex == -1))
531
- return null;
532
-
533
- if (tag == 'select') {
534
- var index = el.selectedIndex;
535
- if (index < 0) return null;
536
- var a = [], ops = el.options;
537
- var one = (t == 'select-one');
538
- var max = (one ? index+1 : ops.length);
539
- for(var i=(one ? index : 0); i < max; i++) {
540
- var op = ops[i];
541
- if (op.selected) {
542
- // extra pain for IE...
543
- var v = $.browser.msie && !(op.attributes['value'].specified) ? op.text : op.value;
544
- if (one) return v;
545
- a.push(v);
546
- }
547
- }
548
- return a;
549
- }
550
- return el.value;
551
- };
552
-
553
- /**
554
- * Clears the form data. Takes the following actions on the form's input fields:
555
- * - input text fields will have their 'value' property set to the empty string
556
- * - select elements will have their 'selectedIndex' property set to -1
557
- * - checkbox and radio inputs will have their 'checked' property set to false
558
- * - inputs of type submit, button, reset, and hidden will *not* be effected
559
- * - button elements will *not* be effected
560
- */
561
- $.fn.clearForm = function() {
562
- return this.each(function() {
563
- $('input,select,textarea', this).clearFields();
564
- });
565
- };
566
-
567
- /**
568
- * Clears the selected form elements.
569
- */
570
- $.fn.clearFields = $.fn.clearInputs = function() {
571
- return this.each(function() {
572
- var t = this.type, tag = this.tagName.toLowerCase();
573
- if (t == 'text' || t == 'password' || tag == 'textarea')
574
- this.value = '';
575
- else if (t == 'checkbox' || t == 'radio')
576
- this.checked = false;
577
- else if (tag == 'select')
578
- this.selectedIndex = -1;
579
- });
580
- };
581
-
582
- /**
583
- * Resets the form data. Causes all form elements to be reset to their original value.
584
- */
585
- $.fn.resetForm = function() {
586
- return this.each(function() {
587
- // guard against an input with the name of 'reset'
588
- // note that IE reports the reset function as an 'object'
589
- if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
590
- this.reset();
591
- });
592
- };
593
-
594
- /**
595
- * Enables or disables any matching elements.
596
- */
597
- $.fn.enable = function(b) {
598
- if (b == undefined) b = true;
599
- return this.each(function() {
600
- this.disabled = !b
601
- });
602
- };
603
-
604
- /**
605
- * Checks/unchecks any matching checkboxes or radio buttons and
606
- * selects/deselects and matching option elements.
607
- */
608
- $.fn.selected = function(select) {
609
- if (select == undefined) select = true;
610
- return this.each(function() {
611
- var t = this.type;
612
- if (t == 'checkbox' || t == 'radio')
613
- this.checked = select;
614
- else if (this.tagName.toLowerCase() == 'option') {
615
- var $sel = $(this).parent('select');
616
- if (select && $sel[0] && $sel[0].type == 'select-one') {
617
- // deselect all other options
618
- $sel.find('option').selected(false);
619
- }
620
- this.selected = select;
621
- }
622
- });
623
- };
624
-
625
- // helper fn for console logging
626
- // set $.fn.ajaxSubmit.debug to true to enable debug logging
627
- function log() {
628
- if ($.fn.ajaxSubmit.debug && window.console && window.console.log)
629
- window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,''));
630
- };
631
-
632
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
login-with-ajax-admin.php CHANGED
@@ -86,25 +86,6 @@ class LWA{
86
  <i>If you'd like to send the user to a specific URL after logout, enter it here (e.g. http://wordpress.org/)</i>
87
  </td>
88
  </tr>
89
- <tr valign="top">
90
- <td scope="row">
91
- <label>Show profile link to wp-admin?</label>
92
- </td>
93
- <td>
94
- <input type="checkbox" name="lwa_admin_link" value='1' <?= ($lwa_data['admin_link'] == '1') ? 'checked="checked"':'' ?> />
95
- <br/>
96
- <i>Checking this will show a link to their wp-admin profile in the sidebar widget when the user is logged in.</i>
97
- </td>
98
- </tr>
99
- <?
100
- //Sort out the role_login/logout arrays, in case they're empty
101
- if(!is_array($lwa_data['role_login'])){
102
- $lwa_data['role_login'] = array();
103
- }
104
- if(!is_array($lwa_data['role_logout'])){
105
- $lwa_data['role_logout'] = array();
106
- }
107
- ?>
108
  <tr valign="top">
109
  <td scope="row">
110
  <label>Role-Based Custom Login Redirects</label>
86
  <i>If you'd like to send the user to a specific URL after logout, enter it here (e.g. http://wordpress.org/)</i>
87
  </td>
88
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  <tr valign="top">
90
  <td scope="row">
91
  <label>Role-Based Custom Login Redirects</label>
login-with-ajax-widget.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class LoginWithAjaxWidget extends WP_Widget {
3
+ /** constructor */
4
+ function LoginWithAjaxWidget() {
5
+ $widget_ops = array('description' => __( "Login widget with AJAX capabilities.") );
6
+ parent::WP_Widget(false, $name = 'Login With Ajax', $widget_ops);
7
+ }
8
+
9
+ /** @see WP_Widget::widget */
10
+ function widget($args, $instance) {
11
+ global $LoginWithAjax;
12
+ $LoginWithAjax->widget($args, $instance);
13
+ }
14
+
15
+ /** @see WP_Widget::update */
16
+ function update($new_instance, $old_instance) {
17
+ return $new_instance;
18
+ }
19
+
20
+ /** @see WP_Widget::form */
21
+ function form($instance) {
22
+ $profile_link = $instance['profile_link'];
23
+ ?>
24
+ <p>
25
+ <label for="<?php echo $this->get_field_id('profile_link'); ?>"><?php _e('Show profile link?'); ?> </label>
26
+ <input id="<?php echo $this->get_field_id('profile_link'); ?>" name="<?php echo $this->get_field_name('profile_link'); ?>" type="checkbox" value="1" <?php echo ($profile_link) ? 'checked="checked"':""; ?> />
27
+ </p>
28
+ <?php
29
+ }
30
+
31
+ }
32
+ ?>
login-with-ajax.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Login With Ajax
4
  Plugin URI: http://netweblogic.com/wordpress/plugins/login-with-ajax/
5
  Description: Ajax driven login widget. Customisable from within your template folder, and advanced settings from the admin area.
6
  Author: NetWebLogic
7
- Version: 1.3.1
8
  Author URI: http://netweblogic.com/
9
  Tags: Login, Ajax, Redirect, BuddyPress, MU, WPMU, sidebar, admin, widget
10
 
@@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
25
  */
26
 
27
  include_once('login-with-ajax-admin.php');
 
28
 
29
  class LoginWithAjax {
30
 
@@ -38,7 +39,7 @@ class LoginWithAjax {
38
  //Remember the current user, in case there is a logout
39
  $this->current_user = wp_get_current_user();
40
  //Make decision on what to display
41
- if ( function_exists('register_sidebar_widget') && !isset($_GET["login-with-ajax"]) ){
42
  //Enqueue scripts
43
  wp_enqueue_script( "login-with-ajax", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/login-with-ajax.js"), array( 'jquery' ) );
44
  //Enqueue stylesheets
@@ -51,7 +52,8 @@ class LoginWithAjax {
51
  wp_enqueue_style( "login-with-ajax-css", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/widget/widget.css") );
52
  }
53
  //Register widget
54
- register_sidebar_widget('Login With Ajax', array(&$this, 'widget'));
 
55
  //Add logout/in redirection
56
  add_action('wp_logout', array(&$this, 'logoutRedirect'));
57
  add_action('wp_login', array(&$this, 'loginRedirect'));
@@ -182,13 +184,18 @@ class LoginWithAjax {
182
  /*
183
  * WIDGET OPERATIONS
184
  */
185
-
186
- // Generate the login template
187
- function widget($args = array()) {
188
- $defaultAtts = array( "is_widget" => true );
189
- $atts = shortcode_atts($defaultAtts, $atts);
190
  extract($args);
191
- $is_widget = ( $is_widget !== false && $is_widget !== "false" && $is_widget !== '0' && $widget !== 0 );
 
 
 
 
 
 
 
192
  if(is_user_logged_in()){
193
  if( file_exists(get_stylesheet_directory().'/plugins/login-with-ajax/widget_in.php') ){
194
  include(get_stylesheet_directory().'/plugins/login-with-ajax/widget_in.php');
@@ -205,13 +212,13 @@ class LoginWithAjax {
205
  }else{
206
  include('widget/widget_out.php');
207
  }
208
- }
209
  }
210
 
211
  function shortcode($atts){
212
- $defaultAtts = array( "is_widget" => false );
213
- $atts = shortcode_atts($defaultAtts, $atts);
214
- $this->widget($atts);
215
  }
216
 
217
  /*
@@ -282,14 +289,13 @@ function LoginWithAjaxInit(){
282
  }
283
 
284
  //Template Tag
285
- function login_with_ajax($atts){
286
  global $LoginWithAjax;
287
- $pairs = array( 'is_widget' => false );
288
  $atts = shortcode_parse_atts($atts);
289
- $LoginWithAjax->widget(shortcode_atts($pairs, $atts));
290
  }
291
 
292
  // Start this plugin once all other plugins are fully loaded
293
- add_action( 'init', 'LoginWithAjaxInit' );
294
 
295
  ?>
4
  Plugin URI: http://netweblogic.com/wordpress/plugins/login-with-ajax/
5
  Description: Ajax driven login widget. Customisable from within your template folder, and advanced settings from the admin area.
6
  Author: NetWebLogic
7
+ Version: 2.0
8
  Author URI: http://netweblogic.com/
9
  Tags: Login, Ajax, Redirect, BuddyPress, MU, WPMU, sidebar, admin, widget
10
 
25
  */
26
 
27
  include_once('login-with-ajax-admin.php');
28
+ include_once('login-with-ajax-widget.php');
29
 
30
  class LoginWithAjax {
31
 
39
  //Remember the current user, in case there is a logout
40
  $this->current_user = wp_get_current_user();
41
  //Make decision on what to display
42
+ if ( function_exists('register_widget') && !isset($_GET["login-with-ajax"]) ){
43
  //Enqueue scripts
44
  wp_enqueue_script( "login-with-ajax", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/login-with-ajax.js"), array( 'jquery' ) );
45
  //Enqueue stylesheets
52
  wp_enqueue_style( "login-with-ajax-css", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/widget/widget.css") );
53
  }
54
  //Register widget
55
+ //register_sidebar_widget('Login With Ajax', array(&$this, 'widget'));
56
+ register_widget("LoginWithAjaxWidget");
57
  //Add logout/in redirection
58
  add_action('wp_logout', array(&$this, 'logoutRedirect'));
59
  add_action('wp_login', array(&$this, 'loginRedirect'));
184
  /*
185
  * WIDGET OPERATIONS
186
  */
187
+
188
+ function widget($args, $instance = array() ){
189
+ //Extract widget arguments
 
 
190
  extract($args);
191
+ //Merge instance options with global options
192
+ $lwa_data = get_option('lwa_data');
193
+ $lwa_data = wp_parse_args($instance, $lwa_data);
194
+ //Deal with specific variables
195
+ $lwa_data['profile_link'] = ( $lwa_data['profile_link'] != false && $lwa_data['profile_link'] != "false" );
196
+ $lwa_data['admin_link'] = $lwa_data['profile_link']; //Backward compatabiliy for customized themes
197
+ $is_widget = ( isset($lwa_data['is_widget']) ) ? ($lwa_data['is_widget'] != false && $lwa_data['is_widget'] != "false") : true ;
198
+ //Choose the widget content to display.
199
  if(is_user_logged_in()){
200
  if( file_exists(get_stylesheet_directory().'/plugins/login-with-ajax/widget_in.php') ){
201
  include(get_stylesheet_directory().'/plugins/login-with-ajax/widget_in.php');
212
  }else{
213
  include('widget/widget_out.php');
214
  }
215
+ }
216
  }
217
 
218
  function shortcode($atts){
219
+ $defaults = array( 'is_widget' => false, 'profile_link' => false );
220
+ $atts = shortcode_atts($defaults, $atts);
221
+ $this->widget(array(), $atts );
222
  }
223
 
224
  /*
289
  }
290
 
291
  //Template Tag
292
+ function login_with_ajax($atts = ''){
293
  global $LoginWithAjax;
 
294
  $atts = shortcode_parse_atts($atts);
295
+ $LoginWithAjax->shortcode($atts);
296
  }
297
 
298
  // Start this plugin once all other plugins are fully loaded
299
+ add_action( 'widgets_init', 'LoginWithAjaxInit' );
300
 
301
  ?>
readme.txt CHANGED
@@ -1,20 +1,19 @@
1
  === Login With Ajax ===
2
-
3
  Contributors: netweblogic
4
  Tags: Login, Ajax, Redirect, BuddyPress, MU, WPMU, sidebar, admin, widget
5
  Requires at least: 2.7
6
- Tested up to: 2.8.4
7
- Stable tag: 1.3.1
8
 
9
  Add smooth ajax during login, avoid screen refreshes and choose where users get redirected to upon login/logout. Supports SSL, MU, and BuddyPress.
10
 
11
  == Description ==
12
 
13
- For sites that need user logins and would like to avoid the normal wordpress login, this plugin adds the capability of placing a login widget in the sidebar with smooth AJAX login effects.
14
 
15
  Some of the features:
16
 
17
- * Login without refreshing your screen!
18
  * Password retrieval now available within the widget.
19
  * Compatible with Wordpress, Wordpress MU and BuddyPress.
20
  * Will work with forced SSL logins.
@@ -22,27 +21,25 @@ Some of the features:
22
  * Redirect users to custom URLs on Login and Logout
23
  * Redirect users with different roles to custom URLs
24
  * shortcode and template tags available
 
 
25
 
26
- If you have any problems with the plugins, please leave a comment on the plugin page (not on the WP forums please) or at least give feedback before giving a low rating. It's considered rude to just give low ratings and nothing reason for doing so.
27
-
28
- If you find this plugin useful please show some love by adding a link on your site to the plugin page on our blog or digg our plugin page [http://netweblogic.com/wordpress/plugins/login-with-ajax/](http://netweblogic.com/wordpress/plugins/login-with-ajax/) thanks!
29
 
30
- = Important information if upgrading and you have a customized widget =
31
-
32
- If you customized the widget, two small changes were made to the default template which you should copy over if you'd like the remember password feature to work. The change requires that you add the ID attribute "LoginWithAjax_Links_Remember" to the remember password link. Also, you need to copy the new element and contents of the <form> below the first one with the ID "LoginWithAjax_Remember" and ensure you don't have another element with that ID in your template. Sorry, first and last time that will happen :)
33
 
34
  == Changelog ==
35
 
36
  = 1.1 =
37
- * Fixed JavaScript for http to https support.
38
- * Added shortcut tag login_with_ajax().
39
 
40
  = 1.11 =
41
- * Fixed regular expression issue.
42
 
43
  = 1.2 =
44
- * Fixed redirection issue.
45
- * Added link to wp-admin profile page when logged in to default widget template.
46
 
47
  = 1.3 =
48
  * Fixed widget template $before_widget... variables being used with shorttag and template tag functions
@@ -54,7 +51,13 @@ If you customized the widget, two small changes were made to the default templat
54
  * Added Shortcode
55
 
56
  = 1.3.1 =
57
- * Small bugfix on admin page if newly installed. Changes also made to the 1.3 tag.
 
 
 
 
 
 
58
 
59
 
60
  == Installation ==
@@ -71,18 +74,23 @@ If you customized the widget, two small changes were made to the default templat
71
 
72
  == Notes ==
73
 
74
- You can use the shortcode [login-with-ajax] or [lwa] and template tag login_with_ajax() :
75
 
76
- * The only option you can add there is "is_widget=true|false". By default it's set to false, if true it uses the $before_widget/$after_widget variables.
 
77
 
78
  When creating customized themes for your widget, there are a few points to consider:
79
 
80
- * Start by copying the files in the /yourpluginpath/login-with-ajax/widget/ folder to /yourthemepath/plugins/login-with-ajax/
81
  * If you have a child theme, you can place the customizations in the child or parent folder (you should probably want to put it in the child folder).
82
- * If you want to customize the login-with-ajax.js javascript, you can also copy that into the same folder above.
83
  * Unless you change the javascript, make sure you wrap your widget with an element with id="login-with-ajax" or "LoginWithAjax". If you use the $before_widget ... variables, this should be done automatically depending on your theme. I recommend you just wrap a div with id="LoginWithAjax" for fuller compatability across themes.
84
  * To force SSL, see [http://codex.wordpress.org/Administration_Over_SSL]("this page"). The plugin will automatically detect the wordpress settings.
85
 
 
 
 
 
86
 
87
  == Screenshots ==
88
 
@@ -98,5 +106,10 @@ When creating customized themes for your widget, there are a few points to consi
98
 
99
  == Frequently Asked Questions ==
100
 
101
- How do I use SSL with this plugin?
102
- To force SSL, see [http://codex.wordpress.org/Administration_Over_SSL]("this page"). The plugin will automatically detect the wordpress settings.
 
 
 
 
 
1
  === Login With Ajax ===
 
2
  Contributors: netweblogic
3
  Tags: Login, Ajax, Redirect, BuddyPress, MU, WPMU, sidebar, admin, widget
4
  Requires at least: 2.7
5
+ Tested up to: 2.8.5
6
+ Stable tag: 2.0
7
 
8
  Add smooth ajax during login, avoid screen refreshes and choose where users get redirected to upon login/logout. Supports SSL, MU, and BuddyPress.
9
 
10
  == Description ==
11
 
12
+ Login With Ajax is for sites that need user logins and would like to avoid the normal wordpress login, this plugin adds the capability of placing a login widget in the sidebar with smooth AJAX login effects.
13
 
14
  Some of the features:
15
 
16
+ * Login without refreshing your screen using AJAX calls.
17
  * Password retrieval now available within the widget.
18
  * Compatible with Wordpress, Wordpress MU and BuddyPress.
19
  * Will work with forced SSL logins.
21
  * Redirect users to custom URLs on Login and Logout
22
  * Redirect users with different roles to custom URLs
23
  * shortcode and template tags available
24
+ * Fallback mechanism, will still work on javascript-disabled browsers
25
+ * Widget specific option to show link to profile page
26
 
27
+ If you have any problems with the plugins, please visit our [http://netweblogic.com/forums/](support forums) for further information and provide some feedback first, we may be able to help. It's considered rude to just give low ratings and nothing reason for doing so.
 
 
28
 
29
+ If you find this plugin useful and would like to say thanks, a link, digg, or some other form of recognition to the plugin page on our blog would be appreciated.
 
 
30
 
31
  == Changelog ==
32
 
33
  = 1.1 =
34
+ * Fixed JavaScript for http to https support
35
+ * Added shortcut tag login_with_ajax()
36
 
37
  = 1.11 =
38
+ * Fixed regular expression issue
39
 
40
  = 1.2 =
41
+ * Fixed redirection issue
42
+ * Added link to wp-admin profile page when logged in to default widget template
43
 
44
  = 1.3 =
45
  * Fixed widget template $before_widget... variables being used with shorttag and template tag functions
51
  * Added Shortcode
52
 
53
  = 1.3.1 =
54
+ * Small bugfix on admin page if newly installed. Changes also made to the 1.3 tag
55
+
56
+ = 2.0 =
57
+ * Made plugin widget available as multiple instances (using new 2.8 Widget API)
58
+ * Profile login link now controllable at widget level
59
+ * Fixed bug where shortcode only appears at beginning of posts
60
+ * Other Small Bug fixes
61
 
62
 
63
  == Installation ==
74
 
75
  == Notes ==
76
 
77
+ You can use the shortcode [login-with-ajax] or [lwa] and template tag login_with_ajax() with these options :
78
 
79
+ * is_widget='true'|'false' - By default it's set to false, if true it uses the $before_widget/$after_widget variables.
80
+ * profile_link='true'|'false' - By default it's set to false, if true, a profile link to wp-admin appears.
81
 
82
  When creating customized themes for your widget, there are a few points to consider:
83
 
84
+ * Start by copying the contents /yourpluginpath/login-with-ajax/widget/ to /yourthemepath/plugins/login-with-ajax/
85
  * If you have a child theme, you can place the customizations in the child or parent folder (you should probably want to put it in the child folder).
86
+ * If you want to customize the login-with-ajax.js javascript, you can also copy that into the same folder above (/yourthemepath/plugins/login-with-ajax/).
87
  * Unless you change the javascript, make sure you wrap your widget with an element with id="login-with-ajax" or "LoginWithAjax". If you use the $before_widget ... variables, this should be done automatically depending on your theme. I recommend you just wrap a div with id="LoginWithAjax" for fuller compatability across themes.
88
  * To force SSL, see [http://codex.wordpress.org/Administration_Over_SSL]("this page"). The plugin will automatically detect the wordpress settings.
89
 
90
+ = Important information if upgrading from 1.2 and you have a customized widget =
91
+
92
+ If you customized the widget, two small changes were made to the default login and logout templates which you should copy over if you'd like the remember password feature to work. The change requires that you add the ID attribute "LoginWithAjax_Links_Remember" to the remember password link. Also, you need to copy the new element and contents of the <form> below the first one with the ID "LoginWithAjax_Remember" and ensure you don't have another element with that ID in your template. Sorry, first and last time that will happen :)
93
+
94
 
95
  == Screenshots ==
96
 
106
 
107
  == Frequently Asked Questions ==
108
 
109
+ = How do I use SSL with this plugin? =
110
+ Yes, see the notes section.
111
+
112
+ = Do you have a shortcode or template tag? =
113
+ Yes, see the notes section.
114
+
115
+ For further questions and answers (or to submit one yourself) go to our [http://netweblogic.com/forums/](support forums).
widget/widget.css CHANGED
@@ -12,7 +12,7 @@
12
  #LoginWithAjax_Status.confirm { color:#009900; }
13
 
14
  /*Logged In CSS*/
15
- #LoginWithAjax_Avatar { width:60px; }
16
 
17
  /*Forgotten password*/
18
  #LoginWithAjax_Remember { margin-top:5px; display:none; }
12
  #LoginWithAjax_Status.confirm { color:#009900; }
13
 
14
  /*Logged In CSS*/
15
+ #LoginWithAjax_Avatar { width:60px; padding-right:10px; }
16
 
17
  /*Forgotten password*/
18
  #LoginWithAjax_Remember { margin-top:5px; display:none; }
widget/widget_in.php CHANGED
@@ -16,7 +16,6 @@
16
  global $current_user;
17
  global $wpmu_version;
18
  get_currentuserinfo();
19
- $lwa_data = get_option('lwa_data');
20
  ?>
21
  <table cellpadding="0" cellspacing="0" width="100%">
22
  <tr>
@@ -30,7 +29,7 @@
30
  <td id="LoginWithAjax_Title">
31
  <?php
32
  //Admin URL
33
- if ( $lwa_data['admin_link'] == '1' ) {
34
  ?>
35
  <a href="<?php bloginfo('siteurl') ?>/wp-admin/profile.php"><?= strtolower(__('Profile')) ?></a><br/>
36
  <?php
@@ -38,11 +37,11 @@
38
  //Logout URL
39
  if ( function_exists( 'wp_logout_url' ) ) {
40
  ?>
41
- <a id="wp-logout" href="<?= wp_logout_url( site_url() ) ?>"><?= strtolower(__( 'Log Out' )) ?></a>
42
  <?
43
  } else {
44
  ?>
45
- <a id="wp-logout" href="<?= site_url() . '/wp-login.php?action=logout&amp;redirect_to=' . site_url() ?>"><?= strtolower(__( 'Log Out' )) ?></a>
46
  <?php
47
  }
48
  ?>
@@ -52,12 +51,12 @@
52
  foreach($bp->bp_nav as $nav_item){
53
  if($nav_item['css_id'] == 'settings'){
54
  ?>
55
- | <a href="<?= $nav_item['link'] ?>"><?= strtolower($nav_item['name']) ?></a>
56
  <?
57
  }
58
  }
59
  ?>
60
- | <a href="<?php bloginfo('siteurl') ?>/wp_admin/">blog admin</a>
61
  <?php
62
  }
63
  ?>
16
  global $current_user;
17
  global $wpmu_version;
18
  get_currentuserinfo();
 
19
  ?>
20
  <table cellpadding="0" cellspacing="0" width="100%">
21
  <tr>
29
  <td id="LoginWithAjax_Title">
30
  <?php
31
  //Admin URL
32
+ if ( $lwa_data['profile_link'] == '1' ) {
33
  ?>
34
  <a href="<?php bloginfo('siteurl') ?>/wp-admin/profile.php"><?= strtolower(__('Profile')) ?></a><br/>
35
  <?php
37
  //Logout URL
38
  if ( function_exists( 'wp_logout_url' ) ) {
39
  ?>
40
+ <a id="wp-logout" href="<?= wp_logout_url( site_url() ) ?>"><?= strtolower(__( 'Log Out' )) ?></a><br />
41
  <?
42
  } else {
43
  ?>
44
+ <a id="wp-logout" href="<?= site_url() . '/wp-login.php?action=logout&amp;redirect_to=' . site_url() ?>"><?= strtolower(__( 'Log Out' )) ?></a><br />
45
  <?php
46
  }
47
  ?>
51
  foreach($bp->bp_nav as $nav_item){
52
  if($nav_item['css_id'] == 'settings'){
53
  ?>
54
+ <a href="<?= $nav_item['link'] ?>"><?= strtolower($nav_item['name']) ?></a>
55
  <?
56
  }
57
  }
58
  ?>
59
+ <a href="<?php bloginfo('siteurl') ?>/wp_admin/">blog admin</a>
60
  <?php
61
  }
62
  ?>