Plugin Directory

Changeset 891455


Ignore:
Timestamp:
04/11/2014 05:02:06 PM (12 years ago)
Author:
rackforms
Message:

New functionality: detects mobile browsers and automatically enables responsive version of form.

Location:
rackforms-express/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • rackforms-express/trunk/rackforms-express.php

    r877543 r891455  
    33  Plugin Name: RackForms Express
    44  Plugin URI: http://www.rackforms.com/rackforms-express-for-wordpress.php
    5   Description: Install and Manage RackForms Express, A Feature Rich and Totally Free Form Builder For WordPress!
    6   Version: 1.0
     5  Description: Install and Manage RackForms Express, A Powerful and Totally Free Form Builder For WordPress!
     6  Version: 1.1
    77  Author: nicSoft
    88  Author URI: http://www.rackforms.com
    99 */
    1010
     11// Note we can never have open/close PHP with space, as this
    1112wp_deregister_script('jquery');
    1213
     
    887888    add_action( 'admin_enqueue_scripts', 'rackforms_enqueue' );
    888889
     890
     891
     892/*
     893  Plugin Name: RackForms iFrame Resize.
     894  Plugin URI: http://www.rackforms.com/documentation/rackforms/wordpress/index.php
     895  Description: Dynamically resizes any RackForms iFrame elements embedded in our posts when the window resizes, though in most cases this is only needed for responsive/liquid templates like the default 'Twenty Twelve', 'Twenty Eleven ', etc. This plugin also browsers sniffs and if a mobile browser is detected, automatically loads the -mobile version of our form. <strong>Important Note:</strong> Your forms must be hosted on the same domain as your WordPress install for this plugin to work!
     896  Version: 1.1
     897  Author: nicsoft
     898  Author URI: http://www.rackforms.com
     899  Disclaimer: Use at your own risk. No warranty expressed or implied is provided.
     900 */
     901
     902/*
     903  Copyright 2008-2012 nicsoft  (email : info@rackforms.com)
     904
     905  This program is free software; you can redistribute it and/or modify
     906  it under the terms of the GNU General Public License as published by
     907  the Free Software Foundation; either version 2 of the License, or
     908  (at your option) any later version.
     909
     910  This program is distributed in the hope that it will be useful,
     911  but WITHOUT ANY WARRANTY; without even the implied warranty of
     912  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     913  GNU General Public License for more details.
     914
     915  You should have received a copy of the GNU General Public License
     916  along with this program; if not, write to the Free Software
     917  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     918 */
     919
     920define('HEFO_VERSION', '1.3.9');
     921
     922$hefo_options = get_option('hefo');
     923
     924add_action('init', 'hefo_init');
     925function hefo_init() {
     926  global $hefo_options;
     927 
     928  if (get_option('hefo_version') == null) {
     929    update_option('hefo_version', HEFO_VERSION);
     930    // Patch for version 1.3.9
     931    $hefo_options['og_enabled'] = 1;
     932    update_option('hefo', $hefo_options);
     933  }
     934 
     935  if (get_option('hefo_version') != HEFO_VERSION) {
     936    update_option('hefo_version', HEFO_VERSION);
     937  }
     938 
     939}
     940
     941add_action('wp_head', 'hefo_wp_head_post', 11);
     942
     943// RackForms - Replace.
     944function hefo_wp_head_post() {
     945   
     946    //wp_enqueue_script('jquery');
     947   
     948    global $hefo_options, $wp_query, $wpdb;
     949    $buffer = '';
     950    if (is_home ()) $buffer .= hefo_replace($hefo_options['head_home']);
     951
     952    $rackforms_js_content = <<<EOF
     953
     954<script type="text/javascript">
     955
     956/**
     957 * This is freely distributable code brought to you by nicSoft, makers of RackForms.
     958 *
     959 * Code should work on almost all modern browsers, including old versions of IE.
     960 *
     961 * This code will resize an iframe (or any other element) based on window size.
     962 * Please note that by default RackForms sets absolute (pixle) sizes on elements
     963 * which means this code will not work without first changing all child elements
     964 * 'width' property to a percentage.
     965 *
     966 * USAGE
     967 *
     968 * 1. set_width and set_height control which direction we want to
     969 *    resize in.
     970 *
     971 * 2. width_offset and height_offset control the padding.
     972 */
     973 
     974var obj_name = 'rackforms-iframe'; // must match the iframe class name, defaults to rackforms-iframe
     975var set_width = true; // default true
     976var set_height = true; // default true
     977
     978var width_offset = -500; // this should be the column width the iframe sits in.
     979var height_offset = 20;
     980
     981
     982// get iframe object based on class name
     983function getObj(name){ 
     984    object = getElementsByClassName(name);
     985   
     986    this.obj = object[0];
     987    this.style = object[0].style;   
     988};
     989
     990// get window size
     991function getWinSize(){
     992    var iWidth = 0, iHeight = 0;
     993   
     994    if (document.getElementById){
     995        iWidth = window.innerWidth;
     996        iHeight = window.innerHeight;
     997    } else if (document.all){
     998        iWidth = document.body.offsetWidth;
     999        iHeight = document.body.offsetHeight;
     1000    }
     1001   
     1002    return {width:iWidth, height:iHeight};
     1003};
     1004
     1005// http://james.padolsey.com/javascript/get-document-height-cross-browser/
     1006function getDocHeight(D) {
     1007    return Math.max(
     1008        Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
     1009        Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
     1010        Math.max(D.body.clientHeight, D.documentElement.clientHeight)
     1011    );
     1012}
     1013
     1014// resize window logic
     1015function resize_id(obj) {
     1016
     1017    var _parentDocHeight = (document.height !== undefined) ? document.height : document.body.offsetHeight;
     1018    var _parentDocWidth = (document.width !== undefined) ? document.width : document.body.offsetWidth;
     1019   
     1020    var oContent = new getObj(obj);
     1021    var oWinSize = getWinSize();
     1022   
     1023    var cw = getElementsByClassName('rackforms-iframe');
     1024    cw = cw[0];
     1025   
     1026    var _docHeight = -1;
     1027   
     1028    if(cw.document !== undefined){ // IE
     1029       
     1030        // http://www.w3schools.com/jsref/prop_frame_contentdocument.asp
     1031        var y = (cw.contentWindow || cw.contentDocument);
     1032        if (y.document)
     1033            y = y.document;
     1034       
     1035        // get height
     1036        if(y.documentElement)
     1037            _docHeight = y.documentElement.scrollHeight;
     1038   
     1039    } else if(cw.contentDocument.documentElement.scrollHeight !== undefined) { // Chrome
     1040   
     1041        if(cw.contentDocument.documentElement.scrollHeight !== undefined)
     1042            _docHeight = cw.contentDocument.documentElement.scrollHeight;
     1043           
     1044    }
     1045   
     1046    var h = oWinSize.height - parseInt(oContent.obj.offsetTop,10);
     1047    var w = oWinSize.width - parseInt(oContent.obj.offsetTop,10);
     1048   
     1049    h = h - height_offset;
     1050    w = w - width_offset;
     1051   
     1052    //if (h > 0 && w > 0) { // doesn't work well with console enabled.
     1053   
     1054        if(set_height && _docHeight > 150) // must be at least 100px to avoid a FF bug where the form doesn't show on load.
     1055            oContent.style.height = _docHeight.toString() + "px";
     1056       
     1057        if(set_width)
     1058            oContent.style.width = w.toString()+"px";
     1059           
     1060    //}
     1061
     1062};
     1063
     1064/*
     1065    Developed by Robert Nyman, http://www.robertnyman.com
     1066    Code/licensing: http://code.google.com/p/getelementsbyclassname/
     1067*/ 
     1068var getElementsByClassName = function (className, tag, elm){
     1069    if (document.getElementsByClassName) {
     1070        getElementsByClassName = function (className, tag, elm) {
     1071            elm = elm || document;
     1072            var elements = elm.getElementsByClassName(className),
     1073                nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
     1074                returnElements = [],
     1075                current;
     1076            for(var i=0, il=elements.length; i<il; i+=1){
     1077                current = elements[i];
     1078                if(!nodeName || nodeName.test(current.nodeName)) {
     1079                    returnElements.push(current);
     1080                }
     1081            }
     1082            return returnElements;
     1083        };
     1084    }
     1085    else if (document.evaluate) {
     1086        getElementsByClassName = function (className, tag, elm) {
     1087            tag = tag || "*";
     1088            elm = elm || document;
     1089            var classes = className.split(" "),
     1090                classesToCheck = "",
     1091                xhtmlNamespace = "http://www.w3.org/1999/xhtml",
     1092                namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
     1093                returnElements = [],
     1094                elements,
     1095                node;
     1096            for(var j=0, jl=classes.length; j<jl; j+=1){
     1097                classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
     1098            }
     1099            try {
     1100                elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
     1101            }
     1102            catch (e) {
     1103                elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
     1104            }
     1105            while ((node = elements.iterateNext())) {
     1106                returnElements.push(node);
     1107            }
     1108            return returnElements;
     1109        };
     1110    }
     1111    else {
     1112        getElementsByClassName = function (className, tag, elm) {
     1113            tag = tag || "*";
     1114            elm = elm || document;
     1115            var classes = className.split(" "),
     1116                classesToCheck = [],
     1117                elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
     1118                current,
     1119                returnElements = [],
     1120                match;
     1121            for(var k=0, kl=classes.length; k<kl; k+=1){
     1122                classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
     1123            }
     1124            for(var l=0, ll=elements.length; l<ll; l+=1){
     1125                current = elements[l];
     1126                match = false;
     1127                for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
     1128                    match = classesToCheck[m].test(current.className);
     1129                    if (!match) {
     1130                        break;
     1131                    }
     1132                }
     1133                if (match) {
     1134                    returnElements.push(current);
     1135                }
     1136            }
     1137            return returnElements;
     1138        };
     1139    }
     1140    return getElementsByClassName(className, tag, elm);
     1141};
     1142
     1143
     1144// http://code.google.com/p/domready/
     1145// This way we do not need the entire jQuery libraries.
     1146(function(){
     1147
     1148    var DomReady = window.DomReady = {};
     1149
     1150    // Everything that has to do with properly supporting our document ready event. Brought over from the most awesome jQuery.
     1151
     1152    var userAgent = navigator.userAgent.toLowerCase();
     1153
     1154    // Figure out what browser is being used
     1155    var browser = {
     1156        version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
     1157        safari: /webkit/.test(userAgent),
     1158        opera: /opera/.test(userAgent),
     1159        msie: (/msie/.test(userAgent)) && (!/opera/.test( userAgent )),
     1160        mozilla: (/mozilla/.test(userAgent)) && (!/(compatible|webkit)/.test(userAgent))
     1161    };   
     1162
     1163    var readyBound = false;
     1164    var isReady = false;
     1165    var readyList = [];
     1166
     1167    // Handle when the DOM is ready
     1168    function domReady() {
     1169        // Make sure that the DOM is not already loaded
     1170        if(!isReady) {
     1171            // Remember that the DOM is ready
     1172            isReady = true;
     1173       
     1174            if(readyList) {
     1175                for(var fn = 0; fn < readyList.length; fn++) {
     1176                    readyList[fn].call(window, []);
     1177                }
     1178           
     1179                readyList = [];
     1180            }
     1181        }
     1182    };
     1183
     1184    // From Simon Willison. A safe way to fire onload w/o screwing up everyone else.
     1185    function addLoadEvent(func) {
     1186      var oldonload = window.onload;
     1187      if (typeof window.onload != 'function') {
     1188        window.onload = func;
     1189      } else {
     1190        window.onload = function() {
     1191          if (oldonload) {
     1192            oldonload();
     1193          }
     1194          func();
     1195        }
     1196      }
     1197    };
     1198
     1199    // does the heavy work of working through the browsers idiosyncracies (let's call them that) to hook onload.
     1200    function bindReady() {
     1201        if(readyBound) {
     1202            return;
     1203        }
     1204   
     1205        readyBound = true;
     1206
     1207        // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
     1208        if (document.addEventListener && !browser.opera) {
     1209            // Use the handy event callback
     1210            document.addEventListener("DOMContentLoaded", domReady, false);
     1211        }
     1212
     1213        // If IE is used and is not in a frame
     1214        // Continually check to see if the document is ready
     1215        if (browser.msie && window == top) (function(){
     1216            if (isReady) return;
     1217            try {
     1218                // If IE is used, use the trick by Diego Perini
     1219                // http://javascript.nwbox.com/IEContentLoaded/
     1220                document.documentElement.doScroll("left");
     1221            } catch(error) {
     1222                setTimeout(arguments.callee, 0);
     1223                return;
     1224            }
     1225            // and execute any waiting functions
     1226            domReady();
     1227        })();
     1228
     1229        if(browser.opera) {
     1230            document.addEventListener( "DOMContentLoaded", function () {
     1231                if (isReady) return;
     1232                for (var i = 0; i < document.styleSheets.length; i++)
     1233                    if (document.styleSheets[i].disabled) {
     1234                        setTimeout( arguments.callee, 0 );
     1235                        return;
     1236                    }
     1237                // and execute any waiting functions
     1238                domReady();
     1239            }, false);
     1240        }
     1241
     1242        if(browser.safari) {
     1243            var numStyles;
     1244            (function(){
     1245                if (isReady) return;
     1246                if (document.readyState != "loaded" && document.readyState != "complete") {
     1247                    setTimeout( arguments.callee, 0 );
     1248                    return;
     1249                }
     1250                if (numStyles === undefined) {
     1251                    var links = document.getElementsByTagName("link");
     1252                    for (var i=0; i < links.length; i++) {
     1253                        if(links[i].getAttribute('rel') == 'stylesheet') {
     1254                            numStyles++;
     1255                        }
     1256                    }
     1257                    var styles = document.getElementsByTagName("style");
     1258                    numStyles += styles.length;
     1259                }
     1260                if (document.styleSheets.length != numStyles) {
     1261                    setTimeout( arguments.callee, 0 );
     1262                    return;
     1263                }
     1264           
     1265                // and execute any waiting functions
     1266                domReady();
     1267            })();
     1268        }
     1269
     1270        // A fallback to window.onload, that will always work
     1271        addLoadEvent(domReady);
     1272    };
     1273
     1274    // This is the public function that people can use to hook up ready.
     1275    DomReady.ready = function(fn, args) {
     1276        // Attach the listeners
     1277        bindReady();
     1278   
     1279        // If the DOM is already ready
     1280        if (isReady) {
     1281            // Execute the function immediately
     1282            fn.call(window, []);
     1283        } else {
     1284            // Add the function to the wait list
     1285            readyList.push( function() { return fn.call(window, []); } );
     1286        }
     1287    };
     1288   
     1289    bindReady();
     1290   
     1291})();
     1292
     1293var getLocation = function(href) {
     1294    var l = document.createElement("a");
     1295    l.href = href;
     1296    return l;
     1297};
     1298
     1299/**
     1300 * Gets all related CSS rules, though will not pick up on media query blocks.
     1301 */
     1302function getCSSRule(ruleName){
     1303   
     1304    ruleName = ruleName.toLowerCase();
     1305   
     1306    foundRules = new Array();
     1307   
     1308    if (document.styleSheets) {
     1309   
     1310        for (var i = 0; i < document.styleSheets.length; i++) {
     1311           
     1312            var styleSheet = document.styleSheets[i];
     1313            var ii = 0;
     1314            var cssRule = false;
     1315            var rulesCount = -1;
     1316           
     1317            // must be same origin for FF or we throw an exception
     1318            var l = getLocation(styleSheet.href);
     1319            if(l.hostname == window.location.hostname){
     1320           
     1321                if (styleSheet.cssRules) {
     1322                    rulesCount = styleSheet.cssRules.length;
     1323                } else {
     1324                    rulesCount = styleSheet.rules.length;
     1325                }
     1326           
     1327                for (var j = 0; j < rulesCount; j++) {
     1328               
     1329                    if (styleSheet.cssRules) {
     1330                        cssRule = styleSheet.cssRules[ii];
     1331                    } else {
     1332                        cssRule = styleSheet.rules[ii];
     1333                    }
     1334                   
     1335                    if (cssRule)  {
     1336                       
     1337                        // CSSStyleRule
     1338                        if (cssRule.selectorText && cssRule.selectorText.toLowerCase() == ruleName) {
     1339                            foundRules.push(cssRule);
     1340                            ii++;
     1341                            continue;
     1342                        }
     1343                       
     1344                        // CSSMediaRule
     1345                        if (cssRule.cssRules) {
     1346
     1347                            for(var r = 0; r < cssRule.cssRules.length; r++){
     1348                           
     1349                                var cssMediaRule = cssRule.cssRules[r];
     1350                               
     1351                                if (cssMediaRule.selectorText && cssMediaRule.selectorText.toLowerCase() == ruleName) {
     1352                                    foundRules.push(cssMediaRule);
     1353                                }
     1354                           
     1355                            }
     1356                       
     1357                        } else if(cssRule.rules) {
     1358                       
     1359                            for(var r = 0; r < cssRule.rules.length; r++){
     1360                           
     1361                                var cssMediaRule = cssRule.rules[r];
     1362                               
     1363                                if (cssMediaRule.selectorText && cssMediaRule.selectorText.toLowerCase() == ruleName) {
     1364                                    foundRules.push(cssMediaRule);
     1365                                }
     1366                           
     1367                            }
     1368                       
     1369                        }
     1370
     1371                       
     1372                       
     1373                    }
     1374
     1375                    ii++;
     1376                   
     1377                }
     1378
     1379            }
     1380   
     1381        }
     1382       
     1383        return foundRules;
     1384       
     1385    }
     1386};
     1387                     
     1388// http://www.abeautifulsite.net/blog/2011/11/detecting-mobile-devices-with-javascript/
     1389var isMobile = {
     1390    Android: function() {
     1391        return navigator.userAgent.match(/Android/i);
     1392    },
     1393    BlackBerry: function() {
     1394        return navigator.userAgent.match(/BlackBerry/i);
     1395    },
     1396    iOS: function() {
     1397        return navigator.userAgent.match(/iPhone|iPad|iPod/i);
     1398    },
     1399    Opera: function() {
     1400        return navigator.userAgent.match(/Opera Mini/i);
     1401    },
     1402    Windows: function() {
     1403        return navigator.userAgent.match(/IEMobile/i);
     1404    },
     1405    any: function() {
     1406        return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
     1407    }
     1408};
     1409
     1410function isResponsive(){
     1411   
     1412    // Rules for responsive/liquid detection:
     1413    // All post content held in a div called #content.
     1414    // in 2012 we wrap #content with a div called #primary, but this has a class of .site-content, this is what has the %.
     1415    // in 2011 we wrap #content with a div called primary, but this div spans the entire page.
     1416    // in 2011 the #content div has % as a css file declaration.
     1417    // in 2010 #content has no %, and no wrapper that uses % -- it is a non-responsive template.
     1418   
     1419    // 2012
     1420    var r = getCSSRule('.site-content');
     1421    for(var t = 0; t < r.length; t++){
     1422        if(r[t].style.width.indexOf('%') != -1){
     1423            return true;
     1424        }
     1425    }
     1426   
     1427    // 2011
     1428    r = getCSSRule('#content');
     1429    for(var t = 0; t < r.length; t++){
     1430        if(r[t].style.width.indexOf('%') != -1){
     1431            return true;
     1432        }
     1433    }
     1434   
     1435    // other conditions...
     1436   
     1437    return false;
     1438   
     1439};
     1440
     1441
     1442var rf_isMobile;
     1443var rf_isResponsive;
     1444
     1445// handle onload()
     1446DomReady.ready(function() {
     1447
     1448    rf_isMobile = isMobile.any();
     1449    rf_isResponsive = isResponsive();
     1450
     1451    // only activate mobile version if a mobile device is being used (detected)
     1452    if(rf_isMobile){
     1453   
     1454        // get iframe
     1455        o = getElementsByClassName(obj_name);
     1456   
     1457        iframe = o[0];
     1458
     1459        // Set iframe to 100% width.
     1460        iframe.width = "100%";
     1461       
     1462    } else {
     1463   
     1464        // always resize iframe on page load
     1465        resize_id(obj_name);
     1466   
     1467    }
     1468   
     1469    // always enable the resize event handler
     1470    window.onresize = function() { resize_id(obj_name); };
     1471
     1472});
     1473
     1474/**
     1475 * Called From RackForms.
     1476 */
     1477function DOM_Loaded(){
     1478   
     1479    if(isMobile.any()){
     1480           
     1481        // Set main output div to 100%
     1482        jQuery('#fb-iframe').contents().find('.formboss-output-div').css({width: '100%'});
     1483
     1484        // text input
     1485        jQuery('#fb-iframe').contents().find(':text').css({width: '96%'});
     1486
     1487        // text area input
     1488        jQuery('#fb-iframe').contents().find('textarea').css({width: '96%'});
     1489
     1490        // select input
     1491        jQuery('#fb-iframe').contents().find('select').css({width: '98%'});
     1492
     1493        // field containers
     1494        jQuery('#fb-iframe').contents().find('.rackforms-field-container').css({width: '100%'});
     1495               
     1496    }
     1497   
     1498    // Always resize content on iframe content load.
     1499    resize_id(obj_name);
     1500
     1501};
     1502           
     1503</script>
     1504
     1505           
     1506           
     1507EOF;
     1508   
     1509    // replace the head content with our custom script
     1510    $buffer .= hefo_replace($rackforms_js_content);
     1511
     1512    ob_start();
     1513    eval('?>' . $buffer);
     1514    $buffer = ob_get_contents();
     1515    ob_end_clean();
     1516    echo $buffer;
     1517}
     1518
     1519function hefo_replace($buffer) {
     1520    global $hefo_options;
     1521    if (empty($buffer)) return '';
     1522    for ($i=1; $i<=5; $i++) {
     1523        $buffer = str_replace('[snippet_' . $i . ']', $hefo_options['snippet_' . $i], $buffer);
     1524    }
     1525    return $buffer;
     1526}
     1527
     1528function hefo_execute($buffer) {
     1529    if (empty($buffer)) return '';
     1530    ob_start();
     1531    eval('?>' . $buffer);
     1532    $buffer = ob_get_contents();
     1533    ob_end_clean();
     1534    return $buffer;
     1535}
    8891536?>
  • rackforms-express/trunk/readme.txt

    r885960 r891455  
    30302. Search for "RackForms Express"
    31313. Select "install now" and activate the plugin.
    32 4. Click the `RackForms` Menu item and press the `Install RackForms Express` button.
     324. Click the `RackForms` Menu item and press the Install RackForms button.
    3333
    3434The longer version:
     
    38383. Select "upload" from the links at the top, and then select the file you downloaded.
    39394. Activate the plugin once the upload completes.
    40 5. Click the `RackForms` Menu item and press the `Install RackForms Express` button.
     405. Click the `RackForms` Menu item and press the Install RackForms button.
    4141
    42 That's it!  Enjoy!
     42That's it! Enjoy!
    4343
    4444== Frequently Asked Questions ==
     
    52521. RackForms Express For WordPress Can Build Any Form Type You Need.
    53532. Collect Entries In An Automated Entry Viewer, Or Send Emails.
    54 3. Build Complete Jobs In Seconds With The Template Browser.
    5554
    5655== Changelog ==
Note: See TracChangeset for help on using the changeset viewer.